支付服务
该服务负责处理订单的信用卡支付。如果信用卡无效或支付无法处理,它将返回一个错误。
初始化OpenTelemetry
建议使用一个初始化文件来require
Node.js 应用程序,该文件会初始化 SDK 和自动仪表化。当在该模块的初始化器文件(opentelemetry.js
)中初始化 OpenTelemetry Node.js SDK 时,您可以选择指定要利用的自动仪表化库,或者使用getNodeAutoInstrumentations()
函数,该函数包括了大多数流行的框架。下面的示例初始化器文件(opentelemetry.js
)包含了基于标准 OpenTelemetry 环境变量的代码,用于 OTLP 导出、资源属性和服务名称的初始化。然后,它在 SDK 初始化完成后使用require
将您的应用程序引入./index.js
以启动它。
const opentelemetry = require('@opentelemetry/sdk-node');
const {
getNodeAutoInstrumentations,
} = require('@opentelemetry/auto-instrumentations-node');
const {
OTLPTraceExporter,
} = require('@opentelemetry/exporter-trace-otlp-grpc');
const {
OTLPMetricExporter,
} = require('@opentelemetry/exporter-metrics-otlp-grpc');
const { PeriodicExportingMetricReader } = require('@opentelemetry/sdk-metrics');
const {
alibabaCloudEcsDetector,
} = require('@opentelemetry/resource-detector-alibaba-cloud');
const {
awsEc2Detector,
awsEksDetector,
} = require('@opentelemetry/resource-detector-aws');
const {
containerDetector,
} = require('@opentelemetry/resource-detector-container');
const { gcpDetector } = require('@opentelemetry/resource-detector-gcp');
const {
envDetector,
hostDetector,
osDetector,
processDetector,
} = require('@opentelemetry/resources');
const sdk = new opentelemetry.NodeSDK({
traceExporter: new OTLPTraceExporter(),
instrumentations: [
getNodeAutoInstrumentations({
// only instrument fs if it is part of another trace
'@opentelemetry/instrumentation-fs': {
requireParentSpan: true,
},
}),
],
metricReader: new PeriodicExportingMetricReader({
exporter: new OTLPMetricExporter(),
}),
resourceDetectors: [
containerDetector,
envDetector,
hostDetector,
osDetector,
processDetector,
alibabaCloudEcsDetector,
awsEksDetector,
awsEc2Detector,
gcpDetector,
],
});
sdk.start();
然后,您可以使用 opentelemetry.js
来启动您的应用程序。这可以在服务的 Dockerfile
的 ENTRYPOINT
命令中完成。
ENTRYPOINT [ "node", "./opentelemetry.js" ]
追踪
为自动仪表化的 span 添加属性
在自动仪表化代码的执行过程中,您可以从上下文中获取当前 span。
const span = opentelemetry.trace.getActiveSpan();
使用 span 对象的 setAttributes
函数可以将属性添加到一个 span 中。在 chargeServiceHandler
函数中,作为匿名对象(map)的属性键/值对被添加到 span 中。
span.setAttributes({
'app.payment.amount': parseFloat(`${amount.units}.${amount.nanos}`),
});
Span 异常和状态
您可以使用 span 对象的 recordException
函数创建一个具有已处理错误的完整堆栈跟踪的 span 事件。在记录异常时,还应相应地设置 span 的状态。您可以在 chargeServiceHandler
函数中看到这一点。
span.recordException(err);
span.setStatus({ code: opentelemetry.SpanStatusCode.ERROR });
指标
创建 Meter 和 Instrument
可以使用@opentelemetry/api-metrics
包来创建 Meter。如下所示,您可以创建 Meter,然后使用创建的 Meter 创建 Instrument。
const { metrics } = require('@opentelemetry/api-metrics');
const meter = metrics.getMeter('paymentservice');
const transactionsCounter = meter.createCounter('app.payment.transactions');
Meters 和 Instruments 应该保持存在。这意味着,如果可能的话,应获取一次 Meter 或 Instrument,然后根据需要重复使用它。
日志
待定
Baggage
在此服务中,使用 OpenTelemetry Baggage 来检查请求是否是合成请求(来自负载生成器)。合成请求将不会收费,这在 span 属性中表示出来。负责实际支付处理的 charge.js
文件中,有检查 Baggage 的逻辑。
// 检查 Baggage 是否含有 synthetic_request=true,然后相应地添加 charged 属性
const baggage = propagation.getBaggage(context.active());
if (
baggage &&
baggage.getEntry('synthetic_request') &&
baggage.getEntry('synthetic_request').value == 'true'
) {
span.setAttribute('app.payment.charged', false);
} else {
span.setAttribute('app.payment.charged', true);
}