日志模块重构
<p>[toc]</p>
<h1>新老板兼容问题</h1>
<ul>
<li><em>首先 由于新版使用了自己开发的glog包,所以删掉了两个启动参数:</em></li>
</ul>
<pre><code>// "--stderrthreshold", "INFO",
// "--color", "true",</code></pre>
<ul>
<li><em>如果要继续使用elk的配置:</em></li>
</ul>
<pre><code>// env 文件中:
GRAYLOG_ADDR= // 不赋值即可
// docker-compose 文件中:
// static message game gateway 服务里的 logging 字段(跟原来一致) :
logging:
driver: "fluentd"
options:
fluentd-address: ${DOCKER_LOG_FLUENTD_HOST}:${DOCKER_LOG_FLUENTD_PORT}
# fluentd-async: "true"
tag: docker.service.gateway</code></pre>
<ul>
<li><em>如果使用graylog的配置:</em></li>
</ul>
<pre><code>// env 文件中:
GRAYLOG_ADDR=127.0.0.1:12201 // 赋值
// docker-compose 文件中:
// static message game gateway 服务里的 logging 字段(跟原来一致) :
logging:
driver: "gelf"
options:
gelf-address: udp://${GRAYLOG_ADDR}
tag: docker.service.gateway</code></pre>
<h1>日志流转图</h1>
<p><img src="https://www.showdoc.com.cn/server/api/attachment/visitfile/sign/b7708e03b59fde667dc3a914e0c4c905" alt="" />
大致解释下: 数据从 input 进入 通过各个streams以及default stream, 最终落库Index. 在streams上绑定的有告警模块(可配置多个),告警模块http回调告警服务. 告警服务负责组织消息推送到钉钉告警群.</p>
<h1>graylog使用</h1>
<p><strong>本节内容以演示为主.</strong>
<img src="https://www.showdoc.com.cn/server/api/attachment/visitfile/sign/9fb1b2a117440cf839f46dd135657a2a" alt="" /></p>
<h1>新版glog</h1>
<p><strong>原本是想改造glog包的,折腾了一天. 感觉改造别人的包很不方便. 所以就重写了glog包,包名还是glog. 提供了更方便易用的接口.</strong></p>
<ul>
<li>测试容器: docker run --log-driver=gelf --log-opt gelf-address=udp://192.168.10.35:tag=redis -p 6379:6379 --name my_redis -v /data/redis/redis.conf:/etc/redis/redis.conf -v /data/redis/data:/var/redis_data redis redis-server /etc/redis/redis.conf --appendonly yes</li>
<li>
<p>测试http curl -XPOST <a href="http://192.168.10.35:12201/gelf">http://192.168.10.35:12201/gelf</a> -p0 -d '{"short_message":"Hello there 5", "host":"example.org", "tag":"test_curl", "_foo":"bar"}'</p>
</li>
<li>查询条件语法</li>
</ul>
<pre><code>// 1 日志里面包含 目标字符串
something
// 2 日志里面包含 目标字符串中任何一个
cloud apex // 等于 cloud OR apex
// 3 目标字符串中包含空格要用引号
"cloud apex"
// 4 通配符
source:*.org
source:exam?le.org
source:exam?le.*
// 5 字段匹配
level:1 // level 的值 = 1
level:>0
level:<4
level:>=1
level:<=4
level:{400 TO 404} // 不包含 400 和 404
level:[0 TO 64} // 包含 0</code></pre>
<h2>日志等级</h2>
<p><strong>大家参考使用:</strong></p>
<table>
<thead>
<tr>
<th style="text-align: left;">等级(枚举)</th>
<th style="text-align: left;">lv</th>
<th style="text-align: left;">lv_name</th>
<th style="text-align: left;">描述&使用场景</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left;">ELL_Trace</td>
<td style="text-align: left;">0</td>
<td style="text-align: left;">TRC</td>
<td style="text-align: left;">用于记录函数调用轨迹,或者理解为比Debug级别更低的一种级别.</td>
</tr>
<tr>
<td style="text-align: left;">ELL_Debug</td>
<td style="text-align: left;">1</td>
<td style="text-align: left;">DBG</td>
<td style="text-align: left;">用于功能调试日志输出.通常用于排查问题,定位问题时使用,用完后及时删除相关日志代码</td>
</tr>
<tr>
<td style="text-align: left;">ELL_Infos</td>
<td style="text-align: left;">2</td>
<td style="text-align: left;">INF</td>
<td style="text-align: left;">用于记录更有价值的事件输出.</td>
</tr>
<tr>
<td style="text-align: left;">ELL_Warns</td>
<td style="text-align: left;">3</td>
<td style="text-align: left;">WRN</td>
<td style="text-align: left;">用户输出程序警告类日志</td>
</tr>
<tr>
<td style="text-align: left;">ELL_Error</td>
<td style="text-align: left;">4</td>
<td style="text-align: left;">ERR</td>
<td style="text-align: left;">用于记录错误类日志</td>
</tr>
<tr>
<td style="text-align: left;">ELL_Fatal</td>
<td style="text-align: left;">5</td>
<td style="text-align: left;">FAL</td>
<td style="text-align: left;">用于记录程序退出日志.遇到此级别日志,程序会自动退出.</td>
</tr>
</tbody>
</table>
<h2>日志效果</h2>
<p><strong>控制台里面的效果,颜色,格式,间隙行...</strong>
<img src="https://www.showdoc.com.cn/server/api/attachment/visitfile/sign/df100dd8ae9ab9fe3b302a469e8d4455" alt="" /></p>
<h2>日志使用(接口)</h2>
<pre><code>// import
"gddserver/internal/pkg/glog"
// 日志输出-基本版
func Trace(format string, v ...interface{}) // 格式化输出日志+默认栈基本信息
func Tracev(v ...interface{}) // 多变量输出日志+默认栈基本信息
func TraceD(depth int, format string, v ...interface{}) // 格式化输出日志+指定深度栈基本信息
func TraceDv(depth int, v ...interface{}) // 多变量输出日志+指定深度栈基本信息
func Tracef(format string, v ...interface{}) // 格式化输出日志
func Traceln(v ...interface{}) // 多变量输出日志
// 其他级别的日志接口 同理,这里就不列全了.
// 日志输出-扩展版
myModuleLogger:=glog.Field("user_id","xxxx") // 构造一个ILoger对象,带自定义的字段和值
myModuleLogger.Debug(...)
myModuleLogger.Warn(...)
myModuleLogger.Error(...)
... // 这些日志输出时都会带上user_id的k-v键值对上报给graylog. 到时候到graylog中查询的时候就可以对user_id进行分组等方便快速的查找日志了.
// ILoger 接口提供的方法:
Field(field string, val interface{}) ILoger // 相比基本版多了Field方法的扩展,也就是说可以挂多个k-v对.
// TRACE
Trace(format string, v ...interface{}) // 格式化输出日志+默认栈基本信息
Tracev(v ...interface{}) // 多变量输出日志+默认栈基本信息
TraceD(depth int, format string, v ...interface{}) // 格式化输出日志+指定深度栈基本信息
TraceDv(depth int, v ...interface{}) // 多变量输出日志+指定深度栈基本信息
// 其他级别的日志接口 同理,这里就不列全了.
// 日志输出-我想把某条日志显示在'运维监控'钉钉群里面
myAlertLogger := glog.Alert()
myAlertLogger.Debug(...) // 输出的内容就可以显示在'运维监控'里面.
</code></pre>
<h2>合并代码冲突问题.</h2>
<pre><code>新的glog包的日志输出方法跟老的glog包有一定差异,所以大家在合并代码时候可能会发生冲突或者编译报错的问题.接下来我们看如何修改问题:
1 确保你的 go.mod 里面已经不再引入 "github.com/golang/glog" 包了.
2 尝试编译让他报错,主要报错的二个方法:
- a glog.Error() 自己调整下更换为 glog.Errorv or glog.Errorln
- a glog.Info() 自己调整下更换为 glog.Errorv or glog.Errorln</code></pre>
<h1>graylog安装</h1>
<p><strong>先up一把,自动创建相关目录,然后赋予权限,然后再up一次</strong></p>
<pre><code>chmod -R 777 data_graylog_journal data_elasticsearch</code></pre>
<p><img src="https://www.showdoc.com.cn/server/api/attachment/visitfile/sign/3ff093877c281f18afee1e874ee3ed0a" alt="" /></p>
<h3>开发或者个人环境</h3>
<p><strong>docker-compose.yml</strong></p>
<pre><code class="language-yml">version: '3'
services:
mongo:
image: mongo:4.2
volumes:
- "./data_mongo:/data/db"
networks:
- graylog_net
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch-oss:7.10.2
environment:
- http.host=0.0.0.0
- transport.host=localhost
- network.host=0.0.0.0
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
volumes:
- "./data_elasticsearch:/usr/share/elasticsearch/data"
ulimits:
memlock:
soft: -1
hard: -1
deploy:
resources:
limits:
memory: 2g
networks:
- graylog_net
graylog:
image: graylog/graylog:4.2
environment:
- GRAYLOG_PASSWORD_SECRET=wVJsl0o1k7hQygMH
- GRAYLOG_ROOT_PASSWORD_SHA2=8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918
- GRAYLOG_HTTP_EXTERNAL_URI=http://192.168.0.155:9000/
- GRAYLOG_ROOT_TIMEZONE=Asia/Shanghai
entrypoint: /usr/bin/tini -- wait-for-it elasticsearch:9200 -- /docker-entrypoint.sh
volumes:
- "./data_graylog_journal:/usr/share/graylog/data/journal"
networks:
- graylog_net
restart: always
depends_on:
- mongo
- elasticsearch
ports:
# Graylog web interface and REST API
- 9000:9000
# Syslog TCP
- 1514:1514
# Syslog UDP
- 1514:1514/udp
# GELF TCP
- 12201:12201
# GELF UDP
- 12201:12201/udp
networks:
graylog_net:
driver: bridge</code></pre>
<h3>生产环境</h3>
<pre><code class="language-yml">version: '3'
services:
mongo:
image: mongo:4.2
restart: on-failure
container_name: graylog_mongo
volumes:
- "./data_mongo:/data/db"
networks:
- graylog_net
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch-oss:7.10.2
restart: on-failure
container_name: graylog_es
volumes:
- "./data_elasticsearch:/usr/share/elasticsearch/data"
environment:
- http.host=0.0.0.0
- transport.host=localhost
- network.host=0.0.0.0
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ulimits:
memlock:
soft: -1
hard: -1
deploy:
resources:
limits:
memory: 4g
networks:
- graylog_net
graylog:
image: graylog/graylog:4.2
restart: on-failure
container_name: graylog_main
volumes:
- "./data_graylog_journal:/usr/share/graylog/data/journal"
environment:
- GRAYLOG_PASSWORD_SECRET=wVJsl0o1k7hQygMH
- GRAYLOG_ROOT_PASSWORD_SHA2=8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918
- GRAYLOG_HTTP_EXTERNAL_URI=http://192.168.1.191:9000/
- GRAYLOG_ROOT_TIMEZONE=Asia/Shanghai
entrypoint: /usr/bin/tini -- wait-for-it elasticsearch:9200 -- /docker-entrypoint.sh
networks:
- graylog_net
depends_on:
- mongo
- elasticsearch
ports:
# Graylog web interface and REST API
- 9000:9000
# Syslog1 TCP
- 5101:5101
# Syslog1 UDP
- 5101:5101/udp
# Syslog2 TCP
- 5102:5102
# Syslog2 UDP
- 5102:5102/udp
# GELF Http1
- 5201:5201
# GELF Http1
- 5202:5202
# GELF TCP1
- 5301:5301
# GELF UDP1
- 5301:5301/udp
# GELF TCP2
- 5302:5302
# GELF UDP2
- 5302:5302/udp
# GELF TCP3
- 5303:5303
# GELF UDP3
- 5303:5303/udp
# GELF TCP4
- 5304:5304
# GELF UDP4
- 5304:5304/udp
# GELF TCP5
- 5305:5305
# GELF UDP5
- 5305:5305/udp
networks:
graylog_net:
driver: bridge</code></pre>
<h1>告警服务安装</h1>
<pre><code>docker run -d -p 3838:3838 --name gdd_alert cloudapex/u.alert:1.0</code></pre>
<h1>告警事件规划</h1>
<p><img src="https://www.showdoc.com.cn/server/api/attachment/visitfile/sign/11c1646634a018731b921a4686bae267" alt="" /></p>