@ coralogix/ 开元- 剖面
为节点.js提供OpenTeleometry连续剖面SDK. 使用 @datadog/pprof 并导出为 OTLP( 默认) 或本地 pprof .
特征
- 长相分析 定期采集JS堆积样本(默认为100Hz),捕获CPU和闲置时间
- 堆积剖析 ——取出内存分配样本,以识别内存被消耗之处
- 追踪关联 - 附带
trace_id编号 :span_id活性OTel跨度样本标签 - Span 属性提取 ——所选择的复制跨度属性(例如.
http.route在剖面图样本上 - 源地图支持 ——地图编译 JS 文件名/行回溯到原始类型Script源
- OTLP gRPC 导出( 默认) ——向OTel采集器/OTLP兼容后端发送OTLP配置文件
- Pprof 推出导出 ——选入替代,将生 pprof 发送给OTel Collector 的
pprofreceiver全部跳过 OTLP 转换 - OTel 环境变量 ——敬礼
OTEL_SERVICE_NAME, (中文(简体) ),OTEL_RESOURCE_ATTRIBUTES, (中文(简体) ),OTEL_PROFILES_EXPORTER等 (中文(简体) ). - 控制台出口国 ——调试输出人提供原始 pprof 内容
安装
npm install @coralogix/opentelemetry-profiling
追踪关联:
npm install @opentelemetry/api @opentelemetry/sdk-trace-node
快速启动
import { ProfilingProvider } from '@coralogix/opentelemetry-profiling';
const provider = new ProfilingProvider({
serviceName: 'my-service',
});
await provider.start();
// Your application code...
// On shutdown
await provider.stop();
配置
程序化
import {
ProfilingProvider,
ConsoleProfileExporter,
OtlpGrpcProfileExporter,
} from '@coralogix/opentelemetry-profiling';
const provider = new ProfilingProvider({
// Service identification
serviceName: 'my-service',
resource: {
'deployment.environment': 'production',
'service.version': '1.2.3',
},
// Profiler toggles
wallProfilingEnabled: true, // default: true
heapProfilingEnabled: true, // default: true
// Collection interval — how often profiles are flushed to the exporter
collectionIntervalMs: 10_000, // default: 10000 (10s)
// Wall profiler tuning
wallSamplingIntervalMicros: 10_000, // default: 10000 (100Hz)
// Heap profiler tuning
heapSamplingIntervalBytes: 524_288, // default: 524288 (512KB)
heapStackDepth: 64, // default: 64
// Trace-profile correlation (requires @opentelemetry/api)
traceCorrelation: true,
// Copy these span attributes onto profiling samples
spanAttributeKeys: ['http.route', 'rpc.method'],
// Source maps — map compiled JS back to original TypeScript sources
sourceMapSearchPaths: ['./dist'],
// Exporters — defaults to [OtlpGrpcProfileExporter]
exporters: [
new OtlpGrpcProfileExporter({
endpoint: 'http://localhost:4317',
headers: { 'x-api-key': 'secret' },
}),
new ConsoleProfileExporter({ verbosity: 'basic' }),
],
});
环境变量
| 变量 | 说明 | 默认 |
|---|---|---|
OTEL_SERVICE_NAME | 服务名称 | —— 说 |
OTEL_RESOURCE_ATTRIBUTES | 逗号分隔 key=value 双对 | —— 说 |
OTEL_PROFILES_EXPORTER | 逗号分离的出口商 : pprof, (中文(简体) ), otlp, (中文(简体) ), console, (中文(简体) ), none | otlp |
OTEL_EXPORTER_PPROF_ENDPOINT | Pprof 推出端点 | http://localhost:4040/v1/pprof |
OTEL_EXPORTER_PPROF_HEADERS | Pprof 推取页眉( 已合并分离) k=v(中文(简体) ) | —— 说 |
OTEL_EXPORTER_OTLP_PROFILES_ENDPOINT | 剖面图特定OTLP gRPC 端点 | —— 说 |
OTEL_EXPORTER_OTLP_ENDPOINT | 一般OTLP gRPC 端点(回落) | http://localhost:4317 |
OTEL_EXPORTER_OTLP_PROFILES_HEADERS | 配置文件 OTLP 标题 | —— 说 |
OTEL_EXPORTER_OTLP_HEADERS | 一般OTLP头(倒置) | —— 说 |
OTEL_PROFILING_WALL_ENABLED | 启用时钟配置器( M)true编号 :false(中文(简体) ) | true |
OTEL_PROFILING_HEAP_ENABLED | 启用堆积剖析器( E)true编号 :false(中文(简体) ) | true |
OTEL_PROFILING_COLLECTION_INTERVAL_MS | 配置文件收集间隔 | 10000 |
OTEL_PROFILING_WALL_SAMPLING_INTERVAL_MICROS | 时间间隔(微秒) | 10000 (100赫兹) |
OTEL_PROFILING_HEAP_SAMPLING_INTERVAL_BYTES | 堆积分配样本间隔( 字节) | 配置器默认 |
OTEL_PROFILING_HEAP_STACK_DEPTH | 堆放样本的最大堆栈框架 | 配置器默认 |
OTEL_PROFILING_HEAP_SAMPLE_TYPES | 堆积样本类型 : bytes, (中文(简体) ), objects,或 both | both |
OTEL_PROFILING_TRACE_CORRELATION | 附加 trace_id编号 :span_id 标签(true编号 :false(中文(简体) ) | true |
OTEL_PROFILING_SPAN_ATTRIBUTE_KEYS | 以逗号分隔的属性键复制到样本 | —— 说 |
OTEL_PROFILING_SOURCE_MAP_SEARCH_PATHS | 为源地图扫描的逗号分隔目录 | —— 说 |
方案配置压倒了环境变量.
出口商
Pprof 推( 选入)
将 HTTP/1.1 上的原始 prof 字节( gzipped) 发送给 OTel 收集器 pprofreceiver 推出端点( r)POST /v1/pprof) (中文(简体) ). 在SDK中没有pprof OTLP转换发生——由收藏家完成.
通过 OTEL_PROFILES_EXPORTER=pprof。 。 。 .
资源属性作为单个 HTTP 标题发送 Otel-Resource-Attributes: k=v,k=v (语法与 OTEL_RESOURCE_ATTRIBUTES) (中文(简体) ). SDK又说 profiler.type=wall|heap 转到每个导出的资源,这样后端就可以区分配置类型。 收藏器必须配置为 include_metadata: true (单位:千美元) transform 将信头推向资源属性的处理器——参见 使用 OpenTelemetry 收集器。 。 。 .
import { PprofPushProfileExporter } from '@coralogix/opentelemetry-profiling';
const exporter = new PprofPushProfileExporter({
endpoint: 'http://collector:4040/v1/pprof',
headers: { authorization: 'Bearer …' },
});
OTLP gRPC( 默认)
通过gRPC(HTTP/2 + protobuf)向一个OTLP相容的采集器发送剖面. 使用节点的内置 http2 模块 - 否 @grpc/grpc-js 依赖性。 Pprof OTLP转换发生在SDK.
默认选择;并 OTEL_PROFILES_EXPORTER=otlp (或 otlp_grpc) (中文(简体) ).
import { OtlpGrpcProfileExporter } from '@coralogix/opentelemetry-profiling';
const exporter = new OtlpGrpcProfileExporter({
endpoint: 'http://localhost:4317',
});
控制台
打印原始 pprof 内容到 stdout 。 三个动词级:
import { ConsoleProfileExporter } from '@coralogix/opentelemetry-profiling';
// basic — one summary line
new ConsoleProfileExporter({ verbosity: 'basic' });
// normal (default) — summary + resource attrs + table sizes + period info
new ConsoleProfileExporter({ verbosity: 'normal' });
// detailed — also includes top-N functions by leaf sample value
new ConsoleProfileExporter({ verbosity: 'detailed', topN: 10 });
自定义
执行 ProfileExporter 接口。 每个出口商都收到原始pprof——根据需要编码或转换.
import { ProfileExporter, ProfileData, buildRequest, encodeRequest } from '@coralogix/opentelemetry-profiling';
class MyExporter implements ProfileExporter {
async export(data: ProfileData): Promise<void> {
// data.profile — pprof-format Profile object
// data.profileType — 'wall' | 'heap'
// data.startedAt / data.stoppedAt — collection window
// data.resource — resolved resource attributes
}
async shutdown(): Promise<void> {
// cleanup
}
}
如果您的出口商需要OTLP ExportProfilesServiceRequest,按要求建立:
const request = buildRequest(
[{ profile: data.profile, profileType: data.profileType, startedAt: data.startedAt, stoppedAt: data.stoppedAt }],
data.resource,
);
const encoded = encodeRequest(request);
追踪文件关联
何时 @opentelemetry/api 已安装和 a TracerProvider 正在激活, 启用 traceCorrelation 将剖析样本与采集到的跨度联系起来.
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
import { ProfilingProvider } from '@coralogix/opentelemetry-profiling';
// Set up tracing first
const tracerProvider = new NodeTracerProvider();
tracerProvider.register();
// Then profiling
const profiling = new ProfilingProvider({
serviceName: 'my-service',
traceCorrelation: true,
});
await profiling.start();
每个在时间跨度活动时捕捉到的壁时点样本 trace_id 财务报告和审定财务报表 span_id prof 输出中的标签.
- Pprof 推动路径:标签通过收藏家的pprof接收器翻译器作为普通的样本属性来行走. 后端键从
trace_id编号 :span_id直接属性. - OTLP 路径: 转换器将这些标签推广到OTLP
Link表格 (单位:千美元)sample.linkIndex) (中文(简体) ).
任一形状都保留相同信息;只有结构布局不同.
平面属性提取
使用 spanAttributeKeys 将特定跨度属性复制到剖析样本上。 这使得通过HTTP路由或RPC方法等属性来组合和过滤配置文件成为可能.
const profiling = new ProfilingProvider({
traceCorrelation: true,
spanAttributeKeys: ['http.route', 'rpc.method', 'rpc.service'],
});
属性从 配置文件收集时间,而不是当时间跨度被激活。 这意味着在跨度创建后设定属性(例如. http.route 快速路由匹配后由 Express 设置)被正确捕获.
说明: Span 属性提取只用于壁点配置图. 使用 V8 的堆积配置文件
AllocationProfiler它没有每个分配上下文的捕捉, 所以没有办法知道哪个跨度是活跃的 当某个分配发生.
使用 OpenTelemetry 收集器
默认: pprof 推
SDK向收藏家发送原始 pprof pprofreceiver 推出终点。 资源属性在 Otel-Resource-Attributes HTTP 头,所以接收器需要 include_metadata: true (单位:千美元) transform 将信头抬入 resource.attributes数字 :
receivers:
pprof:
server:
endpoint: 0.0.0.0:4040
include_metadata: true
processors:
transform:
profile_statements:
- set(resource.attributes, ParseKeyValue(metadata["otel-resource-attributes"], "=", ","))
exporters:
debug:
verbosity: detailed
service:
pipelines:
profiles:
receivers: [pprof]
processors: [transform]
exporters: [debug]
没有 transform 规则,配置文件将抵达时没有 service.name 或其它资源属性——由信头携带,但没有任何东西默认促进它们.
OTLP gRPC 化学反应
如果您选择退出 pprof 推 (OTEL_PROFILES_EXPORTER=otlp),标准OTLP接收器适用:
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
exporters:
debug:
verbosity: detailed
service:
pipelines:
profiles:
receivers: [otlp]
exporters: [debug]
说明: 收藏者必须拥有
--feature-gates=+service.profilesSupport旗帜集(或运行配置支持为GA的版本).
如何运作
@datadog/pprof驱动实际采样——它使用本地加成setitimer(SIGALRM)用于墙上点采样和V8'sAllocationProfiler堆积取样- 收藏循环 运行
collectionIntervalMs(默认 10s),呼叫stop(restart=true)墙壁剖析器和profile()在堆积剖析器上 - 每名出口商编码 ——提供者将原始pprof交给每个被配置的出口商. pprof将导出者gzip-en编码为字节并POST. OTLP出口商在当地转换 pprof → OTLP(以字典为基础的字符串/功能/位置/stack表),编码为protobuf,用gRPC长度前置编码来设定,并通过HTTP/2发送. 转换只发生在需要转换的出口商身上.
长相对 CPU 剖面
无论JavaScript是否执行,墙壁剖面仪都按正常的墙钟间隔取出样本. 这意味着:
- On-CPU 工作( 计算) 显示为函数框架
- 关闭CPU时间( I/O等, 事件循环闲置) 显示为
(idle) - 两人都被俘虏,完整地描绘了时间花在什么地方
Async 堆栈限制
当节点被击中时 await,调用堆栈是无伤的——没有可取样的堆栈. 这意味着一个功能像 await db.query() 显示为 (idle) 样本,而不是归结于 db.query启用 traceCorrelation 将闲暇时间分配给活跃的间距,有助于弥合这一差距.
来源地图
当剖析 TypeScript 或捆绑的应用程序时, V8 报告从编译的 JS 输出中函数名称和文件名 。 启用 sourceMapSearchPaths 将这些文件映射回原始源文件 :
const provider = new ProfilingProvider({
sourceMapSearchPaths: ['./dist'],
});
await provider.start();
提供者扫描指定的目录 .js.map 启动时的文件。 配置文件然后显示原文件名和行号(例如:. src/handler.ts:42 改为 dist/handler.js:120) (中文(简体) ).
需要您的构建以发布源地图( 例如) . "sourceMap": true 内 tsconfig.json) (中文(简体) ).
实例
见 examples/ 目录 :
basic.ts- 与控制台出口商的最小设置otlp-collector.ts- 出口到OTel收集器source-maps.ts——将JS编成的地图反馈至TypeScript来源
API 参考
ProfilingProviderConfig
| 选项 | 类型 | 默认 | 说明 |
|---|---|---|---|
serviceName | string | —— 说 | 服务名称( 可选的; 如果未设置则从资源中删除) |
resource | Record<string, string | number | boolean> | —— 说 | 追加资源属性 |
exporters | ProfileExporter[] | [OtlpGrpcProfileExporter] | 导出例 |
traceCorrelation | boolean | true | 将样本与活动OTel相接 |
spanAttributeKeys | string[] | [] | 复制到样本的扩展属性 |
wallProfilingEnabled | boolean | true | 启用时钟配置 |
heapProfilingEnabled | boolean | true | 启用堆积剖析 |
collectionIntervalMs | number | 10000 | 配置文件被冲出的次数 |
wallSamplingIntervalMicros | number | 10000 | 墙壁剖面仪采样间隔( 100Hz) |
heapSamplingIntervalBytes | number | 524288 | 高压剖面仪取样间隔(512KB) |
heapStackDepth | number | 64 | 堆积样本的最大堆积深度 |
sourceMapSearchPaths | string[] | —— 说 | 要扫描的目录 .js.map 文件 |
ProfilingProvider
| 方法 | 说明 |
|---|---|
new ProfilingProvider(config?) | 创建可选配置的提供者 |
start(): Promise<void> | 启动剖析器并开始定期收集 |
stop(): Promise<void> | 停止配置文件、 冲出最终配置文件、 关机出口商 |
ProfileData
| 外地 | 类型 | 说明 |
|---|---|---|
profile | Profile (从) pprof-format(中文(简体) ) | 原始 pprof 配置文件 |
profileType | 'wall' | 'heap' | 配置类型 |
startedAt | Date | 开始收藏窗口 |
stoppedAt | Date | 收藏窗口结束 |
resource | ResourceAttributes | 解析此配置的资源属性 |
ProfileExporter
| 方法 | 说明 |
|---|---|
export(data: ProfileData): Promise<void> | 导出单个配置文件 |
shutdown(): Promise<void> | 清理资源 |
许可证
阿帕奇 - 2.0