Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: OpenTelemetry logger #1043

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft

WIP: OpenTelemetry logger #1043

wants to merge 1 commit into from

Conversation

sandhose
Copy link
Member

This is very much WIP, but works.

It basically implements a ILogger which sends spans through the OpenTelemetry API.
The OTEL API is a no-op by default, but here we're setting up the SDK to export to an OTLP over HTTP endpoint (localhost:4317 by default).
I've added a docker-compose stack to start the OTEL collector and a Jaeger instance to collect the traces.

It also touches a bit the HTTP client so that the trace context is injected in the HTTP headers. I have a modified Synapse somewhere to accept those headers and propagate the trace context.

Comment on lines +111 to +112
if (requestOptions?.log?.injectHeaders) {
requestOptions.log.injectHeaders(fetchHeaders);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit hacky, but it is where propagation headers are injected. What header exactly is being injected is defined by the propagator when initialising the OTEL SDK.

This also probably breaks if the server doesn't allow the uber-trace-id header in the CORS

Comment on lines +188 to +197
const resource = new Resource({
[SemanticResourceAttributes.SERVICE_NAME]: 'hydrogen-web',
});
const detectedResources = await detectResources({ detectors: [browserDetector] });

const provider = new WebTracerProvider({
resource: resource.merge(detectedResources),
});
provider.addSpanProcessor(new BatchSpanProcessor(new OTLPTraceExporter()));
provider.register({ propagator: new JaegerPropagator() });
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does a bunch of things.

The 'resources' are K/V that are attached to all the spans. The browserDetector will automatically add the browser name and version in those resourceS.

Then the WebTracerProvider provides the OTEL API implementation, and it registers itself as the global provider. We could also pass that to the OTEL logger instead if don't want to pollute some global variable.

Comment on lines +24 to +53
function itemCaption(values: LogItemValues): string {
if (values.t === "network") {
return `HTTP request`;
} else {
return values.l || values.t || "Log item";
}
}

function mapLabelToAttribute(t: string | undefined, key: string): string | null {
if (key === "l") return null;
if (key === "t") return null;

if (t === "network") {
if (key === "method") return SemanticAttributes.HTTP_METHOD;
if (key === "url") return SemanticAttributes.HTTP_URL;
if (key === "status") return SemanticAttributes.HTTP_STATUS_CODE;
}

return `hydrogen.${key}`;
}

function labelsToAttributes(labels: object): Attributes {
return Object.entries(labels)
.reduce((attrs, [key, value]) => {
const mapped = mapLabelToAttribute(labels['t'], key);
if (!mapped) return attrs;
return { ...attrs, [mapped]: value as AttributeValue };
}, {
});
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those functions are an attempt to map the various keys in the log entries to well-known OTEL attributes. The list of those attributes can be found here: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/README.md

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant