转载自:https://mp.weixin.qq.com/s?__biz=MzU4MjQ0MTU4Ng==&mid=2247492075&idx=1&sn=ba63984111671a2590ebc82b60441b74&chksm=fdbaeef6cacd67e0a001731c2caab8a3dd7ea41850c7bed04efd986679e54454838ef3f6a32b&cur_album_id=1837018771652149250&scene=190#rd

ELK在日志方面给我的感觉是大而全,查询匹配是杠杠的,Kibana图表非常丰富。但如果面对大量的数据,需要查询,在不堆机器的情况下,还是会比较疲软,查询比较慢,之前公司每当突发流量的时候,由于日志写入比较大,队列都在kafka,es消费慢,导致无法实时出数据。

Loki 受到了 prometheus启 发,对日志进行打标签的方式而非全文索引的方,而且也可以跟kubernetes集成。

安装Loki(使用Local方式)

安装和运行

1、https://github.com/grafana/loki/releases/

2.找到要安装的版本,我采用的是v2.1.0

3.下载Loki和Promtail, (Loki为日志的引擎,通过Promtail来发送日志到Loki)

4.在本机找一个目录存放这两个2进制文件

5.下载两者的配置文件

wget https://raw.githubusercontent.com/grafana/loki/master/cmd/loki/loki-local-config.yaml
wget https://raw.githubusercontent.com/grafana/loki/master/cmd/promtail/promtail-local-config.yaml

6.使用如下命令启动Loki

./loki-linux-amd64 -config.file=loki-local-config.yaml
cd /usr/local/loki/
ls
loki-linux-amd64 loki-local-config.yaml promtail-linux-amd64 promtail-local-config.yaml
./loki-linux-amd64 -config.file=loki-local-config.yaml

尝试搜集nginx日志

1.首先对nginx默认的日志进行改造,让他以json的方式进行输出到目录,然后用Promtail对其进行读取。

2.读取使用LogQL的json方式去读取,这个LogQL内容填写在grafana中。

nginx的部分配置改造

promtail_json日志格式配置

log_format promtail_json '{"@timestamp":"$time_iso8601",'
'"@version":"Promtail json",'
'"server_addr":"$server_addr",'
'"remote_addr":"$remote_addr",'
'"host":"$host",'
'"uri":"$uri",'
'"body_bytes_sent":$body_bytes_sent,'
'"bytes_sent":$body_bytes_sent,'
'"request":"$request",'
'"request_length":$request_length,'
'"request_time":$request_time,'
'"status":"$status",'
'"http_referer":"$http_referer",'
'"http_user_agent":"$http_user_agent"'
'}';

虚拟server配置

server {
server_name loki.test.com; # 域名设置
listen 8888;
access_log /var/log/nginx/loki_access.log promtail_json;
location / {
return 200 "It's ok!";
}
}

访问127.0.0.1:8888,观察日志已经正常输出为json格式,请保证该json格式正确。

root@test:/etc/nginx/conf.d$tail -f /var/log/nginx/loki_access.log
{"@timestamp":"2021-03-06T01:54:42-05:00","@version":"Promtail json","server_addr":"127.0.0.1","remote_addr":"192.168.65.130","host":"127.0.0.1","uri":"/","body_bytes_sent":8,"bytes_sent":8,"request":"GET / HTTP/1.1","request_length":78,"request_time":0.000,"status":"200","http_referer":"-","http_user_agent":"curl/7.29.0"}

nginx日志改造完毕

Promtail配置文件修改

1.因为搜集日志是Promtail处理,所以自然而然是需要根据自己需求来配置Promtail的配置文件。

server:
http_listen_port: 9080
grpc_listen_port: 0 positions:
filename: /tmp/loki-positions.yaml # 记录pos点
sync_period: 5s # 5s一次将当前读取到的pos点同步至filename配置的文件内 clients:
- url: http://localhost:3100/loki/api/v1/push scrape_configs:
- job_name: Loki
static_configs:
- labels: # 设定的部分标签
job: Loki-nginx
host: localhost
app: nginx
__path__: /var/log/nginx/loki_access.log # 待读取的nginx日志

LogQL json部分文档理解

json的提取分为两种方式,带参数和不带参数

1.不带参数的方式

  • 使用|json来提取日志的json内容,前提是json内容为有效json格式。
  • 嵌套的字段会用”_”将内外层的key进行拼接。
  • 忽略数组。

看一下官网中不带参数方式的样例

{
"protocol": "HTTP/2.0",
"servers": ["129.0.1.1","10.2.1.3"],
"request": {
"time": "6.032",
"method": "GET",
"host": "foo.grafana.net",
"size": "55",
"headers": {
"Accept": "*/*",
"User-Agent": "curl/7.68.0"
}
},
"response": {
"status": 401,
"size": "228",
"latency_seconds": "6.031"
}
}

被json解后,得到如下:

"protocol" => "HTTP/2.0"
"request_time" => "6.032"
"request_method" => "GET"
"request_host" => "foo.grafana.net"
"request_size" => "55"
"response_status" => "401"
"response_size" => "228"
"response_size" => "228"

从输出能看到,原本request字段内容为嵌套,所以request里面的内容的key验证了如上第二点,使用”_”进行了拼接。同时servers由于是个数组,所以在解析后直接丢弃了servers这个key,验证了第三点。

2.带参数的方式

  • 带参数的方式,json只会根据参数来解开需要的部分(当单条json数据比较大的时候应该能省很多资源)。
  • 使用| json label=”expression”, another=”expression”的方式来编写该方法。可以存在多个参数

看一下官网中带参数方式的样例

使用| json first_server=”servers[0]”, ua=”request.headers["User-Agent"]进行提取

{
"protocol": "HTTP/2.0",
"servers": ["129.0.1.1","10.2.1.3"],
"request": {
"time": "6.032",
"method": "GET",
"host": "foo.grafana.net",
"size": "55",
"headers": {
"Accept": "*/*",
"User-Agent": "curl/7.68.0"
}
},
"response": {
"status": 401,
"size": "228",
"latency_seconds": "6.031"
}
}

输出结果为:

"first_server" => "129.0.1.1"
"ua" => "curl/7.68.0"

first_server和ua都为原先参数中指定的key

如果要提取整个对象,可以使用| json server_list=”servers”, headers=”request.headers 这样就能得到如下输出:

"server_list" => `["129.0.1.1","10.2.1.3"]`
"headers" => `{"Accept": "*/*", "User-Agent": "curl/7.68.0"}`

尝试写一条LogQL表达式

一条完整的LogQL表达式由两部分构成:

  • a log stream selector,可以理解为,通过设定的label去匹配要抓取哪些日志。
  • a log pipeline,可以理解为表达式。比如json的提取。

比如如下表达式

{container="query-frontend",namespace="tempo-dev"} |= "metrics.go" | logfmt | duration > 10s and throughput_mb < 500

{container=”query-frontend”,namespace=”tempo-dev”} 部分为log stream selector,后面部分为log pipeline。

编写一个简单的nginx日志需求

  • Loki-nginx日志中状态码为200的条数。
  • 根据当前选定时间范围,自动调整。

思考:

1.如何指定Loki-nginx,可以使用log stream selector的表达式来选定。

2.nginx日志已经转变为了json,所以可以用|json来提取。

3.如何获取status字段的信息? |json后面直接跟随|status即可,即|json|status

4.如何根据当前选定的时间范围?使用内置变量[$\_\_interval]

5.条数该得用什么方法获得?LogQL有内置函数count_over_time配合sum,这边需要注意的是count_over_time是根据指定时间范围返回日志条目的具体内容,所以还需要配合sum获得时间段内的总数。

编写:

1.首先选定Loki-nginx的日志,{job="Loki-nginx"}

2.使用count_over_time函数配合[$\_\_interval]来获取总共的条数。count_over_time({job="Loki-nginx"}[$\_\_interval])

3.过滤status字段,让其等于200,表达式count_over_time({job="Loki-nginx"} | json | status = 200 [$\_\_interval]),此时会报错,因为status为字符串,可以添加__error__=””让其忽略转换出现的异常。得到count_over_time({job="Loki-nginx"} | json | status = 200 \_\_error\_\_="" [$\_\_interval])

4.此时在grafana上显示为多条数据,配合sum得到单独一个数值。

5.最终的表达式为:sum(count_over_time({job="Loki-nginx"} | json | status = 200 __error__="" [$__interval]))

原文链接:https://kirakirazone.com/2021/03/06/Loki日志服务01/

