mirror of
https://github.com/denoland/deno.git
synced 2025-01-20 20:42:19 -05:00
feat(unstable): add basic support for otel trace links (#27727)
Currently only links with no attributes.
This commit is contained in:
parent
395628026f
commit
5e9b3712de
5 changed files with 198 additions and 15 deletions
|
@ -42,6 +42,7 @@ use opentelemetry::metrics::InstrumentBuilder;
|
||||||
use opentelemetry::metrics::MeterProvider as _;
|
use opentelemetry::metrics::MeterProvider as _;
|
||||||
use opentelemetry::otel_debug;
|
use opentelemetry::otel_debug;
|
||||||
use opentelemetry::otel_error;
|
use opentelemetry::otel_error;
|
||||||
|
use opentelemetry::trace::Link;
|
||||||
use opentelemetry::trace::SpanContext;
|
use opentelemetry::trace::SpanContext;
|
||||||
use opentelemetry::trace::SpanId;
|
use opentelemetry::trace::SpanId;
|
||||||
use opentelemetry::trace::SpanKind;
|
use opentelemetry::trace::SpanKind;
|
||||||
|
@ -94,6 +95,7 @@ deno_core::extension!(
|
||||||
op_otel_span_attribute1,
|
op_otel_span_attribute1,
|
||||||
op_otel_span_attribute2,
|
op_otel_span_attribute2,
|
||||||
op_otel_span_attribute3,
|
op_otel_span_attribute3,
|
||||||
|
op_otel_span_add_link,
|
||||||
op_otel_span_update_name,
|
op_otel_span_update_name,
|
||||||
op_otel_metric_attribute3,
|
op_otel_metric_attribute3,
|
||||||
op_otel_metric_record0,
|
op_otel_metric_record0,
|
||||||
|
@ -1324,17 +1326,6 @@ impl OtelSpan {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[fast]
|
|
||||||
fn drop_link(&self) {
|
|
||||||
let mut state = self.0.borrow_mut();
|
|
||||||
match &mut **state {
|
|
||||||
OtelSpanState::Recording(span) => {
|
|
||||||
span.links.dropped_count += 1;
|
|
||||||
}
|
|
||||||
OtelSpanState::Done(_) => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[fast]
|
#[fast]
|
||||||
fn end(&self, end_time: f64) {
|
fn end(&self, end_time: f64) {
|
||||||
let end_time = if end_time.is_nan() {
|
let end_time = if end_time.is_nan() {
|
||||||
|
@ -1448,6 +1439,48 @@ fn op_otel_span_update_name<'s>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[op2(fast)]
|
||||||
|
fn op_otel_span_add_link<'s>(
|
||||||
|
scope: &mut v8::HandleScope<'s>,
|
||||||
|
span: v8::Local<'s, v8::Value>,
|
||||||
|
trace_id: v8::Local<'s, v8::Value>,
|
||||||
|
span_id: v8::Local<'s, v8::Value>,
|
||||||
|
#[smi] trace_flags: u8,
|
||||||
|
is_remote: bool,
|
||||||
|
#[smi] dropped_attributes_count: u32,
|
||||||
|
) -> bool {
|
||||||
|
let trace_id = parse_trace_id(scope, trace_id);
|
||||||
|
if trace_id == TraceId::INVALID {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
let span_id = parse_span_id(scope, span_id);
|
||||||
|
if span_id == SpanId::INVALID {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
let span_context = SpanContext::new(
|
||||||
|
trace_id,
|
||||||
|
span_id,
|
||||||
|
TraceFlags::new(trace_flags),
|
||||||
|
is_remote,
|
||||||
|
TraceState::NONE,
|
||||||
|
);
|
||||||
|
|
||||||
|
let Some(span) =
|
||||||
|
deno_core::_ops::try_unwrap_cppgc_object::<OtelSpan>(scope, span)
|
||||||
|
else {
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
let mut state = span.0.borrow_mut();
|
||||||
|
if let OtelSpanState::Recording(span) = &mut **state {
|
||||||
|
span.links.links.push(Link::new(
|
||||||
|
span_context,
|
||||||
|
vec![],
|
||||||
|
dropped_attributes_count,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
struct OtelMeter(opentelemetry::metrics::Meter);
|
struct OtelMeter(opentelemetry::metrics::Meter);
|
||||||
|
|
||||||
impl deno_core::GarbageCollected for OtelMeter {}
|
impl deno_core::GarbageCollected for OtelMeter {}
|
||||||
|
|
|
@ -15,6 +15,7 @@ import {
|
||||||
op_otel_metric_record2,
|
op_otel_metric_record2,
|
||||||
op_otel_metric_record3,
|
op_otel_metric_record3,
|
||||||
op_otel_metric_wait_to_observe,
|
op_otel_metric_wait_to_observe,
|
||||||
|
op_otel_span_add_link,
|
||||||
op_otel_span_attribute1,
|
op_otel_span_attribute1,
|
||||||
op_otel_span_attribute2,
|
op_otel_span_attribute2,
|
||||||
op_otel_span_attribute3,
|
op_otel_span_attribute3,
|
||||||
|
@ -186,7 +187,6 @@ interface OtelSpan {
|
||||||
spanContext(): SpanContext;
|
spanContext(): SpanContext;
|
||||||
setStatus(status: SpanStatusCode, errorDescription: string): void;
|
setStatus(status: SpanStatusCode, errorDescription: string): void;
|
||||||
dropEvent(): void;
|
dropEvent(): void;
|
||||||
dropLink(): void;
|
|
||||||
end(endTime: number): void;
|
end(endTime: number): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -359,14 +359,24 @@ class Span {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
addLink(_link: Link): Span {
|
addLink(link: Link): Span {
|
||||||
this.#otelSpan?.dropLink();
|
const droppedAttributeCount = (link.droppedAttributesCount ?? 0) +
|
||||||
|
(link.attributes ? ObjectKeys(link.attributes).length : 0);
|
||||||
|
const valid = op_otel_span_add_link(
|
||||||
|
this.#otelSpan,
|
||||||
|
link.context.traceId,
|
||||||
|
link.context.spanId,
|
||||||
|
link.context.traceFlags,
|
||||||
|
link.context.isRemote ?? false,
|
||||||
|
droppedAttributeCount,
|
||||||
|
);
|
||||||
|
if (!valid) return this;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
addLinks(links: Link[]): Span {
|
addLinks(links: Link[]): Span {
|
||||||
for (let i = 0; i < links.length; i++) {
|
for (let i = 0; i < links.length; i++) {
|
||||||
this.#otelSpan?.dropLink();
|
this.addLink(links[i]);
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,10 @@
|
||||||
},
|
},
|
||||||
"args": "run -A main.ts metric.ts",
|
"args": "run -A main.ts metric.ts",
|
||||||
"output": "metric.out"
|
"output": "metric.out"
|
||||||
|
},
|
||||||
|
"links": {
|
||||||
|
"args": "run -A main.ts links.ts",
|
||||||
|
"output": "links.out"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
96
tests/specs/cli/otel_basic/links.out
Normal file
96
tests/specs/cli/otel_basic/links.out
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
{
|
||||||
|
"spans": [
|
||||||
|
{
|
||||||
|
"traceId": "00000000000000000000000000000001",
|
||||||
|
"spanId": "0000000000000001",
|
||||||
|
"traceState": "",
|
||||||
|
"parentSpanId": "",
|
||||||
|
"flags": 1,
|
||||||
|
"name": "example span",
|
||||||
|
"kind": 1,
|
||||||
|
"startTimeUnixNano": "[WILDCARD]",
|
||||||
|
"endTimeUnixNano": "[WILDCARD]",
|
||||||
|
"attributes": [],
|
||||||
|
"droppedAttributesCount": 0,
|
||||||
|
"events": [],
|
||||||
|
"droppedEventsCount": 0,
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"traceId": "1234567890abcdef1234567890abcdef",
|
||||||
|
"spanId": "1234567890abcdef",
|
||||||
|
"traceState": "",
|
||||||
|
"attributes": [],
|
||||||
|
"droppedAttributesCount": 0,
|
||||||
|
"flags": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"droppedLinksCount": 0,
|
||||||
|
"status": {
|
||||||
|
"message": "",
|
||||||
|
"code": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"traceId": "00000000000000000000000000000002",
|
||||||
|
"spanId": "0000000000000002",
|
||||||
|
"traceState": "",
|
||||||
|
"parentSpanId": "",
|
||||||
|
"flags": 1,
|
||||||
|
"name": "example span",
|
||||||
|
"kind": 1,
|
||||||
|
"startTimeUnixNano": "[WILDCARD]",
|
||||||
|
"endTimeUnixNano": "[WILDCARD]",
|
||||||
|
"attributes": [],
|
||||||
|
"droppedAttributesCount": 0,
|
||||||
|
"events": [],
|
||||||
|
"droppedEventsCount": 0,
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"traceId": "1234567890abcdef1234567890abcdef",
|
||||||
|
"spanId": "1234567890abcdef",
|
||||||
|
"traceState": "",
|
||||||
|
"attributes": [],
|
||||||
|
"droppedAttributesCount": 0,
|
||||||
|
"flags": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"droppedLinksCount": 0,
|
||||||
|
"status": {
|
||||||
|
"message": "",
|
||||||
|
"code": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"traceId": "00000000000000000000000000000003",
|
||||||
|
"spanId": "0000000000000003",
|
||||||
|
"traceState": "",
|
||||||
|
"parentSpanId": "",
|
||||||
|
"flags": 1,
|
||||||
|
"name": "example span",
|
||||||
|
"kind": 1,
|
||||||
|
"startTimeUnixNano": "[WILDCARD]",
|
||||||
|
"endTimeUnixNano": "[WILDCARD]",
|
||||||
|
"attributes": [],
|
||||||
|
"droppedAttributesCount": 0,
|
||||||
|
"events": [],
|
||||||
|
"droppedEventsCount": 0,
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"traceId": "1234567890abcdef1234567890abcdef",
|
||||||
|
"spanId": "1234567890abcdef",
|
||||||
|
"traceState": "",
|
||||||
|
"attributes": [],
|
||||||
|
"droppedAttributesCount": 2,
|
||||||
|
"flags": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"droppedLinksCount": 0,
|
||||||
|
"status": {
|
||||||
|
"message": "",
|
||||||
|
"code": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"logs": [],
|
||||||
|
"metrics": []
|
||||||
|
}
|
40
tests/specs/cli/otel_basic/links.ts
Normal file
40
tests/specs/cli/otel_basic/links.ts
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
|
import { trace } from "npm:@opentelemetry/api@1.9.0";
|
||||||
|
|
||||||
|
const tracer = trace.getTracer("example-tracer");
|
||||||
|
|
||||||
|
const span1 = tracer.startSpan("example span", {
|
||||||
|
links: [{
|
||||||
|
context: {
|
||||||
|
traceId: "1234567890abcdef1234567890abcdef",
|
||||||
|
spanId: "1234567890abcdef",
|
||||||
|
traceFlags: 1,
|
||||||
|
},
|
||||||
|
}],
|
||||||
|
});
|
||||||
|
span1.end();
|
||||||
|
|
||||||
|
const span2 = tracer.startSpan("example span");
|
||||||
|
span2.addLink({
|
||||||
|
context: {
|
||||||
|
traceId: "1234567890abcdef1234567890abcdef",
|
||||||
|
spanId: "1234567890abcdef",
|
||||||
|
traceFlags: 1,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
span2.end();
|
||||||
|
|
||||||
|
const span3 = tracer.startSpan("example span");
|
||||||
|
span3.addLink({
|
||||||
|
context: {
|
||||||
|
traceId: "1234567890abcdef1234567890abcdef",
|
||||||
|
spanId: "1234567890abcdef",
|
||||||
|
traceFlags: 1,
|
||||||
|
},
|
||||||
|
attributes: {
|
||||||
|
key: "value",
|
||||||
|
},
|
||||||
|
droppedAttributesCount: 1,
|
||||||
|
});
|
||||||
|
span3.end();
|
Loading…
Add table
Reference in a new issue