Skip to content

Commit

Permalink
OpenTelemetry Exporter using Resources API to get service properties (#…
Browse files Browse the repository at this point in the history
…12893)

* OT Exporter use Resources API to get service properties

* Test

* Addung pnpm-lock

* Addressing comments

* Updating pnpm
  • Loading branch information
hectorhdzg authored Dec 15, 2020
1 parent 6b838b8 commit 2424b74
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 9 deletions.
2 changes: 2 additions & 0 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 @@ -82,6 +82,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,27 @@ 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];
const serviceInstanceId = span.resource.labels[SERVICE_RESOURCE.INSTANCE_ID];
if (serviceName) {
if (serviceNamespace) {
tags[AI_CLOUD_ROLE] = `${serviceNamespace}.${serviceName}`;
} else {
tags[AI_CLOUD_ROLE] = String(serviceName);
}
}
if (serviceInstanceId) {
tags[AI_CLOUD_ROLE_INSTACE] = String(serviceInstanceId);
}
}

// @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

0 comments on commit 2424b74

Please sign in to comment.