opentelemetry-js
opentelemetry-js copied to clipboard
Root span - end time in an event driven architecture
What happened?
Steps to Reproduce
- Create a parent span
- Create a child span based on the traceparent header.
- Close the child span at the end of Service 1 after message is pushed to service bus or RabbitMQ
- Create a child span based on the traceparent header in Service 2
- ....
Expected Result
I would have expected the logs to be already shown under the parent span in a tool like azure monitor, zipkin or jaeger. I know why this happens and it's because the parent span is not being closed at the end of let's say messages being pushed through 20 services and when all are finalized the parent span is supposed to be closed.
This would happen in an entirely other service so i'm already not sure if we can close the initial parentspan based on the traceparent header ? If not starting and immediatly ending the parentspan would be a solution but then to "process runtime" isn't really adding up as the full process could take 5 minutes to go through all services.
Actual Result
As long as the parent span is not closed all childspans appear but are managed under the first "child span".
Additional Details
Is there an option to create a parent span that keeps open (never closes) which all childs are managed under so that the main parent timeline looks correct ?
I assume the setup code & package.json doesn't matter in this case as it's a functional issue i.m.o ? If anyone has advice on how to managed the parent span staying open and being logged immediatly (basicly no end date defined yet) please keep me informed.
Receive event -> queue -> Service 1 -> queue -> Service 2 -> queue -> Send to external (end) span flow below: --- create parent -------- child start - child end -- child start - child end -- child start -child end
OpenTelemetry Setup Code
// server.tracer is the decoration of the getTracer method (this all works)
// API endpoint to create the Parent Span
const span_name: string = req.headers['span-name'];
const span = server.tracer.startSpan(span_name);
// API endpoint to create a Child span
const span_name: string = req.headers['span-name'];
const traceparentDecode = util.getTraceparentSections(req.headers.traceparent);
if (traceparentDecode !== null) {
const parentcontext: ot.SpanContext = {
traceId: traceparentDecode.traceId,
spanId: traceparentDecode.parentId,
traceFlags: 1
};
const ParentSpanContext = ot.trace.setSpanContext(ot.context.active(), parentcontext);
const Span: ot.Span = server.tracer.startSpan(span_name, { startTime: new Date(req.headers['span-start-date']) }, ParentSpanContext);
Span.setStatus({
code: ot.SpanStatusCode.OK
});
}
package.json
{
"name": "otlp-api-logger",
"private": true,
"license": "UNLICENSED",
"version": "1.0.0",
"description": "",
"scripts": {
"remove_build": "rimraf build",
"start": "node build/index.js",
"dev": "yarn remove_build && yarn build && yarn start",
"build": "yarn remove_build && swc ./src --out-dir build",
"format": "prettier --write .",
"lint": "yarn lint:types && yarn lint:code && yarn format",
"lint:types": "tsc --noEmit",
"lint:style": "prettier --check .",
"lint:code": "eslint ."
},
"dependencies": {
"@fastify/helmet": "^11.0.0",
"@fastify/rate-limit": "^9.1.0",
"@fastify/swagger": "^8.3.1",
"@fastify/swagger-ui": "^1.8.1",
"@opentelemetry/exporter-trace-otlp-proto": "^0.52.1",
"@opentelemetry/sdk-trace-node": "^1.25.1",
"axios": "^1.6.7",
"dotenv": "^16.4.5",
"fastify": "^4.26.0",
"fastify-type-provider-zod": "^1.1.9",
"uuid": "^9.0.1",
"zod": "^3.22.4"
},
"devDependencies": {
"@swc/cli": "^0.1.62",
"@swc/core": "^1.3.56",
"@types/uuid": "^9.0.1",
"@typescript-eslint/eslint-plugin": "^6.4.0",
"@typescript-eslint/parser": "^7.5.0",
"eslint": "^8.0.1",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^5.1.3",
"gts": "^5.3.0",
"prettier": "^3.2.5",
"rimraf": "^5.0.5",
"swc": "^1.0.11",
"typescript": "5.5.2"
}
}
Relevant log output
No response