-
Notifications
You must be signed in to change notification settings - Fork 1k
/
payment.md
167 lines (138 loc) · 4.93 KB
/
payment.md
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
---
title: Payment Service
linkTitle: Payment
aliases: [paymentservice]
cSpell:ignore: nanos
---
This service is responsible to process credit card payments for orders. It will
return an error if the credit card is invalid or the payment can not be
processed.
[Payment service source](https://github.com/open-telemetry/opentelemetry-demo/blob/main/src/paymentservice/)
## Initializing OpenTelemetry
It is recommended to `require` Node.js app using an initializer file that
initializes the SDK and auto-instrumentation. When initializing the
OpenTelemetry Node.js SDK in that module, you optionally specify which
auto-instrumentation libraries to leverage, or make use of the
`getNodeAutoInstrumentations()` function which includes most popular frameworks.
The below example of an initializer file (`opentelemetry.js`) contains all code
required to initialize the SDK and auto-instrumentation based on standard
OpenTelemetry environment variables for OTLP export, resource attributes, and
service name. It then `require`s your app at `./index.js` to start it up once
the SDK is initialized.
```javascript
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();
```
You can then use `opentelemetry.js` to start your app. This can be done in the
`ENTRYPOINT` command for the service's `Dockerfile`.
```dockerfile
ENTRYPOINT [ "node", "./opentelemetry.js" ]
```
## Traces
### Add attributes to auto-instrumented spans
Within the execution of auto-instrumented code you can get current span from
context.
```javascript
const span = opentelemetry.trace.getActiveSpan();
```
Adding attributes to a span is accomplished using `setAttributes` on the span
object. In the `chargeServiceHandler` function an attributes is added to the
span as an anonymous object (map) for the attribute key/values pair.
```javascript
span.setAttributes({
'app.payment.amount': parseFloat(`${amount.units}.${amount.nanos}`),
});
```
### Span Exceptions and status
You can use the span object's `recordException` function to create a span event
with the full stack trace of a handled error. When recording an exception also
be sure to set the span's status accordingly. You can see this in the
`chargeServiceHandler` function
```javascript
span.recordException(err);
span.setStatus({ code: opentelemetry.SpanStatusCode.ERROR });
```
## Metrics
### Creating Meters and Instruments
Meters can be created using the `@opentelemetry/api-metrics` package. You can
create meters as seen below, and then use the created meter to create
instruments.
```javascript
const { metrics } = require('@opentelemetry/api-metrics');
const meter = metrics.getMeter('paymentservice');
const transactionsCounter = meter.createCounter('app.payment.transactions');
```
Meters and Instruments are supposed to stick around. This means you should get a
Meter or an Instrument once , and then re-use it as needed, if possible.
## Logs
TBD
## Baggage
OpenTelemetry Baggage is leveraged in this service to check if the request is
synthetic (from the load generator). Synthetic requests will not be charged,
which is indicated with a span attribute. The `charge.js` file which does the
actual payment processing, has logic to check the baggage.
```javascript
// 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);
}
```