Skywalking系列之日志分析语言LAL的配置与解析

提到Skywalking相比并不陌生,或多或少地听到过这个名词,如果你是JAVA开发者,那么可能就更为了解。

作为国内甚至国际上热度比较高、社区比较活跃的APM(Application Performance Monitoring System)系统,它拥有众多的使用者,从传统Java服务,到云原生架构下的服务,甚至框架。

人们对于日志价值的挖掘也是源源不断,从打日志、存日志、同步日志到解析日志,更期望从规范的日志中提取有效的消息,用于检测或告警。

那么今天要介绍的Skywalking中的LAL(Log Analysis Language)模块,就是协助用户从有效的日志数据中,结合自定义的pattern,抽离出有效的字段,用于应用的监控或告警。

全文概览

  • LAL 的背景知识
  • SkyWalking LAL 的基础语法
    • Layer
    • Filter
      • 全局操作符 - abort
      • 全局操作符 - tag
      • Filter:Parser模块
      • Filter:Extractor模块
      • Filter:Sink模块

LAL 的背景知识

SkyWalking中的LAL的语法就能够实现,通过正则等形式,结合groovy语法,匹配出指定字段进行提取,实现从文本中摘出所需要的字段进行聚合统计。

处理的这个数据来源主要就是各类日志,比如Nginx日志、数据库日志、应用日志,由于应用日志是人为写入的,那么对于这个监控就有无限可能。

其实这个功能有很多类似的业内实现,比如说:

Filebeat:轻量级日志文件 shipper,用于转发和集中日志数据到 Elasticsearch 或 Logstash。 同样支持json和正则的形式,分为input/processors/output 。

filebeat.inputs:
- type: stdinprocessors:- dissect:tokenizer: "%{logDate} %{logTime}  %{logLevel} %{pid} --- [%{thread}] %{logger} : %{message}"field: "message"target_prefix: "dissect"
output.console:enabled: truepretty: truefilebeat.inputs:- type: logpaths:- "/data/logs/*/error.log"document_type: jsonjson.message_key: logjson.keys.under_root: truejson.overwrite_keys: truefields:logType: errJsonfields_under_root: true

Fluentd / Fluent Bit:高可用、高性能的日志采集器,支持多种输入输出插件,适用于多种数据源和目标。区分为input/parser/filter/output 。

<parse>@type regexpexpression /^\[(?<logtime>[^\]]*)\] (?<name>[^ ]*) (?<title>[^ ]*) (?<id>\d*)$/time_key logtimetime_format %Y-%m-%d %H:%M:%S %ztypes id:integer
</parse>

Logstash:Elastic Stack 的一部分,强大的数据处理管道,能够从多个来源收集数据,转换并输出到像 Elasticsearch 这样的存储系统。区分为 input/filter/output。

input { stdin { } }filter {grok {match => { "message" => "%{COMBINEDAPACHELOG}" }}date {match => [ "timestamp" , "dd/MMM/yyyy:HH:mm:ss Z" ]}
}output {elasticsearch { hosts => ["localhost:9200"] }stdout { codec => rubydebug }
}

如果对这些类似的产品有过使用经验的,那你肯定能非常快速的理解和上手LAL,主要包含2块概念:Layer, Filter

SkyWalking LAL 的基础语法

对于语法官网也有给到专门的说明,也可以移步去官网学习。

基本框架:

filter { // filter A: this is for persistence// ... parsersink {sampler {// .. sampler configs}}
}
filter { // filter B:// ... extractors to generate many metricsextractors {metrics {// ... metrics}}sink {dropper {} // drop all logs because they have been saved in "filter A" above.}
}

Layer

对于你这块功能一个命名,需要是唯一的具有指向性的名称。

你如果在lal的目录下,新增了一个日志解析方式,需要生效就需要在 application.yml 文件中,在 log-analyzer:default:lalFiles 的配置下,启用你自定义的layer,或者通过 SW_LOG_LAL_FILES 的环境变量来激活你的配置。

Filter

Filter模块是一组 parser, extractor 和 sink

Filter允许做一些条件判断,其中可以结合log对象的参数值。
log对象值有:

 // [Optional] The timestamp of the log, in millisecond.// If not set, OAP server would use the received timestamp as log's timestamp, or relies on the OAP server analyzer.int64 timestamp = 1;// [Required] **Service**. Represents a set/group of workloads which provide the same behaviours for incoming requests.//// The logic name represents the service. This would show as a separate node in the topology.// The metrics analyzed from the spans, would be aggregated for this entity as the service level.//// If this is not the first element of the streaming, use the previous not-null name as the service name.string service = 2;// [Optional] **Service Instance**. Each individual workload in the Service group is known as an instance. Like `pods` in Kubernetes, it// doesn't need to be a single OS process, however, if you are using instrument agents, an instance is actually a real OS process.//// The logic name represents the service instance. This would show as a separate node in the instance relationship.// The metrics analyzed from the spans, would be aggregated for this entity as the service instance level.string serviceInstance = 3;// [Optional] **Endpoint**. A path in a service for incoming requests, such as an HTTP URI path or a gRPC service class + method signature.//// The logic name represents the endpoint, which logs belong.string endpoint = 4;// [Required] The content of the log.LogDataBody body = 5;// [Optional] Logs with trace contextTraceContext traceContext = 6;// [Optional] The available tags. OAP server could provide search/analysis capabilities based on these.LogTags tags = 7;// [Optional] Since 9.0.0// The layer of the service and servce instance. If absent, the OAP would set `layer`=`ID: 2, NAME: general`string layer = 8;
全局操作符 - abort

类似于for循环中的 continue, 已经达到满足的条件,提前跳出当前流程,后续步骤都不会被执行。

