[Playground] OTLP-Mapper - instana to otlp span mapper#2534
[Playground] OTLP-Mapper - instana to otlp span mapper#2534abhilash-sivan wants to merge 42 commits into
Conversation
4490ab0 to
f1c0d6f
Compare
53e1fcc to
d261bc5
Compare
| spans = []; | ||
| batchingBuckets.clear(); | ||
|
|
||
| const processedSpans = |
There was a problem hiding this comment.
This is where the conversion is happening.
This seems to be the optimal place because if we convert early, then in some places we talk Instana format and it could raise unexpected issues. So before transmission seems simple and maintanable
There was a problem hiding this comment.
Should we do this here or just after the current BE transformation,
https://github.com/instana/nodejs/pull/2534/changes?utm_source=chatgpt.com#diff-462ace70d7ac6eb4cd6f82756059c88629bfad1463fde0498d89106d7ccc8104L193
Right now we’re applying the transformation after collecting all spans. IMO it would be cleaner to do it before calling transmitSpans, so the transmit layer only deals with already-transformed spans.
TBD
There was a problem hiding this comment.
Yeah, I agree. This would be a more cleaner way
// Transform internal span data format into external (backend) readable format.
span = applySpanTransformation(span);
Just after this transformation, we can call the Otel transformation.
There was a problem hiding this comment.
One thing we have to consider is that currently all the spans intended for transmission — i.e., the array of spans — are converted together. If we do it in the above-mentioned area, we will have to process the spans individually.
There was a problem hiding this comment.
Note: TBD — Transform each span to OTLP format immediately in addSpan and store them in OTLP format in the buffer if batching is enabled. This would require changes to the batching logic.
There was a problem hiding this comment.
How do you want to organize the agent ports etc?
OTLP mode is on -> port will change.
There is something missing.
There was a problem hiding this comment.
Also:
How can we skip the agent announcement cycle when connecting to an otel collector later?
Did you draw that path as well to confirm the architecture?
There was a problem hiding this comment.
No, I haven’t worked much on the architecture yet. I can work on the dynamic port connections part, and I’ll also think through the agent announcement cycle and how we can skip it when connecting to an OTel collector
This needs to be communicated in the next WG. Traces & Metrics mapping is required. |
08a2757 to
e827e9c
Compare
e827e9c to
d6c01a6
Compare
| * RabbitMQ-specific mappings | ||
| * Extends base messaging with RabbitMQ-specific fields | ||
| */ | ||
| rabbitmq: { |
There was a problem hiding this comment.
Not verified rabbitmq per se. It's just to show how we differentiate children under messaging or any other group.
There was a problem hiding this comment.
But for RabbitMQ, there’s nothing really common with BASE_MAPPINGS.messaging. I don’t think any of the others share much with it either, apart from Kafka.
| mappings: SPAN_ATTRIBUTE_MAPPINGS.kafka, | ||
| prefix: 'messaging.kafka', | ||
| additionalAttributes: { | ||
| 'messaging.system': 'kafka' |
There was a problem hiding this comment.
Why do we need that here? If we have already a custom kafka mapping object?
There was a problem hiding this comment.
messaging.system is an additional attribute that we append to the span. For Kafka, the system name also happens to be kafka, so it may seem redundant at first glance.
However, additionalAttributes is intended for constant or computed attributes that do not directly map from a single field inside span.data.kafka.
messaging.system falls into that category since it is effectively a constant defined per transformer, rather than something extracted from the incoming span payload itself.
I have changed this to: 'messaging.system': this.systemName
which will fetch the appropriate value in this case
| scopeSpans: [ | ||
| { | ||
| scope: { | ||
| name: '@instana/collector', |
There was a problem hiding this comment.
nitpick: we might need to update the package name later. Since this transformer lives in core, it could also be used by the serverless package in the future. It would be better to dynamically fetch the package name instead of hardcoding it.
| * | ||
| * @see https://opentelemetry.io/docs/specs/semconv/database/ | ||
| */ | ||
| database: { |
There was a problem hiding this comment.
It should be databases since that is the naming pattern we already use. You can also see this in the IBM documentation and in the directory structure under core/src/tracing/instrumentation
|
|
||
| 'use strict'; | ||
|
|
||
| const { getOtlpAttributeMappings } = require('./otlp_mapper/mapper'); |
There was a problem hiding this comment.
this file still needed?
There was a problem hiding this comment.
yes, metrics are handled here
|
|
||
| attributes.push({ | ||
| key: 'telemetry.sdk.version', | ||
| value: { stringValue: '3.0.0' } |
There was a problem hiding this comment.
nit pick: This value is currently hard coded, can we source this from package.json? or add todo comment for fixing this later
|
|
||
| // Service name from span data | ||
| const serviceName = | ||
| instanaSpan.data?.service || process.env.OTEL_SERVICE_NAME || process.env.SERVICE_NAME || 'unknown-service'; |
There was a problem hiding this comment.
What is process.env.SERVICE_NAME? Did you mean process.env.INSTANA_SERVICE_NAME?
May be here, we can use config.serviceName as well.
instanaSpan.data?.service || process.env.OTEL_SERVICE_NAME || config.serviceName;
| * RabbitMQ-specific mappings | ||
| * Extends base messaging with RabbitMQ-specific fields | ||
| */ | ||
| rabbitmq: { |
There was a problem hiding this comment.
But for RabbitMQ, there’s nothing really common with BASE_MAPPINGS.messaging. I don’t think any of the others share much with it either, apart from Kafka.
| * @see https://opentelemetry.io/docs/specs/semconv/general/attributes/#server-and-client-attributes | ||
| */ | ||
| peer: { | ||
| hostname: { key: 'net.peer.name' }, |
There was a problem hiding this comment.
net.peer.name and net.peer.port are depreacted.
net.peer.name => server.address
net.peer.port => server.port
https://opentelemetry.io/blog/2023/http-conventions-declared-stable/#http-client-span-attributes
| /** | ||
| * Protocol configuration for transformer instantiation and semantic system names | ||
| */ | ||
| const PROTOCOL_CONFIG = { |
There was a problem hiding this comment.
PROTOCOL_CONFIG feels slightly misleading because this object is not really defining protocols, it’s mapping Instana span types to OTEL semantic convention system names.
We can reduce duplication in PROTOCOL_CONFIG by treating systemName as defaulting to spanType.
Maybe simplify to something like:
const OTEL_SYSTEM_NAMES = {
http: 'http',
kafka: 'kafka',
rabbitmq: 'rabbitmq',
mongo: 'mongodb'
};
Then:
function getProtocolConfig(spanType) {
return {
spanType: spanType,
systemName: OTEL_SYSTEM_NAMES[spanType] || spanType
};
}
| * | ||
| * When a span contains multiple data keys (e.g., both 'mongo' and 'peer'), | ||
| * this array determines which transformer to use. Primary span types are | ||
| * checked first, auxiliary data types last. |
| * @returns {string} OTLP trace ID (32-character hex) | ||
| */ | ||
| function convertTraceId(instanaTraceId) { | ||
| if (!instanaTraceId) return '00000000000000000000000000000000'; |
There was a problem hiding this comment.
IMO this may not be a valid case, but if instanaTraceId is falsy we silently convert it to an all-zero trace ID. How is this expected to be handled? Do we have any known scenarios where this can happen? 🤔
| http: HttpTransformer, | ||
|
|
||
| // Messaging protocols | ||
| kafka: KafkaTransformer, |
There was a problem hiding this comment.
This is wrong IMO
Either we instantiate all of them here or none.
So we have to go with "all".
rabbitmq: span =>
new MessagingTransformer
UI: https://instana.io/s/B2R0pfHbSpaV5jXmQNDd7w
This is just a playground where we convert Instana spans to Otel spans and send them to the Otel backend.
INSTANA_OTLP_FORMAT=true SERVICE_NAME=test-nodejs-service INSTANA_DEBUG=true node index.jshttps://instana.io/s/Ehe2Zhb7QyKyxrmQg0fK8Q The BE uses path_tpl or url values ot show in the UI, so we mapped the otel span name to the same data from Instana span.
After conversion using the script: