docker 运行 influxdb grafana

docker 启动 influxdb

# 启动 docker
$ sudo docker run -d -p 8083:8083 -p8086:8086 --expose 8090 --expose 8099 --name indb -v /data/dockerdata/influxdb:/var/lib/influxdb docker.io/influxdb
# 创建数据库和用户
$ sudo docker exec -it indb /bin/bash
> create User nginx with password '123456'
> GRANT ALL PRIVILEGES ON monitor TO nginx
> CREATE RETENTION POLICY "monitor_retention" ON "monitor" DURATION 30d REPLICATION 1 DEFAULT   

docker 启动 grafana

# grafana 5.10 后创建数据卷需要传入权限, 使用 nginx 反代需要设置 server root
# 使用 link 连接其他容器,访问该容器内容直接使用 容器名称
sudo docker run -d \-p 3000:3000 \-e INFLUXDB_HOST=localhost \-e INFLUXDB_PORT=8086 \-e INFLUXDB_NAME=monitor \-e INFLUXDB_USER=nginx \ -e INFLUXDB_PASS=123456 \-e "GF_SECURITY_ADMIN_PASSWORD=123456" \-e "GF_SERVER_ROOT_URL=https://www.amoyiki.com/monitor/"  \-v /data/dockerdata/grafana:/var/lib/grafana \--link indb:indb \--user root  \--name grafana \grafana/grafana

配置 grafana 数据源

PS Access 使用 Server 即可

go 项目

编写 go 代码

本代码完全照搬慕课网视频教程

