6

Opentelemetry 可观测性规范(三)—— OTEL 核心源码梳理

 8 months ago
source link: https://www.zoucz.com/blog/2023/12/17/a833c170-9c8d-11ee-9fa0-5dbc93f9d3ee/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

本文基于 Opentelemetry JS 语言的实现,梳理了其对 OTEL 的具体实现,方便深入理解 OTEL 的工作原理,便于日常项目中的可观测性数据上报和自定义的三方 instrumentation 组件开发。 我要说话

1. API

1.1 API 结构梳理

API 模块提供了 context、metrics、trace、propagation 等核心功能的 API 定义,以及它们的默认实现。 我要说话

image.png

我要说话

1.2 API 具体实现

├── api
│   ├── context.ts # 维护一个 ContextAPI 单例对象 context,提供全局 context 的设置、访问等方法
│   ├── diag.ts    # 维护一个 DiagAPI 单例对象 diag,提供全局诊断日志的管理
│   ├── metrics.ts # 维护一个 MetricsAPI 单例对象 metrics,提供全局 MeterProvider 管理、Meter 创建功能
│   ├── propagation.ts # 维护一个 PropagationAPI 单例对象 propagation
		       # 提供全局 propagator 的设置、inject、extract 方法、Baggage 相关方法
│   └── trace.ts   # 维护一个 TraceAPI 单例对象 trace,提供全局 TracerProvider 的管理、Tracer创建功能
├── baggage        #【具体实现】baggage,由 propagation.ts 调用
│   ├── context-helpers.ts # 操作 baggage 在 context 中读写的工具函数
│   ├── internal
│   │   ├── baggage-impl.ts # baggage 具体实现
│   │   └── symbol.ts # 数据类型 symbol 标记
│   ├── types.ts      # Baggage 相关接口定义,baggage-impl.ts 实现了 Baggage 接口
│   └── utils.ts      # 提供出口方法 createBaggage、baggageEntryMetadataFromString
├── common            # 一些基础类型定义
│   ├── Attributes.ts # 属性类型
│   ├── Exception.ts  # 异常类型
│   └── Time.ts       # 时间类型
├── context           # context 相关实现
│   ├── NoopContextManager.ts # 默认的 NoopContextManager implements types.ContextManager
			      # 第一次 active 时返回 ROOT_CONTEXT
│   ├── context.ts            # 默认的 BaseContext implements Context,提供一个实例作为 ROOT_CONTEXT
│   └── types.ts              # Context、ContextManager 接口定义
├── diag                      # 诊断日志相关实现
│   ├── ComponentLogger.ts    # 日志组件 logger
│   ├── consoleLogger.ts      # 控制台 logger
│   ├── internal
│   │   ├── logLevelLogger.ts # 根据现有 logger 创建限制输出级别的 logger
│   │   └── noopLogger.ts     # 未设置任何 logger 时的 no operation logger,啥也不干
│   └── types.ts              # DiagLogger、DiagLoggerApi 接口定义
├── internal # 内部公共能力模块
│   ├── global-utils.ts # 根据 platform 获取并维护一个全局对象
			# 含 DiagLogger、TracerProvider、ContextManager、
		        # MeterProvider、TextMapPropagator
			# 并提供 get、register、unregister 等函数
│   └── semver.ts # 提供一个semver版本兼容性判断函数,输入版本号,输出当前api是否支持此版本号
├── metrics                   # metrics 相关接口定义和默认实现
│   ├── Meter.ts              # Meter 接口定义,含各类指标的创建等方法定义
│   ├── MeterProvider.ts      # MeterProvider 接口定义,里边就一个 getMeter 方法
│   ├── Metric.ts             # 各类指标和指标选项定义,如 Histogram、Counter 等
│   ├── NoopMeter.ts          # 默认的 Meter 实现,各类方法都返回一个啥也不干的指标对象
│   ├── NoopMeterProvider.ts  # 默认的 MeterProvider 实现,getMeter 返回 NoopMeter 对象
│   └── ObservableResult.ts   # ObservableResult、BatchObservableResult 接口定义
├── platform # 根据不同平台获取 global 对象
│   ├── browser # 浏览器环境获取 global
│   │   ├── globalThis.ts
│   │   └── index.ts
│   ├── index.ts # 默认返回 node 环境 global
│   └── node # node 环境获取 global
│       ├── globalThis.ts
│       └── index.ts
├── propagation                    # propagation 相关接口定义和默认实现
│   ├── NoopTextMapPropagator.ts   # 默认的 TextMapPropagator 实现,啥也不干
│   └── TextMapPropagator.ts       # TextMapPropagator 接口定义,提供 inject /extract 方法
├── trace                            # trace 相关接口和默认实现
│   ├── internal
│   │   ├── tracestate-impl.ts       # 一个实现 TraceState 接口的 TraceStateImpl,提供设置/读取
				     # 序列化、反序列化等方法 
