influxDB+grafana 日志监控平台(Golang)
influxdb
InfluxDB 是一个开源分布式时序、事件和指标数据库。使用 Go 语言编写,无需外部依赖。其设计目标是实现分布式和水平伸缩扩展。
influxDB启动流程:
1 用docker下拉influxdb的镜像
docker pull tutum/influxdb docekr
2 Docker环境下运行influxdb
docker run -d -p 8083:8083 -p8086:8086 --expose 8090 --expose 8099 --name influxsrv tutum/influxdb
各个参数含义:
-d:容器在后台运行
-p:将容器内端口映射到宿主机端口,格式为 宿主机端口:容器内端口;
8083是influxdb的web管理工具端口
8086是influxdb的HTTP API端口
--expose:可以让容器接受外部传入的数据
--name:容器名称 最后是镜像名称+tag,镜像为tutum/influxdb,tag的值0.8.8指定了要运行的版本,默认是latest。
3 启动influxdb后,influxdb会启动一个内部的HTTP server管理工具,用户可以通过接入该web服务器来操作influxdb。
当然,也可以通过CLI即命令行的方式访问influxdb。
打开浏览器,输入http://127.0.0.1:8083,访问管理工具的主页
4 Influxdb客户端 可以参考里面例子
https://github.com/influxdata/influxdb/tree/master/client
PS. Influxdb原理详解
https://www.linuxdaxue.com/influxdb-principle.html
Grafana
Grafana 是一个开源的时序性统计和监控平台,支持例如 elasticsearch、graphite、influxdb 等众多的数据源,并以功能强大的界面编辑器著称。
官网:https://grafana.com/
grafana启动流程:
1 docker 拉取镜像
docker run -d --name=grafana -p 3000:3000 grafana/grafana
2 访问管理工具的主页
浏览器127.0.0.1:3000 , 登录 grafana的默认端口是3000,用户名和密码为 admin / admin,配置文件/etc/grafana/grafana.ini,更改配置文件后需要重启grafana。
3. 创建数据库,绑定influxdb
4. 创建一个新的面板
home —> New Dashboard —> Graph —> 点击,Edit
5 Edit中的Metrics就是构造一个SQL的查询语句
Golang打点
监控日志程序通过 influxdb 将需要的内容打点到influxdb
1.导入 github.com/influxdata/influxdb/client/v2
2.创建influxdb client
// Create a new HTTPClientc, err := client.NewHTTPClient(client.HTTPConfig{Addr: addr,Username: username,Password: password,})if err != nil {log.Fatal(err)}defer c.Close()复制代码
3.创建需要打的点的格式,类型
// Create a new point batchbp, err := client.NewBatchPoints(client.BatchPointsConfig{Database: database,Precision: precision,})if err != nil {log.Fatal(err)}复制代码
4.创建点,将点添加进influxdb数据库
// Create a point and add to batch//Tags:Path,Method,Scheme,Statustags := map[string]string{"Path": v.Path,"Method": v.Method,"Scheme": v.Scheme,"Status": v.Status,}fields := map[string]interface{}{"UpstreamTime": v.UpstreamTime,"RequestTime": v.RequestTime,"BytesSent": v.BytesSent,}pt, err := client.NewPoint("nginx_log", tags, fields, v.TimeLocal)if err != nil {log.Fatal(err)}bp.AddPoint(pt)// Write the batchif err := c.Write(bp); err != nil {log.Fatal(err)}复制代码
Golang 完整代码
imooc.log日志格式如下:
172.0.0.12 - - [02/May/2018:17:17:35 +0000] http "GET /foo?query=t HTTP/1.0" 200 2133 "-" "KeepAliveClient" "-" 1.005 1.854
172.0.0.12 - - [02/May/2018:17:17:36 +0000] http "POST /bar?query=t HTTP/1.0" 300 2133 "-" "KeepAliveClient" "-" 1.025 1.854
代码逻辑主要是 通过读取模块读取imooc.log日志文件中日志,然后通过正则表达式,一行一行解析获取数据,并通过写入模块将数据通过influxdb客户端打点,最后通过grafana去显示数据图形.
package mainimport ("bufio""fmt""github.com/influxdata/influxdb/client/v2""io""net/url""os""regexp""strconv""strings""time""flag""log""net/http""encoding/json"
)const (TypeHandleLine = 0TypeErrNum = 1TpsIntervalTime = 5
)var TypeMonitorChan = make(chan int,200)type Message struct {TimeLocal time.TimeBytesSent intPath, Method, Scheme, Status stringUpstreamTime, RequestTime float64
}//系统状态监控
type SystemInfo struct {HandleLine int `json:"handleLine"` //总处理日志行数Tps float64 `json:"tps"` //系统吞吐量ReadChanLen int `json:"readChanLen"` //read channel 长度WriterChanLen int `json:"writeChanLen"` //write channel 长度RunTime string `json:"ruanTime"` //运行总时间ErrNum int `json:"errNum"` //错误数
}type Monitor struct {startTime time.Timedata SystemInfotpsSli []inttps float64
}func (m *Monitor)start(lp *LogProcess) {go func() {for n := range TypeMonitorChan {switch n {case TypeErrNum:m.data.ErrNum += 1case TypeHandleLine:m.data.HandleLine += 1}}}()ticker := time.NewTicker(time.Second *TpsIntervalTime)go func() {for {<-ticker.Cm.tpsSli = append(m.tpsSli,m.data.HandleLine)if len(m.tpsSli) > 2 {m.tpsSli = m.tpsSli[1:]m.tps = float64(m.tpsSli[1] - m.tpsSli[0])/TpsIntervalTime}}}()http.HandleFunc("/monitor", func(writer http.ResponseWriter, request *http.Request) {m.data.RunTime = time.Now().Sub(m.startTime).String()m.data.ReadChanLen = len(lp.rc)m.data.WriterChanLen = len(lp.wc)m.data.Tps = m.tpsret ,_ := json.MarshalIndent(m.data,"","\t")io.WriteString(writer,string(ret))})http.ListenAndServe(":9193",nil)
}type Reader interface {Read(rc chan []byte)
}type Writer interface {Writer(wc chan *Message)
}type LogProcess struct {rc chan []bytewc chan *Messageread Readerwrite Writer
}type ReadFromFile struct {path string //读取文件的路径
}//读取模块
func (r *ReadFromFile) Read(rc chan []byte) {//打开文件f, err := os.Open(r.path)fmt.Println(r.path)if err != nil {panic(fmt.Sprintf("open file err :", err.Error()))}//从文件末尾开始逐行读取文件内容f.Seek(0, 2) //2,代表将指正移动到末尾rd := bufio.NewReader(f)for {line, err := rd.ReadBytes('\n') //连续读取内容知道需要'\n'结束if err == io.EOF {time.Sleep(5000 * time.Microsecond)continue} else if err != nil {panic(fmt.Sprintf("ReadBytes err :", err.Error()))}TypeMonitorChan <- TypeHandleLinerc <- line[:len(line)-1]}}type WriteToinfluxDB struct {influxDBDsn string //influx data source
}//写入模块
/**1.初始化influxdb client2. 从Write Channel中读取监控数据3. 构造数据并写入influxdb
*/
func (w *WriteToinfluxDB) Writer(wc chan *Message) {infSli := strings.Split(w.influxDBDsn, "@")addr := infSli[0]username := infSli[1]password := infSli[2]database := infSli[3]precision := infSli[4]// Create a new HTTPClientc, err := client.NewHTTPClient(client.HTTPConfig{Addr: addr,Username: username,Password: password,})if err != nil {log.Fatal(err)}defer c.Close()for v := range wc {// Create a new point batchbp, err := client.NewBatchPoints(client.BatchPointsConfig{Database: database,Precision: precision,})if err != nil {log.Fatal(err)}// Create a point and add to batch//Tags:Path,Method,Scheme,Statustags := map[string]string{"Path": v.Path,"Method": v.Method,"Scheme": v.Scheme,"Status": v.Status,}fields := map[string]interface{}{"UpstreamTime": v.UpstreamTime,"RequestTime": v.RequestTime,"BytesSent": v.BytesSent,}fmt.Println("taps:",tags)fmt.Println("fields:",fields)pt, err := client.NewPoint("nginx_log", tags, fields, v.TimeLocal)if err != nil {log.Fatal(err)}bp.AddPoint(pt)// Write the batchif err := c.Write(bp); err != nil {log.Fatal(err)}// Close client resourcesif err := c.Close(); err != nil {log.Fatal(err)}log.Println("write success")}}//解析模块
func (l *LogProcess) Process() {/**172.0.012 - - [04/Mar/2018:13:49:52 +0000] http "GET /foo?query=t HTTP/1.0" 200 2133 "-""KeepAliveClient" "-" 1.005 1.854([\d\.]+)\s+([^ \[]+)\s+([^ \[]+)\s+\[([^\]]+)\]\s+([a-z]+)\s+\"([^"]+)\"\s+(\d{3})\s+(\d+)\s+\"([^"]+)\"\s+\"(.*?)\"\s+\"([\d\.-]+)\"\s+([\d\.-]+)\s+([\d\.-]+)*/r := regexp.MustCompile(`([\d\.]+)\s+([^ \[]+)\s+([^ \[]+)\s+\[([^\]]+)\]\s+([a-z]+)\s+\"([^"]+)\"\s+(\d{3})\s+(\d+)\s+\"([^"]+)\"\s+\"(.*?)\"\s+\"([\d\.-]+)\"\s+([\d\.-]+)\s+([\d\.-]+)`)for v := range l.rc {ret := r.FindStringSubmatch(string(v))if len(ret) != 14 {TypeMonitorChan <- TypeErrNumfmt.Println("FindStringSubmatch fail:", string(v))fmt.Println(len(ret))continue}message := &Message{}//时间: [04/Mar/2018:13:49:52 +0000]loc, _ := time.LoadLocation("Asia/Shanghai")t, err := time.ParseInLocation("02/Jan/2006:15:04:05 +0000", ret[4], loc)if err != nil {TypeMonitorChan <- TypeErrNumfmt.Println("ParseInLocation fail:", err.Error(), ret[4])}message.TimeLocal = t//字符串长度: 2133byteSent, _ := strconv.Atoi(ret[8])message.BytesSent = byteSent//"GET /foo?query=t HTTP/1.0"reqSli := strings.Split(ret[6], " ")if len(reqSli) != 3 {TypeMonitorChan <- TypeErrNumfmt.Println("strings.Split fail:", ret[6])continue}message.Method = reqSli[0]u, err := url.Parse(reqSli[1])if err != nil {TypeMonitorChan <- TypeErrNumfmt.Println("url parse fail:", err)continue}message.Path = u.Path//httpmessage.Scheme = ret[5]//code: 200message.Status = ret[7]//1.005upstreamTime, _ := strconv.ParseFloat(ret[12], 64)message.UpstreamTime = upstreamTime//1.854requestTime, _ := strconv.ParseFloat(ret[13], 64)message.RequestTime = requestTime//fmt.Println(message)l.wc <- message}
}/**
分析监控需求:某个协议下的某个请求在某个请求方法的 QPS&响应时间&流量*/
func main() {var path, influDsn stringflag.StringVar(&path, "path", "./imooc.log", "read file path")flag.StringVar(&influDsn, "influxDsn", "http://127.0.01:8086@imooc@imoocpass@imooc@s", "influx data source")flag.Parse()r := &ReadFromFile{path: path,}w := &WriteToinfluxDB{influxDBDsn: influDsn,}lp := &LogProcess{rc: make(chan []byte,200),wc: make(chan *Message),read: r,write: w,}go lp.read.Read(lp.rc)for i:=1;i<2 ; i++ {go lp.Process()}for i:=1;i<4 ; i++ {go lp.write.Writer(lp.wc)}fmt.Println("begin !!!")m:= &Monitor{startTime:time.Now(),data:SystemInfo{},}m.start(lp)
}
复制代码
influxDB+grafana 日志监控平台(Golang)相关推荐
- go + influxdb + grafana 日志监控系统
docker 运行 influxdb grafana docker 启动 influxdb # 启动 docker $ sudo docker run -d -p 8083:8083 -p8086:8 ...
- JMeter 5.0 + InfluxDB + Grafana 性能测试监控平台(Windows平台)
文章目录 1. 前言 1.1 InfluxDB 和 Grafana是什么? 1.2 JMeter的历代支持变迁 1.3 这篇文章讲了什么? 2. 下载与安装 2.1 InfluxDB 安装 2.2 G ...
- anemometer mysql 500_Anemometer MySQL 慢查询日志监控平台
Anemometer 是一款开源的(慢查询)日志监控平台,当前主要用于 MySQL 的慢查询日志跟踪. Anemometer 演示地址:http://lab.fordba.com/anemometer ...
- Anemometer MySQL 【慢查询日志监控平台】(实战)
Anemometer 是一款开源的(慢查询)日志监控平台,当前主要用于 MySQL 的慢查询日志跟踪. Anemometer 演示地址:http://lab.fordba.com/anemometer ...
- 基于ELK搭建网站实时日志监控平台
基于ELK搭建网站实时日志监控平台 1 为什么要用到ELK 早在传统的单体应用时代,查看日志大都通过SSH客户端登服务器去看,使用较多的命令就是 less 或者 tail.如果服务部署了好几台,就要分 ...
- 日志监控平台搭建 关于flume Kafka Elk
最近需要搭建一套日志监控平台,参考了新浪与美团的一些东西.现在实录一下搭建与优化调整的过程 目前把这几件放在一起的文档还不够多,其中相当一部分因为elk的升级配置也已经不能用了,更多的是单机版的配置, ...
- 基于Prometheus+Grafana搭建监控平台-(2)实现监控elink服务器EIMServer
EIMServer是由北京华夏易联科技开发有限公司研发的一款可以私有部署的即时通讯服务平台E-Link,服务器是基于OSGI框架研发的java服务器程序,所以也可以通过Prometheus+Grafa ...
- 基于Prometheus+Grafana搭建监控平台-(5)实现监控Solr服务
基于Prometheus+Grafana搭建监控平台-(1)搭建基础环境,实现监控JVM 基于Prometheus+Grafana搭建监控平台-(2)实现监控elink服务器EIMServer 基于P ...
- 腾讯SNG全链路日志监控平台之构建挑战
作者丨吴树生:腾讯高级工程师,负责SNG大数据监控平台建设.近十年监控系统开发经验,具有构建基于大数据平台的海量高可用分布式监控系统研发经验. 导语:当前SNG全链路日志监控平台每日数据存储量10TB ...
最新文章
- RabbitMQ基本概念(一)-RabbitMQ的优劣势及产生背景
- 研究人员首次实现人脑实时连接互联网,攻壳社会的前奏?
- 使用DX 一些知识点整理(随时添加)
- 中国城市人口分布区域分析
- selenium3 + python - cookie定位
- java stl分解_[STL训练]寻梦-题解(Java代码)极简思路
- 计算机动画制作 教学设计,《设置动画效果》教学设计
- FIle类和递归方法的使用
- Effective C++ Notebook
- 如何用PS把背景完全扣掉,变成透明
- 利用数据细分目标客户群
- 【软件应用开发】小米便签APP维护开发
- 【Vegas原创】IPAD忘记密码重置恢复出厂设置
- 数据分析的重要性体现在哪?
- json 微信小程序 筛选_微信小程序(同城小程序)_总结二(筛选功能)
- JSP打印九九乘法表和表格
- 金融伦理学(Financial Ethcs)笔记
- Python 机器学习 | 超参数优化 黑盒(Black-Box)非凸优化技术实践
- 关系代数之专门的关系运算(选择、投影)
- unity urp 实现泰森多边形Voronoi扰动
热门文章
- ***“出更”---获取源码的***
- 案例:使用jquery的ajax load方法更新局部页面并应用NProgress库实现顶部进度条
- js基础---object对象
- C# 中对WinForm窗体中的控件快速设置TableIndex次序
- 分布式缓存之Memcache
- Serializable接口初探
- 系统要关闭,可我程序还有事要处理?
- Silverlight4.0(9) 之 分页控件轻量级的Session
- Ubuntu 16.04设置IP、网关、DNS
- 动态视频目标检测和跟踪技术(入门)