支付服务
此服务负责处理订单的信用卡支付。如果信用卡无效或付款无法处理,它将返回错误。
初始化 OpenTelemetry
建议使用初始化文件来 `require` Node.js 应用程序,该文件负责初始化 SDK 和自动仪器。在那个模块中初始化 OpenTelemetry Node.js SDK 时,您可以选择性地指定要利用的自动仪器库,或者使用 `getNodeAutoInstrumentations()` 函数,它包含了大多数流行框架。下面的初始化文件(`opentelemetry.js`)示例包含了初始化 SDK 和根据标准的 OpenTelemetry 环境变量进行自动仪器所需的所有代码,用于 OTLP 导出、资源属性和服务名称。然后它 `require` 您的应用程序在 `./index.js`,在 SDK 初始化后启动它。
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", "--require", "./opentelemetry.js", "./index.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
Meter 可以使用 `@opentelemetry/api-metrics` 包创建。您可以像下面一样创建 Meter,然后使用创建的 Meter 来创建 Instrument。
const { metrics } = require('@opentelemetry/api-metrics');
const meter = metrics.getMeter('payment');
const transactionsCounter = meter.createCounter('app.payment.transactions');
Meter 和 Instrument 应该一直存在。这意味着您应该只获取一次 Meter 或 Instrument,然后尽可能重复使用它。
日志
待定
Baggage
此服务利用 OpenTelemetry Baggage 来检查请求是否为合成请求(来自负载生成器)。合成请求将不会被收费,这会通过 Span 属性来指示。 `charge.js` 文件负责实际的支付处理,其中包含用于检查 Baggage 的逻辑。
// check baggage for synthetic_request=true, and add charged attribute accordingly
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);
}