│   │   ├── tracestate-validators.ts # 提供 TraceState 的key/value合法性校验方法(正则)
│   │   └── utils.ts                 # 基于 TraceStateImp 包装 createTraceState 函数并导出
│   ├── NonRecordingSpan.ts          # 默认的 Span 实现,一个啥也不干的 Span 类实现
│   ├── NoopTracer.ts                # 默认的 Tracer 实现,返回 NonRecordingSpan
│   ├── NoopTracerProvider.ts        # 默认的 TracerProvider 实现,返回 NoopTracer
│   ├── ProxyTracer.ts               # 代理 Tracer,可以传入 TracerDelegator 对象代理其他 Tracer
│   ├── ProxyTracerProvider.ts       # 代理 TracerProvider,可以代理另一个 TracerProvider
│   ├── Sampler.ts                   # Sampler 采样器接口定义,提供 shouldSample 方法
│   ├── SamplingResult.ts            # SamplingResult 采样结果接口定义,含是否记录结果
│   ├── SpanOptions.ts               # startSpan 传入的选项
│   ├── attributes.ts              # 对 ../common/Attributes 中的属性导出
│   ├── context-utils.ts           # 封装从 content 中增删改查 span 的方法
│   ├── invalid-span-constants.ts  # 实现默认的非法 SpanContext
│   ├── link.ts                    # Link 接口定义
│   ├── span.ts                    # Span 接口定义
│   ├── span_context.ts            # SpanContext 接口定义,是 Span 的一个属性,含 spanid、traceid等
│   ├── span_kind.ts               # SpanKind 枚举 
│   ├── spancontext-utils.ts       # 提供 SpanContext 合法性判断相关方法
                                   # 提供 wrapSpanContext 基于 SpanContext 创建一个 Span 对象
│   ├── status.ts                  # SpanStatus 接口,含 code、message 属性
│   ├── trace_flags.ts             # TraceFlags 枚举
│   ├── trace_state.ts             # TraceState 接口定义,含设置、获取、序列化等方法
│   ├── tracer.ts                  # Tracer 接口定义,含 startSpan、startActiveSpan 方法
│   ├── tracer_options.ts          # TracerOptions 接口定义
│   └── tracer_provider.ts         # TracerProvider 接口定义,含 getTracer 方法
├── context-api.ts            # 导出 ContextAPI 实例(/api/context.ts)
├── diag-api.ts               # 导出 DiagAPI 实例(/api/diag.ts)
├── index.ts                  # 全局出口
├── metrics-api.ts            # 导出 MetricsAPI 实例(/api/metrics)
├── propagation-api.ts        # 导出 PropagationAPI 实例(/api/propagation)
└── trace-api.ts              # 导出 TraceAPI 实例(/api/trace)

其中内容比较多的 trace 模块结构: 我要说话

trace uml我要说话

2. 稳定阶段模块

2.1 稳定阶段模块结构梳理

image.png

我要说话

模块列表: 我要说话

packages
├── opentelemetry-context-async-hooks      # 基于 async_hooks 实现异步上下文库
                                           # 并实现 ContextManager API接口
├── opentelemetry-context-zone             # 基于 zone.js 实现的 web 环境异步上下文库
                                           # 实际上只是导出 @opentelemetry/context-zone-peer-dep