package mainimport ("bufio""encoding/json""flag""fmt""github.com/influxdata/influxdb/client/v2""io""log""net/http""net/url""os""regexp""strconv""strings""time"
)type Reader interface {Read(rc chan []byte)
}type Writer interface {Write(wc chan *Message)
}type LogProcess struct {rc chan []byte // 读取 -> 解析wc chan *Message // 解析 -> 写入reader Readerwriter Writer
}type Message struct {TimeLocal time.TimeByteSent intPath, Method, Scheme, Status stringRequestTime float64
}type SystemInfo struct {HandleLine int `json: "handleLine"` // 总日志行数Tps float64 `json: "tps"` // 系统吞吐量ReadChanLen int `json: "readChanLen"` // read channel 长度WriteChanLen int `json: "wirteChanLen"` // wirte channel 长度RunTime string `json:"runTime"` // 总运行时间ErrNum int `json:"errTime"` // 错误数
}const (TypeHandleLine = 0TypeErrNum = 1
)var TypeMonitorChan = make(chan int, 200)type Monitor struct {startTime time.Timedata SystemInfotpsSlic []int
}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 * 5)go func() {for {<-ticker.Cm.tpsSlic = append(m.tpsSlic, m.data.HandleLine)if len(m.tpsSlic) > 2 {m.tpsSlic = m.tpsSlic[1:]}}}()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.WriteChanLen = len(lp.wc)if len(m.tpsSlic) >= 2 {m.data.Tps = float64(m.tpsSlic[1]-m.tpsSlic[0]) / 5}ret, _ := json.MarshalIndent(m.data, "", "\t")io.WriteString(writer, string(ret))})http.ListenAndServe(":9999", nil)
}type ReadFromFile struct {path string // 读取文件的地址
}func (r *ReadFromFile) Read(rc chan []byte) {// 打开文件f, err := os.Open(r.path)if err != nil {panic(fmt.Sprintln("open file error: %s", err.Error()))}// 从文件末尾逐行读取文件内容f.Seek(0, 2)rd := bufio.NewReader(f)for {line, err := rd.ReadBytes('\n')if err == io.EOF {time.Sleep(500 * time.Millisecond)continue} else if err != nil {panic(fmt.Sprintln("read file error: %s", err.Error()))}TypeMonitorChan <- TypeHandleLinerc <- line[:len(line)-1]}}type WriteToInfluxDB struct {influxDBsn string
}func (w *WriteToInfluxDB) Write(wc chan *Message) {// 写入模块infSli := strings.Split(w.influxDBsn, "&")// Create a new HTTPClientc, err := client.NewHTTPClient(client.HTTPConfig{Addr: infSli[0],Username: infSli[1],Password: infSli[2],})if err != nil {log.Fatal(err)}defer c.Close()// Create a new point batchbp, err := client.NewBatchPoints(client.BatchPointsConfig{Database: infSli[3],Precision: infSli[4],})if err != nil {log.Fatal(err)}for v := range wc {// Create a point and add to batchtags := map[string]string{"Path": v.Path, "Method": v.Method, "Scheme": v.Scheme,"Status": v.Status}fields := map[string]interface{}{"RequestTime": v.RequestTime,"BytesSent": v.ByteSent,}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 influxdb success ...")}
}
func (l *LogProcess) Process() {// 解析模块/**139.199.10.130 - - [12/Dec/2018:16:02:34 +0800] "POST /wp-cron.php HTTP/1.1" 200 0 "https://xxx.exmple.com/wp-cron.php?doing_wp_cron=1544601753.9868400096893310546875" "WordPress/4.9.8; https://xxx.exmple.com" "-" "0.058"([\d\.]+)\s+([^ \[]+)\s+([^ \[]+)\s+\[([^\]]+)\]\s+\"([^"]+)\"\s+(\d{3})\s+(\d+)\s+\"([^"]+)\"\s+\"(.*?)\"\s+\"([^"]+)\"\s+\"([^"]+)\"*/r := regexp.MustCompile(`([\d\.]+)\s+([^ \[]+)\s+([^ \[]+)\s+\[([^\]]+)\]\s+\"([^"]+)\"\s+(\d{3})\s+(\d+)\s+\"([^"]+)\"\s+\"(.*?)\"\s+\"([^"]+)\"\s+\"([^"]+)\"`)loc, _ := time.LoadLocation("Asia/Shanghai")for v := range l.rc {ret := r.FindStringSubmatch(string(v))if len(ret) != 14 {TypeMonitorChan <- TypeErrNumlog.Println("FindStringSubmatch fail: ", string(v))continue}message := &Message{}t, err := time.ParseInLocation("02/Jan/2006:15:04:05 +0000", ret[4], loc)if err != nil {TypeMonitorChan <- TypeErrNumlog.Println("ParseInLocation failed: ", err.Error(), ret[4])continue}message.TimeLocal = tbyteSent, _ := strconv.Atoi(ret[8])message.ByteSent = byteSentreqSli := strings.Split(ret[6], " ")if len(reqSli) != 3 {TypeMonitorChan <- TypeErrNumlog.Println("strings.Split fail", ret[6])continue}message.Method = reqSli[0]u, err := url.Parse(reqSli[1])if err != nil {TypeMonitorChan <- TypeErrNumlog.Println("url parse fail: ", err)continue}message.Path = u.Pathmessage.Scheme = ret[5]message.Status = ret[7]requestTime, _ := strconv.ParseFloat(ret[12], 64)message.RequestTime = requestTimel.wc <- message}}func main() {var path, influxDsn string// 利用命令行参数 传入配置flag.StringVar(&path, "path", "./access.log", "read file path")flag.StringVar(&influxDsn, "influxDsn", "http://localhost:8086&root&123456&imooc&s","influx data source")flag.Parse()r := &ReadFromFile{path: path,}w := &WriteToInfluxDB{influxDBsn: influxDsn,}lp := &LogProcess{rc: make(chan []byte),wc: make(chan *Message),reader: r,writer: w,}go lp.reader.Read(lp.rc)go lp.Process()go lp.writer.Write(lp.wc)m := &Monitor{startTime: time.Now(),data: SystemInfo{},}m.start(lp)}

编写启动脚本

(稍后用 docker 部署时使用)

./log_process --path "/var/log/nginx/access.log" --influxDsn "http://indb:8086&root&root&monitor&s" 

编译 go 项目

go build log_process.go

编写Dockerfile

FROM golang:latest
MAINTAINER amoyiki "amoyiki@gmail.com"
WORKDIR $GOPATH/src/amoyiki.com/nginxlog
ADD . $GOPATH/src/amoyiki.com/nginxlog
EXPOSE 9999
ENTRYPOINT ["sh", "./start_process.sh"]  

编译并启动镜像

$ sudo docker build -t log_process .
# 指定数据卷方便容器读取 nginx 日志, 指定关联 influxdb 容器,确保 go 项目能连接到 influxdb 容器
$ sudo docker run --name log1 -d -v /var/log/nginx:/var/log/nginx --link indb:indb log_process
# 查看当前所有容器
$ sudo docker ps -a

最终结果

更多文章请访问我的 Blog 四畳半神话大系

go + influxdb + grafana 日志监控系统相关推荐

  1. influxDB+grafana 日志监控平台(Golang)

    influxdb InfluxDB 是一个开源分布式时序.事件和指标数据库.使用 Go 语言编写,无需外部依赖.其设计目标是实现分布式和水平伸缩扩展. influxDB启动流程:  1  用docke ...

  2. 【监控】使用 Grafana、collectd 和 InfluxDB 打造现代监控系统

    参考资料: Grafana 是 Graphite 和 InfluxDB 仪表盘和图形编辑器:http://www.oschina.net/p/grafana 使用 Grafana.collectd 和 ...

  3. ELK 搭建 TB 级海量日志监控系统,这个太强了!

    欢迎关注方志朋的博客,回复"666"获面试宝典 作者:非洲羚羊 来源:cnblogs.com/dengbangpang/p/12961593.html 本文主要介绍怎么使用 ELK ...

  4. 如何用ELK搭建TB级的日志监控系统?

    点击上方"朱小厮的博客",选择"设为星标" 后台回复"加群",加入新技术 来源:8rr.co/6UEz 本文主要介绍怎么使用 ELK Sta ...

  5. 深度学习核心技术精讲100篇(四十八)-TB级的日志监控系统很难?带你使用ELK轻松搭建日志监控系统

    前言 本文主要介绍怎么使用 ELK Stack 帮助我们打造一个支撑起日产 TB 级的日志监控系统.在企业级的微服务环境中,跑着成百上千个服务都算是比较小的规模了.在生产环境上,日志扮演着很重要的角色 ...

  6. 服务器日志监控系统怎么解决,服务器日志监控系统

    服务器日志监控系统 内容精选 换一换 简要介绍Rsyslog是一个集中日志管理工具,基于流行的服务端/客户端模式,通过TCP或者UDP传输协议来发送日志信息,或者从网络设备.服务器.路由器.交换机.以 ...

  7. 五分钟搭建基于 Prometheus + Grafana 实时监控系统

    文章目录 Prometheus + Grafana 实时监控系统 Prometheus + Grafana 实时监控系统 依赖镜像包 启动 node-exporter check 端口 node_ex ...

  8. ELK日志监控系统搭建

    ELK日志监控系统搭建 一.安装Elasticsearch: https://es.xiaoleilu.com/index.html  1.下载elasticsearch安装文件,官网下载地址:htt ...

  9. 服务器日志和监控系统,服务器日志监控系统

    服务器日志监控系统 内容精选 换一换 VPC流日志功能可以记录虚拟私有云中的流量信息,帮助您优化安全组和防火墙控制规则.监控网络流量.进行网络攻击分析等.当您想要了解虚拟私有云网卡的流量详情时,您可以 ...

最新文章

  1. 排序算法----桶排序(java版)
  2. ios swift ios8 模糊
  3. CakePHP之Model
  4. mysql 按时间累计计算_精通MySQL索引背后的数据结构及算法原理
  5. 杜教BM模板(用于求线性递推公式第N项)
  6. Wi-Fi 6连续两年出货量国内登顶,锐捷无线靠什么这么6?
  7. mpi如何选择合适的进程数量_洗涤工厂如何选择合适的洗衣龙
  8. hash算法_阿里面试官:讲一下Hashmap中hash算法!
  9. Javaweb新手软件推荐
  10. iPhone 5福音 网友发布Nano-SIM剪卡教程
  11. 【pandas】reset_index函数详解
  12. 奈奎斯特与香农定理_奈奎斯特定理和香农定理有什么区别?
  13. mysql重复数据只取一条数据_sql不重复的查找统计数据(经典)
  14. 工资管理系统/c语言期末大作业学习经历
  15. 生活鸡汤---送给女人和男人的
  16. PLC控制系统的软件设计
  17. python实现windows ie代理切换
  18. python if continue的用法_Python continue语句用法实例
  19. 2019年,全栈开发者应该学些什么?
  20. 小区物业管理系统-分析设计

热门文章

  1. 众成翻译2.0上线,翻译即有机会获赠图书
  2. 360私有云平台-HULK 5岁啦~
  3. 以行为单位对字符串变量下标为奇数位置上的字符按其ASCii值从小到大的顺序进行排序,排序后的结果仍按行重新存入字符串数组xx中
  4. Linux Signal及Golang中的信号处理
  5. linux etc/init 与etc/init.d的区别
  6. redis有序集合sorted set详解
  7. redis中list类型详解及常用命令
  8. Linux 初始化之 Systemd机制简介
  9. 年底了,按约定把2021 Go面试八股整理全了
  10. Go gomaxprocs 调高会引起调度性能损耗