使用 Loki 收集 nginx 日志的更多相关文章

  1. ELK Stack (2) —— ELK + Redis收集Nginx日志

    ELK Stack (2) -- ELK + Redis收集Nginx日志 摘要 使用Elasticsearch.Logstash.Kibana与Redis(作为缓冲区)对Nginx日志进行收集 版本 ...

  2. ELK filter过滤器来收集Nginx日志

    前面已经有ELK-Redis的安装,此处只讲在不改变日志格式的情况下收集Nginx日志. 1.Nginx端的日志格式设置如下: log_format access '$remote_addr - $r ...

  3. ELK日志系统之使用Rsyslog快速方便的收集Nginx日志

    常规的日志收集方案中Client端都需要额外安装一个Agent来收集日志,例如logstash.filebeat等,额外的程序也就意味着环境的复杂,资源的占用,有没有一种方式是不需要额外安装程序就能实 ...

  4. 安装logstash5.4.1,并使用grok表达式收集nginx日志

    关于收集日志的方式,最简单性能最好的应该是修改nginx的日志存储格式为json,然后直接采集就可以了. 但是实际上会有一个问题,就是如果你之前有很多旧的日志需要全部导入elk上查看,这时就有两个问题 ...

  5. ELK 二进制安装并收集nginx日志

    对于日志来说,最常见的需求就是收集.存储.查询.展示,开源社区正好有相对应的开源项目:logstash(收集).elasticsearch(存储+搜索).kibana(展示),我们将这三个组合起来的技 ...

  6. 第七章·Logstash深入-收集NGINX日志

    1.NGINX安装配置 源码安装nginx 因为资源问题,我们先将nginx安装在Logstash所在机器 #安装nginx依赖包 [root@elkstack03 ~]# yum install - ...

  7. ELASTIC 5.2部署并收集nginx日志

    elastic 5.2集群安装笔记   设计架构如下: nginx_json_log ->filebeat ->logstash ->elasticsearch ->kiban ...

  8. rsyslog收集nginx日志配置

    rsyslog日志收集配置 rsyslog服务器收集各服务器的日志,并汇总,再由logstash处理 请查看上一篇文章  http://bbotte.blog.51cto.com/6205307/16 ...

  9. EFK收集nginx日志

    准备三台centos7的服务器 两核两G的 关闭防火墙和SELinux systemctl stop firewalld setenforce 0 1.每一台都安装jdk rpm -ivh jdk-8 ...

随机推荐

  1. Graphics2D类

    Graphics2D类 Java语言在Graphics类提供绘制各种基本的几何图形的基础上,扩展Graphics类提供一个Graphics2D类,它拥用更强大的二维图形处理能力,提供.坐标转换.颜色管 ...

  2. 比起网易有数BI,也许这款数据可视化软件更适合你!

    有数BI是网易推出的面向企业客户的可视化敏捷BI产品.拥有数据填报和自助式商业智能分析产品,提供网页端和手机端应用,帮助客户快速实现数据填报.多维分析.大数据探索.实时大数据展示和成员分享. 山海鲸可 ...

  3. C++系统函数

    C++语言预先编写了很多常用函数提供给广大程序员使用,这些函数被统称为系统函数.C++语言全盘继承了C语言的标准C库,另外又增加了一些新的库(更多的是系统类库),这些新库被统称为C++标准库. 一.C ...

  4. 【Azure 事件中心】Azure Event Hub 新功能尝试 -- 异地灾难恢复 (Geo-Disaster Recovery)

    问题描述 关于Event Hub(事件中心)的灾备方案,大多数就是新建另外一个备用的Event Hub,当主Event Hub出现不可用的情况时,就需要切换到备Event Hub上. 而在切换的过程中 ...

  5. JavaScript数组方法总结及手写

    目录 手写数组衍生方法 1.检测是否为数组 2.类数组转化为数组 3.数组扁平化 4.数组去重 5.数组使用Math.max 手写数组内置方法 1. Array.prototype.filter 2. ...

  6. python中print函数

    python中的输出函数 注意不是C中的printf 起作用就是将希望输出的内容输出在IDLE或标准的控制台上 python解释器将代码翻译成及其能听懂的语言,从而实现代码的实现 print的输出内容 ...

  7. python 执行需要管理员权限的命令(Windows)

    由于Windows存在管理员权限限制,执行需管理员权限的命令时会出错, 有两种方案, 1.采用python调用vbs文件,vbs调用bat文件 2.采用提供弹出用户管理员权限方式让用户确认 1.采用p ...

  8. c语言中的gets和fgets的使用差别

    gets和fgets的差别 2022年6月30日 #include<stdio.h> #include<string.h> #define STLEN 8 int main(i ...

  9. 丽泽普及2022交流赛day22 无社论

    开始掉分模式 . T3 有人上费用流了???(id) 不用 TOC 了 . T1 暴力 T2 没看见 任意两圆不相交,gg 包含关系容易维护,特判相切 . 单调栈即可 T3 贪心 T4 神秘题

  10. 4.5省选模拟solution

    \(4.5\)省选测试\(solution\) 题面可是我精心准备(咕咕咕)了一周写出来的,大家就当看故事吧(那里面的人物确实是存在的,\(E\)就是本人啦,也算是对一段经历的回忆吧,所以这套考试的题 ...