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

OpenTelemetry Exporter using Resources API to get service properties #12893

Merged
merged 7 commits into from
Dec 15, 2020
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 14 additions & 8 deletions common/config/rush/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
"@azure/core-http": "^1.2.0",
"@opentelemetry/api": "^0.10.2",
"@opentelemetry/core": "^0.10.2",
"@opentelemetry/resources": "^0.10.2",
"@opentelemetry/semantic-conventions": "^0.10.2",
"@opentelemetry/tracing": "^0.10.2"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ let instance: Context | null = null;
export class Context {
public tags: Tags;

public static DefaultRoleName: string = "Node.js";

public static appVersion: { [path: string]: string } = {};

public static sdkVersion: string | null = null;
Expand Down Expand Up @@ -98,8 +96,6 @@ export class Context {

private _loadDeviceContext(): void {
this.tags["ai.device.id"] = "";
this.tags["ai.cloud.role"] = Context.DefaultRoleName;
this.tags["ai.cloud.roleInstance"] = os && os.hostname();
this.tags["ai.device.osVersion"] = os && `${os.type()} ${os.release()}`;

// not yet supported tags
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

export const AI_CLOUD_ROLE = "ai.cloud.role";
export const AI_CLOUD_ROLE_INSTACE = "ai.cloud.roleInstance";
export const AI_OPERATION_ID = "ai.operation.id";
export const AI_OPERATION_PARENT_ID = "ai.operation.parentId";
export const AI_OPERATION_NAME = "ai.operation.name";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { URL } from "url";
import { ReadableSpan } from "@opentelemetry/tracing";
import { hrTimeToMilliseconds } from "@opentelemetry/core";
import { SpanKind, Logger, CanonicalCode, Link } from "@opentelemetry/api";
import { SERVICE_RESOURCE } from "@opentelemetry/resources";
import { Tags, Properties, MSLink, Measurements } from "../types";
import {
HTTP_METHOD,
Expand All @@ -13,6 +14,8 @@ import {
HTTP_STATUS_CODE
} from "./constants/span/httpAttributes";
import {
AI_CLOUD_ROLE,
AI_CLOUD_ROLE_INSTACE,
AI_OPERATION_ID,
AI_OPERATION_PARENT_ID,
AI_OPERATION_NAME,
Expand All @@ -35,10 +38,26 @@ import { RemoteDependencyData, RequestData, TelemetryItem as Envelope } from "..
function createTagsFromSpan(span: ReadableSpan): Tags {
const context = getInstance();
const tags: Tags = { ...context.tags };

tags[AI_OPERATION_ID] = span.spanContext.traceId;
if (span.parentSpanId) {
tags[AI_OPERATION_PARENT_ID] = span.parentSpanId;
}
if (span.resource && span.resource.labels) {
const serviceName = span.resource.labels[SERVICE_RESOURCE.NAME];
const serviceNamespace = span.resource.labels[SERVICE_RESOURCE.NAMESPACE];
if (serviceName) {
if (serviceNamespace) {
tags[AI_CLOUD_ROLE] = serviceNamespace + "." + serviceName;
hectorhdzg marked this conversation as resolved.
Show resolved Hide resolved
} else {
tags[AI_CLOUD_ROLE] = serviceName.toString();
}
}
if (span.resource.labels[SERVICE_RESOURCE.INSTANCE_ID]) {
tags[AI_CLOUD_ROLE_INSTACE] = span.resource.labels[SERVICE_RESOURCE.INSTANCE_ID].toString();
hectorhdzg marked this conversation as resolved.
Show resolved Hide resolved
}
}

// @todo: is this for RequestData only?
if (
(span.kind === SpanKind.SERVER || span.kind === SpanKind.CONSUMER) &&
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import { Span, BasicTracerProvider } from "@opentelemetry/tracing";
import { Span, BasicTracerProvider, TracerConfig } from "@opentelemetry/tracing";
import { SpanKind, CanonicalCode } from "@opentelemetry/api";
import * as assert from "assert";
import { NoopLogger, hrTimeToMilliseconds } from "@opentelemetry/core";
import { Resource, SERVICE_RESOURCE } from "@opentelemetry/resources";

import { Tags, Properties, Measurements } from "../../../src/types";
import {
AI_CLOUD_ROLE,
AI_CLOUD_ROLE_INSTACE
} from "../../../src/utils/constants/applicationinsights";
import * as http from "../../../src/utils/constants/span/httpAttributes";
import * as grpc from "../../../src/utils/constants/span/grpcAttributes";
import * as ai from "../../../src/utils/constants/applicationinsights";
Expand All @@ -18,9 +23,16 @@ import { TelemetryItem as Envelope } from "../../../src/generated";

const context = getInstance(undefined, "./", "../../");

const tracer = new BasicTracerProvider({
logger: new NoopLogger()
}).getTracer("default");
const tracerProviderConfig: TracerConfig = {
logger: new NoopLogger(),
resource: new Resource({
[SERVICE_RESOURCE.INSTANCE_ID]: "testServiceInstanceID",
[SERVICE_RESOURCE.NAME]: "testServiceName",
[SERVICE_RESOURCE.NAMESPACE]: "testServiceNamespace"
})
};

const tracer = new BasicTracerProvider(tracerProviderConfig).getTracer("default");

function assertEnvelope(
envelope: Envelope,
Expand Down Expand Up @@ -49,7 +61,15 @@ function assertEnvelope(
assert.deepStrictEqual(envelope.time, expectedTime);
}

assert.deepStrictEqual(envelope.tags, { ...context.tags, ...expectedTags });
const expectedServiceTags: Tags = {
[AI_CLOUD_ROLE]: "testServiceNamespace.testServiceName",
[AI_CLOUD_ROLE_INSTACE]: "testServiceInstanceID"
};
assert.deepStrictEqual(envelope.tags, {
...context.tags,
...expectedServiceTags,
...expectedTags
});
assert.deepStrictEqual((envelope?.data?.baseData as RequestData).properties, expectedProperties);
assert.deepStrictEqual(
(envelope?.data?.baseData as RequestData).measurements,
Expand Down