├── opentelemetry-context-zone-peer-dep    # 基于 zone.js 实现 ContextManager API接口
├── opentelemetry-core                     # API 中 trace 的相关实现,后面细说
├── opentelemetry-exporter-jaeger          # jaeger 的 SpanExporter 实现
├── opentelemetry-exporter-zipkin          # zipkin 的 SpanExporter 实现
├── opentelemetry-propagator-b3            # B3 格式的 TextMapPropagator 实现
├── opentelemetry-propagator-jaeger        # jaeger 的 TextMapPropagator 实现
├── opentelemetry-resources                # Resource 的接口定义、具体实现
                                           # 默认的浏览器、环境变量 detector 实现
├── opentelemetry-sdk-trace-base           # trace 的基础实现,提供手动 instrumentation 方法
                                           # 实现了 API 中的 TracerProvider 和 Sampler
├── opentelemetry-sdk-trace-node           # 实现了 node 环境的 auto instrumentation
                                           # 配合 opentelemetry-instrumentation 实现
├── opentelemetry-sdk-trace-web            # 实现了 web 环境的 auto instrumentation
├── opentelemetry-semantic-conventions     # Trace 和 Resource 的术语表
├── opentelemetry-shim-opentracing         # 从 opentracing 升级到 otel 组件
├── sdk-metrics                            # metrics 的相关实现,提供手动 instrumentation 方法
└── template

2.2 @opentelemetry/core 模块具体实现

packages/opentelemetry-core/src
├── baggage
│   ├── propagation
│   │   └── W3CBaggagePropagator.ts  # 按 W3C trace 规范实现的 Baggage TextMapPropagator
│   ├── constants.ts                 # Baggage 相关约束常量
│   └── utils.ts                     # Baggage 相关实现
├── common                           # API 中工具函数的实现
│   ├── ......
├── internal                         
│   ├── exporter.ts                  # Exporter 接口定义
│   └── validators.ts                # 命名校验工具函数
├── platform                         # 平台相关工具函数
│   ├── browser                      # 浏览器运行环境相关工具函数
│   │   ├── ......
│   ├── node                         # node 运行环境相关工具函数
│   │   ├── ......
│   └── index.ts
├── propagation
│   └── composite.ts                    # 多传播渠道 TextMapPropagator 实现
├── trace                               # trace相关实现
│   ├── sampler                         # 各类采样器实现
│   │   ├── AlwaysOffSampler.ts         # 不上报的采样器
│   │   ├── AlwaysOnSampler.ts          # 总是上报的采样器
│   │   ├── ParentBasedSampler.ts       # 基于父采样结果的采样器
│   │   └── TraceIdRatioBasedSampler.ts # 基于 trace_id 的比例采样器
│   ├── IdGenerator.ts                  # IdGenerator 接口定义
│   ├── TraceState.ts                   # TraceState API 接口的具体实现
│   ├── W3CTraceContextPropagator.ts    # 按 W3C trace 规范实现的 TraceContext TextMapPropagator
│   ├── rpc-metadata.ts                 # rpc context 元数据设置函数
│   └── suppress-tracing.ts             # 设置/获取 取消 trace 标记的函数
├── utils                               # 工具函数
│   ├── ......
├── ExportResult.ts                     # export 结果接口定义
└── index.ts

2.3 @opentelemetry/sdk-metrics 具体实现

├── aggregator                         # 数据聚合相关实现 DROP/SUM/LAST_VALUE/HISTOGRAM/...
│   ├── ......
├── exemplar                           # 指标数据采集相关实现(measurement)                                         
│   ├── ......
├── export                                  # exporter 相关实现
│   ├── AggregationSelector.ts              # 时序聚合方案选择函数
│   ├── AggregationTemporality.ts           # 时序聚合方案枚举,增量/总量
│   ├── ConsoleMetricExporter.ts            # PushMetricExporter 基于控制台的实现类
│   ├── InMemoryMetricExporter.ts           # PushMetricExporter 保存到内存的实现
│   ├── MetricData.ts                       # 定义指标数据类型接口,包装 aggregator/types 的类型
│   ├── MetricExporter.ts                   # 指标数据导出接口 PushMetricExporter
│   ├── MetricProducer.ts                   # 指标数据生产器接口,提供 collect 方法
│   ├── MetricReader.ts                     # 指标读取器抽象类,维护 MetricProducer
│   └── PeriodicExportingMetricReader.ts    # 定时导出的 MetricReader 派生类
├── state                              # 指标数据存储相关实现
│   ├── ......
├── view                               # 数据视图相关实现
│   ├── ......
├── InstrumentDescriptor.ts    # 指标描述信息接口定义
├── Instruments.ts             # 对 API 中 Metrics 中各类指标类型接口的具体实现,如 Histogram 等
├── Meter.ts                   # 对 API 中 Meter 接口的具体实现
├── MeterProvider.ts           # 对 API 中 MeterProvider 接口的具体实现
├── ObservableResult.ts        # 对 API 中 ObservableResult 接口的具体实现
├── index.ts                   # 模块出口

sdk-mertics 模块UML: 我要说话

trace uml我要说话

指标采集内部组件之间的关系: 我要说话

image.png

我要说话

一个指标 创建 → 收集指标值 → 数据聚合视图 → 指标读取 → 指标上报 的流程: 我要说话

image.png

我要说话

3. 实验阶段模块

实验阶段的模块 api 处于不稳定阶段,目前 logs 的 api 在不稳定阶段。还有一些官方的 exporter、instrumentation 模块也处于不稳定阶段。 我要说话

3.1 实验阶段模块结构梳理

实验阶段模块代码结构: 我要说话

image.png

我要说话

实验阶段模块具体的列表和作用如下: 我要说话

./experimental/packages
├── api-events  # EventsAPI,含全局 EventEmitterProvider 注册、事件库&事件接口定义等
├── api-logs    # LogsAPI,含全局 LoggerProvider 注册、日志库&日志接口定义等
├── exporter-logs-otlp-grpc  # 实现 otlp pb 数据编码协议 & grpc 传输协议的 logs 导出模块
├── exporter-logs-otlp-http  # 实现 otlp json 数据编码协议 & http 传输协议的 logs 导出模块
├── exporter-logs-otlp-proto # 实现 otlp pb 数据编码协议 & http 传输协议的 logs 导出模块
├── exporter-trace-otlp-grpc # 实现 otlp pb 数据编码协议 & grpc 传输协议的 trace 导出模块
├── exporter-trace-otlp-http # 实现 otlp json 数据编码协议 & http 传输协议的 trace 导出模块
├── exporter-trace-otlp-proto # 实现 otlp pb 数据编码协议 & http 传输协议的 trace 导出模块
├── opentelemetry-browser-detector # 浏览器环境的 Resource detector 
├── opentelemetry-exporter-metrics-otlp-grpc # otlp pb 编码 & grpc 传输协议的 metrics 导出
├── opentelemetry-exporter-metrics-otlp-http # otlp json 编码 & http 传输协议的 metrics 导出
├── opentelemetry-exporter-metrics-otlp-proto # otlp pb 编码 & http 传输协议的 metrics 导出
├── opentelemetry-exporter-prometheus    # 实现 prometheus 协议的 metrics 导出(pull模式)
├── opentelemetry-instrumentation        # 提供 instrumentation 接口定义、基础类实现
                                         # 以及实现自动检测相关的方法
├── opentelemetry-instrumentation-fetch  # 基于 instrumentation 实现的 fetch trace监控模块
├── opentelemetry-instrumentation-grpc   # 基于 instrumentation 实现的 grpc trace、metrics 监控模块
├── opentelemetry-instrumentation-http   # 基于 instrumentation 实现的 http trace、metrics 监控模块
├── opentelemetry-instrumentation-xml-http-request # 基于 instrumentation 实现的 xhr trace监控模块
├── opentelemetry-sdk-node    # 提供实现了全部 Trace 和 Metrics API 的 SDK (此模块只是导出包装)
├── otlp-exporter-base        # 提供一个 otlp 导出的基类,供上报到 collector 使用
├── otlp-grpc-exporter-base   # 基于 otlp-exporter-base 实现的 grpc 版,只支持 node 
├── otlp-proto-exporter-base  # 基于 otlp-exporter-base 实现的 http + pb 版
├── otlp-transformer          # otlp 序列化方法
├── sdk-logs                  # logs 的相关实现
└── shim-opencensus           # opencensus 升级到 opentelemetry 工具包

3.2 实现自定义的 instrumentation 模块

参考文档: 我要说话

本文链接:https://www.zoucz.com/blog/2023/12/17/a833c170-9c8d-11ee-9fa0-5dbc93f9d3ee/我要说话

☞ 参与评论我要说话


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK