前言

上一小节描述了metrics、traces,本小节来把log也加进去,并且做一个traces与log的联动

  • 当查看日志的时候,可以同时跳转到对应的jaeger,查看分段trace情况

应用服务

  • 本次要测试的应用服务架构为 a.py-->b.py
  • 业务服务会往对应的目录打印日志,并且日志包含了trace_id

a.py

import tornado.httpserver as httpserver
import tornado.web
from tornado.ioloop import IOLoop
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.resources import SERVICE_NAME, Resource
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.trace import get_tracer
from opentelemetry.propagate import inject
import requests
import logging trace.set_tracer_provider(
TracerProvider(resource=Resource.create({SERVICE_NAME: "line-a"}))
)
span_processor = BatchSpanProcessor(OTLPSpanExporter(endpoint="http://127.0.0.1:4318/v1/traces"))
trace.get_tracer_provider().add_span_processor(span_processor) logger = logging.getLogger('a.py')
logger.setLevel(logging.INFO)
formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
file_handler = logging.FileHandler('logs/access-a.log', mode='a', encoding='utf-8')
file_handler.setFormatter(formatter)
logger.addHandler(file_handler) def traced(name):
def decorator(func):
def wrapper(*args, **kwargs):
tracer = get_tracer(__name__)
with tracer.start_as_current_span(name):
trace_id = format(trace.get_current_span().get_span_context().trace_id, '032x')
logger.info('{} {}'.format(name, trace_id))
return func(*args, **kwargs)
return wrapper
return decorator class TestFlow(tornado.web.RequestHandler):
def get(self):
views()
self.finish('hello world') @traced("phase-1")
def views():
views_2()
headers = {}
inject(headers)
requests.get("http://127.0.0.1:20000", headers=headers) @traced("phase-2")
def views_2():
pass def applications():
urls = []
urls.append([r'/', TestFlow])
return tornado.web.Application(urls) def main():
app = applications()
server = httpserver.HTTPServer(app)
server.bind(10000, '0.0.0.0')
server.start(1)
IOLoop.current().start() if __name__ == "__main__":
try:
main()
except KeyboardInterrupt as e:
IOLoop.current().stop()
finally:
IOLoop.current().close()

同理配置b.py

...
trace.set_tracer_provider(
TracerProvider(resource=Resource.create({SERVICE_NAME: "line-b"}))
) logger = logging.getLogger('b.py')
logger.setLevel(logging.INFO)
formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
file_handler = logging.FileHandler('logs/access-b.log', mode='a', encoding='utf-8') ...
@traced("phase-3")
def views(headers):
pass ...
def main():
app = applications()
server = httpserver.HTTPServer(app)
server.bind(20000, '0.0.0.0')
server.start(1)
IOLoop.current().start()
...

访问curl 127.0.0.1:10000之后,就会往日志文件中写入日志

 cat access-a.log
2025-08-21 11:22:18 - a.py - INFO - phase-1 38f0e8cef3e331993eca1675fa8c956b
2025-08-21 11:22:18 - a.py - INFO - phase-2 38f0e8cef3e331993eca1675fa8c956b cat access-b.log
2025-08-21 11:22:18 - b.py - INFO - phase-3 38f0e8cef3e331993eca1675fa8c956b

日志系统loki

1)安装loki

loki.yaml

auth_enabled: false

server:
http_listen_port: 3100 common:
instance_addr: 127.0.0.1
path_prefix: /loki
storage:
filesystem:
chunks_directory: /loki/chunks
rules_directory: /loki/rules
replication_factor: 1
ring:
kvstore:
store: inmemory schema_config:
configs:
- from: 2020-10-24
store: tsdb
object_store: filesystem
schema: v13
index:
prefix: index_
period: 24h ruler:
alertmanager_url: http://localhost:9093
docker run -d --name grafana-loki \
-p 3100:3100 \
-v ./loki.yaml:/etc/loki/local-config.yaml \
grafana/loki:v3.5.3

2)安装promtail

promtail.yaml

server:
http_listen_port: 9080
grpc_listen_port: 0 positions:
filename: /tmp/positions.yaml clients:
- url: http://10.22.12.178:3100/loki/api/v1/push scrape_configs:
- job_name: system
static_configs:
- labels:
job: access_log
__path__: /var/log/access*.log
docker run -d --name grafana-promtail \
-v ./promtail.yaml:/etc/promtail/config.yml \
-v ./logs:/var/log:ro \
grafana/promtail:3.5

3)安装grafana

docker run -d --name grafana-grafana \
-p 3000:3000 \
grafana/grafana:12.1.1

4)在grafana上配置loki

登录grafana --> connections --> data sources --> 选择loki --> 开始配置

最关键的步骤就是把connection改成loki的地址10.22.12.178:3100

5)查看下刚才写入的日志

日志已经进来了

logs跳转至traces

之前已经将traces采集进jaeger,现在又拥有了日志,将他们通过traceid联动起来,在grafana找到日志,并且通过traceid字段跳转去jaeger查询详细信息

登录grafana --> connections --> data sources --> 选择刚才配置好的loki --> Derived fields

  • Name:随便取一个
  • Type:Regex in log line
  • Regex:([0-9a-f]{32,})
  • URL:配置jaeger的URL,http://10.22.12.178:16686/trace/${__value.raw}

配置完成之后查看日志,有会个跳转按钮,点击之后就来带jaeger-UI的查询页面

联系我

  • 联系我,做深入的交流


至此,本文结束

在下才疏学浅,有撒汤漏水的,请各位不吝赐教...

opentelemetry全链路初探--日志跳转trace的更多相关文章

  1. Dubbo 全链路追踪日志的实现

    微服务架构的项目,一次请求可能会调用多个微服务,这样就会产生多个微服务的请求日志,当我们想要查看整个请求链路的日志时,就会变得困难,所幸的是我们有一些集中日志收集工具,比如很热门的ELK,我们需要把这 ...

  2. APM全链路监控--日志收集篇

    一.监控的意义: 随着互联网普及的广度和深度,对于项目的监控显得格外重要:无论是web服务器进程.内存.cpu等资源监控,还是爬虫程序请求频率,状态码以及储存结果的监控,都需要一个及时的反馈机制. 二 ...

  3. 基于SLF4J的MDC机制和Dubbo的Filter机制,实现分布式系统的日志全链路追踪

    原文链接:基于SLF4J的MDC机制和Dubbo的Filter机制,实现分布式系统的日志全链路追踪 一.日志系统 1.日志框架 在每个系统应用中,我们都会使用日志系统,主要是为了记录必要的信息和方便排 ...

  4. .NET Core集成CorrelationId实现全链路日志输出

    .NET Core集成CorrelationId实现全链路日志输出 一,链路追踪 随着微服务架构的流行,一次请求会涉及多个服务的调用,并且服务本身也可能会依赖其他服务,整个请求路径会构成一个调用链,当 ...

  5. 【Logback+Spring-Aop】实现全面生态化的全链路日志追踪系统服务插件「Logback-MDC篇」

    日志追踪 日志追踪对于功能问题的排查和数据流转的路径分析时非常重要的,有了全链路日志追踪体系机制可以非常有效且快速的定位问题,但在多线程环境中,若没有相关成熟的框架的支持,想要实现日志追踪,就需要手动 ...

  6. C#编写Windows服务程序 (服务端),client使用 消息队列 实现淘宝 订单全链路效果

    需求: 针对 淘宝提出的 订单全链路 产品接入 .http://open.taobao.com/doc/detail.htm?id=102423&qq-pf-to=pcqq.group oms ...

  7. Go微服务全链路跟踪详解

    在微服务架构中,调用链是漫长而复杂的,要了解其中的每个环节及其性能,你需要全链路跟踪. 它的原理很简单,你可以在每个请求开始时生成一个唯一的ID,并将其传递到整个调用链. 该ID称为Correlati ...

  8. 全链路跟踪skywalking简介

    该文章主要包括以下内容: skywalking的简介 skywalking的使用,支持多种调用中间件(httpclent,springmvc,dubbo,mysql等等) skywalking的tra ...

  9. 基于 Istio 的全链路灰度方案探索和实践

    作者|曾宇星(宇曾) 审核&校对:曾宇星(宇曾) 编辑&排版:雯燕 背景 微服务软件架构下,业务新功能上线前搭建完整的一套测试系统进行验证是相当费人费时的事,随着所拆分出微服务数量的不 ...

  10. 全链路追踪traceId,ThreadLocal与ExecutorService

    关于全链路追踪traceId遇到线程池的问题,做过架构的估计都遇到过,现在以写个demo,总体思想就是获取父线程traceId,给子线程,子线程用完移除掉. mac上的chrome时不时崩溃,写了一大 ...

随机推荐

  1. LiveRTMP推送RTSP视频源进行RTMP直播

    LiveRTMP ##RTSP视频源进行RTMP直播 /* NVSource从RTSPClient获取数据后回调给上层 */ int Easy_APICALL __RTSPSourceCallBack ...

  2. Flutter 布局核心思想

    认真对待每时.每刻每一件事,把握当下.立即去做. 在 Flutter 中,布局确实完全通过组件(Widget)来实现,这与许多其他 UI 框架的设计理念不同.以下是 Flutter 布局系统的详细解析 ...

  3. shader编程基础:画圆

    前记 使用的在线编译工具shadertoy的编写shader语言.跳转链接:Shadertoy 基本实现 void mainImage( out vec4 fragColor, in vec2 fra ...

  4. 星球助手发布更新v1.3.2

    星球助手发布更新v1.3.2,重要的更新内容有 可以给软件设置自定义的工作目录 设置只下载指定扩展名的文件 提示一下,该版本更改了上一版本对设置参数的保存方法,所以,之前保存的参数会被重置,请重新设置 ...

  5. Django过时了吗?从ASGI到AI时代的思考

    前言 本文本来只是 DjangoStarterv3.2.1 新版本发布博客里的一段思考,不过越写越长,干脆拆分成一篇独立的文章得了. "Django 过时了吗?" 这是一个几乎每天 ...

  6. 【LeetCode】16. 最接近的三数之和

    [LeetCode]16. 最接近的三数之和 题目 给定一个包括 n 个整数的数组 nums 和 一个目标值 target.找出 nums 中的三个整数,使得它们的和与 target 最接近.返回这三 ...

  7. 在 Conda 环境中,更换 R 语言的镜像源

    .markdown-body { line-height: 1.75; font-weight: 400; font-size: 16px; overflow-x: hidden; color: rg ...

  8. 托管C++实现C#接口崩溃的一种情况

    "System.TypeLoadException"类型的未经处理的异常在 CYSAlogExe.exe 中发生 其他信息: 程序集"CLRAdapter, Versio ...

  9. 权威调研榜单:四氟加热器厂家TOP3榜单好评深度解析

    随着化工.医药.食品等行业对耐腐蚀加热设备需求持续增长,四氟加热器市场呈现稳健发展态势.行业数据显示,2024年国内特种加热器市场规模突破65亿元,其中四氟加热器占比约30%,年增长率保持在15%以上 ...

  10. 应用安全 --- 流量分析 之 wireshark去噪音

    我们分析一个应用时常常发现有很多不必要流量干扰了我们的分析.我把这个叫噪音. 去除方法是 右键流量过滤选择且非选中,多次应用完成去噪 这是我的去噪过滤语法 (((((((((((((((((((((( ...