filter {if (log.service == "TestingService") { // Don't waste resources on TestingServicesabort {} // all remaining components won't be executed at all}// ... parsers, extractors, sinks
}
全局操作符 - tag

给数据打上标签,丰富最终的数据内容,对于后续步骤中也可以以此作为判断,比如给不同条件的数据做归类,后续进行不同处理等。

[{"tags":{"data":[{"key":"TEST_KEY","value":"TEST_VALUE"}]},"body":{...}...}
]

对增加的标签进行判断

filter {if (tag("TEST_KEY") == "TEST_VALUE") {...   }
}
Filter:Parser模块

这个解析器模块就和前面描述的组件的解析部分一样,就是什么样的数据结构需要做什么样的解析处理,包括json类型数据、yaml类型数据和text文本类型数据

jsonyaml类型的数据很好理解,都是有相对固定的格式要求,text文本类型就需要借助一些正则来实现匹配。

给出规则进行匹配,匹配成功后就能够获取到对应解析出来的对象,那么这些数据如何获取呢?

这边会有一个 parsed 对象来承载解析成功的字段,可以通过 parsed.xxx 来读取到对应的值,是一个典型的map。 json和yaml由于都是固定的键值类型的数据,因此解析后 parsed 对象就会包含其所有值。对于text的文本类型,由于需要类似正则的方式进行匹配的,那么匹配成功就能够获取对应的上的字段值。

此处有一个 abortOnFailure 的参数,表示日志到解析这一步如果就失败了那后续匹配链上的步骤还要不要继续,默认就是遇到失败就跳过不继续往下走了。

  • JSON格式
filter {json {abortOnFailure true // this is optional because it's default behaviour}
}
  • YAML格式
filter {yaml {abortOnFailure true // this is optional because it's default behaviour}
}
  • TEXT格式

纯粹的文本格式可以通过强大的正则表达式去适配所有的情况。
其中regexp的参数必须使用前后括号包围: regexp ("xxxxxx")

filter {text {abortOnFailure true // this is optional because it's default behaviour// this is just a demo patternregexp "(?<timestamp>\\d{8}) (?<thread>\\w+) (?<level>\\w+) (?<traceId>\\w+) (?<msg>.+)"}extractor {tag level: parsed.level// we add a tag called `level` and its value is parsed.level, captured from the regexp abovetraceId parsed.traceId// we also extract the trace id from the parsed result, which will be used to associate the log with the trace}// ...
}
Filter:Extractor模块

提取器模块,就是将上一个解析步骤产生的字段罗列罗列,筛选出需要的字段,进行后续的聚合或存储,数据可以取自log对象parsed对象

parsed对象 除了上面解析出来的一些字段,还有一些默认系统加入的字段,都是系统内链路上共有的值,为了日志能够更好地与服务、实例、链路关联起来。

  • service:parsed.service, 服务的名称,用于和链路和指标绑定
  • instance:parsed.instance, 服务实例的名称,用于和链路和指标绑定
  • endpoint:parsed.endpoint, 服务实例的名称,用于和链路和指标绑定
  • traceId:parsed.traceId,用于和链路和指标绑定
  • segmentId:parsed.segmentId,用于和链路和指标绑定
  • spanId:parsed.spanId,用于和链路和指标绑定
  • timestamp:提取后可以指定类型和format, 到毫秒级别
filter {// ... parserextractor {timestamp parsed.time as String}
}filter {// ... parserextractor {timestamp parsed.time as String, "yyyy-MM-dd HH:mm:ss"}
}
  • layer:parsed.layer, 用于与服务绑定
  • tag:手动打标签
filter {// ... parserextractor {tag level: parsed.level, (parsed.statusCode): parsed.statusMsgtag anotherKey: "anotherConstantValue"layer 'GENERAL'}
}
  • metrics:前面步骤我们通过parse和extractor前面的步骤,实现了从文本中解析出键值对,并根据条件打上了额外的标签,最终如何来使用呢?–> 使用MAL语言,将值做成指标。

首先,在 lal 脚本中,组装好 metrics 的定义。

filter {// ...extractor {service parsed.serviceNamemetrics {name "log_count" //指标名称timestamp parsed.timestamp //增加一个时间戳labels level: parsed.level, service: parsed.service, instance: parsed.instance //抽取出status_code、service、instance 三个标签,可用于前端匹配与展示value 1 //作为一个值,出现1次计数1次}metrics {name "http_response_time" //指标名称timestamp parsed.timestamp //增加一个时间戳labels status_code: parsed.statusCode, service: parsed.service, instance: parsed.instance //抽取出status_code、service、instance 三个标签,可用于前端匹配与展示value parsed.duration //作为一个值,对于时间后续可以累加}}// ...
}

随后,在 log-mal-rules 目录中增加指标 MAL 的声明,此外还需要在 application.yaml 中声明启用这个配置文件:log-analyzer:default:malFiles

metrics:- name: log_count_debugexp: log_count.tagEqual('level', 'DEBUG').sum(['service', 'instance']).increase('PT1M')- name: log_count_errorexp: log_count.tagEqual('level', 'ERROR').sum(['service', 'instance']).increase('PT1M')- name: response_time_percentileexp: http_response_time.sum(['le', 'service', 'instance']).increase('PT5M').histogram().histogram_percentile([50,70,90,99])

以上就是MAL中的语法,实现过滤、预聚合,给到最终进行存储。
通过上述的MAL的定义,在页面看板中,就可以在service面板中,获取到日志文件中按照时间维护DEBUG/ERROR类型的日志有多少条。

  • slowSql:通过"LOG_KIND" = "SLOW_SQL"的标记,可以让OAP服务识别普通日志和慢查询日志。

OAP服务也会对于每个服务,默认每10分钟存储TOP50的SQL,topNReportPeriod: ${SW_CORE_TOPN_REPORT_PERIOD:10})

  • statement

除了展示具体的慢SQL日志,还可以提取SQL statement。

  • latency

提取数据库慢SQL的延时信息。

  • id

id字段指示数据库慢SQL

  • sampledTrace

对大量的细节数据进行采样,降低下游存储等压力。

Filter:Sink模块

接收器持久化模块,通过上述的读取、解析、打标处理,最终日志指标数据需要存储起来。

  • Sampler:针对数据进行采样,减少真实数据量,如果命中多个取样器,最后一个取样器决定取样结果。
    • rateLimit: 1分钟采样多少条日志. rateLimit(“SamplerID”) 需要一个取样ID,声明相同的ID可以使用相同的取样策略。
    • possibility: 通过Java随机数产生一个可能性,与百分比参数进行比对。
filter {// ... parsersink {sampler {if (parsed.service == "ImportantApp") {rateLimit("ImportantAppSampler") {rpm 1800  // samples 1800 pieces of logs every minute for service "ImportantApp"}} else {rateLimit("OtherSampler") {rpm 180   // samples 180 pieces of logs every minute for other services than "ImportantApp"}}}}
}filter {// ... parsersink {sampler {if (parsed.service == "ImportantApp") {possibility(80) { // samples 80% of the logs for service "ImportantApp"}} else {possibility(30) { // samples 30% of the logs for other services than "ImportantApp"}}}}
}
  • Dropper: 是一个特殊的接收器,根据某些标签把一类日志全部丢弃,比如DEBUG日志。
filter {// ... parsersink {if (parsed.level == "DEBUG") {dropper {}} else {sampler {// ... configs}}}
}
  • Enforcer:是一种特殊的接收器,强制采样日志,主要场景:对于已经配置采样器,但是对于一些重要的ERROR日志希望百分之百展现的,可以使用这个。
filter {// ... parsersink {sampler {// ... sampler configs}if (parsed.level == "ERROR" || parsed.userId == "TestingUserId") { // sample error logs or testing users' logs (userId == "TestingUserId") even if the sampling strategy is configuredenforcer {}}}
}

如果喜欢我的文章的话,可以去GitHub上给一个免费的关注吗?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/10089.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

react18+ts如何生成二维码并且下载

目录 一、下载qrcode.react 二、引入qrcode.react 三 、编写下载二维码的函数 在react开发中如果需要二维码&#xff0c;笔者选择使用qrcode.react来快速生成。 一、下载qrcode.react pnpm add qrcode.react 二、引入qrcode.react import {Box,Stack,Fab} from mui/mate…

【基础算法总结】二分查找一

二分查找一 1. 二分查找2.在排序数组中查找元素的第一个和最后一个位置3.x 的平方根4.搜索插入位置 点赞&#x1f44d;&#x1f44d;收藏&#x1f31f;&#x1f31f;关注&#x1f496;&#x1f496; 你的支持是对我最大的鼓励&#xff0c;我们一起努力吧!&#x1f603;&#x1…

spring boot 线程池

文章目录 引言I 配置线程池II 封装线程池任务执行器2.1 唯一性标识2.2 LogFilter:设置request_id2.3 logback使用request_idIII 检测线程池引言 SpringBootApplication启动类上需要加入注解@EnableAsync或者在配置类上使用 应用场景:封装线程池任务执行器:在任务提交时,会…

制造业数字化转型解决方案及应用(125页PPT)

一、资料介绍 《制造业数字化转型解决方案及应用》是一份内容丰富、深入剖析制造业数字化转型的125页PPT资料。这份资料以“智能制造、制造业数字化转型、制造业数字化转型案例”为关键词&#xff0c;全面展现了制造业数字化转型的核心理念、解决方案以及实际应用案例。 关注…

【JS红宝书学习笔记】第1、2章

第1章 什么是JavaScript JavaScript 是一门用来与网页交互的脚本语言&#xff0c;包含以下三个组成部分。 ECMAScript&#xff1a;由 ECMA-262 定义并提供核心功能。文档对象模型&#xff08;DOM&#xff09;&#xff1a;提供与网页内容交互的方法和接口。浏览器对象模型&…

块元素、内联元素、行内块元素

一、介绍&#xff1a; CSS元素划分成块元素、行内元素&#xff08;内联元素&#xff09;、行内块元素等多种常用类型。也就是说&#xff1a;在CSS中&#xff0c;元素根据其在页面上的布局方式被分为不同的显示类型。 背景&#xff1a;HTML负责定义网页的结构和内容&#xff0c…

OC foudation框架(上)学习

foundation框架 文章目录 foundation框架字符串&#xff08;NSString && NSMutableString&#xff09;NSString的其他功能NSMutableString 日期与时间 &#xff08;NSDate&#xff09;2.1 日期与时间&#xff08;NSDate&#xff09;2.2日期格式器日历与日期组件定时器&…

Java入门基础学习笔记8——注释

1、注释&#xff1a; 注释是写在程序中对代码进行解释说明的文件&#xff0c;方便自己和其他人查看&#xff0c;以便理解程序的。 package cn.ensource.note;/**文档注释文档注释 */ public class NoteDemo {public static void main(String[] args) {// 单行注释System.out.…

word转pdf的java实现(documents4j)

一、多余的话 java实现word转pdf可用的jar包不多&#xff0c;很多都是收费的。最近发现com.documents4j挺好用的&#xff0c;它支持在本机转换&#xff0c;也支持远程服务转换。但它依赖于微软的office。电脑需要安装office才能转换。鉴于没在linux中使用office&#xff0c;本…

SwiftUI 调整视图内容周围间隙(Content Margins)的“时髦”方法

概述 在 SwiftUI 开发的应用中,往往在小屏设备(比如 iPhone)上布局良好的 App 放到大屏(iPad)上后就会“一塌糊涂”。因为它们一味的只想着“占据”却不知道“舍弃”。 从 iOS 17.0(iPad 17.0)开始苹果提供了原生的视图修改器方法专注于处理此事。 在本篇博文中,您将…

Python实战开发及案例分析(17)—— 粒子群算法

粒子群优化&#xff08;Particle Swarm Optimization, PSO&#xff09;是一种计算方法&#xff0c;它通过模拟鸟群的社会行为来解决优化问题。粒子群优化算法中的每个“粒子”代表问题空间中的一个候选解决方案。每个粒子都会根据自己的经验以及邻居的经验来调整其在解空间中的…

windows轻松管理nodejs 版本 升/降级 卸载等等

#nvm-windows 管理nodejs 版本神器# 不经意升级了node版本导致原有项目启动异常, 看到了node版本管理神器:nvm-windos 1,先下载 nvm >> git 选择如下安装包或 nvm-setup.exe文件 https://github.com/coreybutler/nvm-windows/releases/tag/1.1.12 2. 双击安装,下一…

centos追加扩容整块磁盘容量

centos追加扩容整块磁盘容量 原磁盘/dev/vdb有100G&#xff0c;整块直接挂载到了/data目录下后来追加了200G到/dev/vdb上[rooti-QxxV9WFa3-2 ~]# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sr0 11:0 1 386K 0 rom vda 253:0 0 100G 0 disk └─vda1…

如何在本地调试THUDM/chatglm2-6b大模型

模型下载网站&#xff1a;https://www.opencsg.com/models 安装git&#xff1a; sudo apt install git安装git-lfs&#xff0c;这个很重要。 sudo apt-get install git-lfs下载模型&#xff1a;THUDM/chatglm2-6b mkdir THUDM cd THUDMgit lfs intsall git clone https://p…

Win10 WSL2 Ubuntu 22.04 配置深度学习环境

文章目录 WSL安装Anaconda下载Anaconda安装包安装配置conda命令conda换国内源conda初始化shell环境conda init手动源激活脚本&#xff1a; 安装Windows上的NVIDIA GPU驱动WSL安装CUDA Toolkit安装12.1版本环境配置报错1报错2 内存不足导致安装崩溃问题描述问题分析问题解决 WSL…

用docker 搭建 vscode for web

前言: 每当我们换机子或者是电脑内容不够的时候&#xff0c;总想着能用web方式使用某些软件&#xff0c;这样子&#xff0c;你无论何时何地都能愉快的开发了&#xff0c;今天来安排下使用容器技术去搭建vscode。 查找合适的Docker镜像 你可以使用官方的Code Server Docker镜像…

vue2人力资源项目6角色管理

elementUi编写表格样式及分页组件 <template><div class"container"><div class"app-container"><!--角色管理内容--><div class"role-operate"><el-button type"primary">添加角色</el-butt…

并行执行参数的应用技巧——《OceanBase 并行执行》系列 5

OceanBase 提供了一套参数&#xff0c;实现对并行执行功能的初始化和调优。 在OceanBase 的启动过程中&#xff0c;系统会根据租户的 CPU 数量和特定的配置项 px_workers_per_cpu_quota 来自动计算出默认的并行执行控制参数。当然&#xff0c;用户也可以选择不采用这些默认值…

一键开启,盲盒小程序里的梦幻奇遇

在这个充满惊喜与未知的数字时代&#xff0c;盲盒小程序以其独特的魅力成为了许多人的新宠。只需一键开启&#xff0c;你就能踏入一个充满梦幻奇遇的世界&#xff0c;探索未知的惊喜与乐趣。 盲盒小程序不仅仅是一个简单的购物平台&#xff0c;它更是一个充满神秘与惊喜的宝藏库…

ETL中如何执行Python脚本

Python的解读 Python 是一种高级、通用的编程语言&#xff0c;由荷兰程序员吉多范罗苏姆&#xff08;Guido van Rossum&#xff09;于1990年代初设计并发布。Python的设计哲学强调代码的可读性和简洁性&#xff0c;它的语法清晰且表达力强&#xff0c;使得开发者能够以更少的代…