Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
2 changes: 1 addition & 1 deletion .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -816,7 +816,7 @@ sdk/dnsresolver/arm-dnsresolver @qiaozha @dw511214992 @MaryGao
sdk/dnsresolver/ci.mgmt.yml @qiaozha @dw511214992 @MaryGao

# PRLabel: %Monitor
/sdk/monitor/ @hectorhdzg
/sdk/monitor/ @hectorhdzg @JacksonWeber

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

@jsquire @ronniegeraghty do you know how Jackson can request for write permissions?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

/sdk/monitor/monitor-query @KarishmaGhiya

# ServiceLabel: %AAD %Service Attention
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import { AggregationTemporality } from '@opentelemetry/sdk-metrics-base';
import { ExportResult } from '@opentelemetry/core';
import { InstrumentType } from '@opentelemetry/sdk-metrics-base';
import { PushMetricExporter } from '@opentelemetry/sdk-metrics-base';
import { ReadableSpan } from '@opentelemetry/sdk-trace-base';
import { ResourceMetrics } from '@opentelemetry/sdk-metrics-base';
Expand All @@ -30,16 +31,22 @@ export abstract class AzureMonitorBaseExporter {
// @public
export class AzureMonitorMetricExporter extends AzureMonitorBaseExporter implements PushMetricExporter {
constructor(options?: AzureExporterConfig);
// (undocumented)
protected _aggregationTemporality: AggregationTemporality;
export(metrics: ResourceMetrics, resultCallback: (result: ExportResult) => void): Promise<void>;
forceFlush(): Promise<void>;
selectAggregationTemporality(): AggregationTemporality;
// (undocumented)
protected _isShutdown: boolean;
selectAggregationTemporality(_instrumentType: InstrumentType): AggregationTemporality;
shutdown(): Promise<void>;
}

// @public
export class AzureMonitorTraceExporter extends AzureMonitorBaseExporter implements SpanExporter {
constructor(options?: AzureExporterConfig);
export(spans: ReadableSpan[], resultCallback: (result: ExportResult) => void): Promise<void>;
// (undocumented)
protected _isShutdown: boolean;
shutdown(): Promise<void>;
}

Expand Down
28 changes: 22 additions & 6 deletions sdk/monitor/monitor-opentelemetry-exporter/src/export/metric.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
import { diag } from "@opentelemetry/api";
import {
AggregationTemporality,
InstrumentType,
PushMetricExporter,
ResourceMetrics,
} from "@opentelemetry/sdk-metrics-base";
import { ExportResult } from "@opentelemetry/core";
import { ExportResult, ExportResultCode } from "@opentelemetry/core";
import { AzureMonitorBaseExporter } from "./base";
import { AzureExporterConfig } from "../config";
import { TelemetryItem as Envelope } from "../generated";
Expand All @@ -19,12 +20,22 @@ export class AzureMonitorMetricExporter
extends AzureMonitorBaseExporter
implements PushMetricExporter
{
/**
* Flag to determine if Exported is shutdown.
*/
protected _isShutdown = false;
/**
* Aggregation temporality.
*/
protected _aggregationTemporality: AggregationTemporality;

/**
* Initializes a new instance of the AzureMonitorMetricExporter class.
* @param AzureExporterConfig - Exporter configuration.
*/
constructor(options: AzureExporterConfig = {}) {
super(options);
this._aggregationTemporality = AggregationTemporality.CUMULATIVE;
diag.debug("AzureMonitorMetricExporter was successfully setup");
}

Expand All @@ -37,6 +48,11 @@ export class AzureMonitorMetricExporter
metrics: ResourceMetrics,
resultCallback: (result: ExportResult) => void
): Promise<void> {
if (this._isShutdown) {
diag.info("Exporter shut down. Failed to export spans.");
setTimeout(() => resultCallback({ code: ExportResultCode.FAILED }), 0);
return;
}
diag.info(`Exporting ${metrics.scopeMetrics.length} metrics(s). Converting to envelopes...`);

let envelopes: Envelope[] = resourceMetricsToEnvelope(metrics, this._instrumentationKey);
Expand All @@ -47,22 +63,22 @@ export class AzureMonitorMetricExporter
* Shutdown AzureMonitorMetricExporter.
*/
public async shutdown(): Promise<void> {
diag.info("Azure Monitor Trace Exporter shutting down");
this._isShutdown = true;
diag.info("AzureMonitorMetricExporter shutting down");
return this._shutdown();
}

/**
* Select aggregation temporality
*/
public selectAggregationTemporality() {
return AggregationTemporality.CUMULATIVE;
public selectAggregationTemporality(_instrumentType: InstrumentType): AggregationTemporality {
return this._aggregationTemporality;
}

/**
* Force flush
*/
public async forceFlush() {
// TODO: https://github.com/open-telemetry/opentelemetry-js/issues/3060
throw new Error("Method not implemented.");
return Promise.resolve();
}
}
16 changes: 14 additions & 2 deletions sdk/monitor/monitor-opentelemetry-exporter/src/export/trace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Licensed under the MIT license.

import { diag } from "@opentelemetry/api";
import { ExportResult } from "@opentelemetry/core";
import { ExportResult, ExportResultCode } from "@opentelemetry/core";
import { ReadableSpan, SpanExporter } from "@opentelemetry/sdk-trace-base";
import { AzureMonitorBaseExporter } from "./base";
import { AzureExporterConfig } from "../config";
Expand All @@ -13,6 +13,11 @@ import { readableSpanToEnvelope, spanEventsToEnvelopes } from "../utils/spanUtil
* Azure Monitor OpenTelemetry Trace Exporter.
*/
export class AzureMonitorTraceExporter extends AzureMonitorBaseExporter implements SpanExporter {
/**
* Flag to determine if Exported is shutdown.
*/
protected _isShutdown = false;

/**
* Initializes a new instance of the AzureMonitorTraceExporter class.
* @param AzureExporterConfig - Exporter configuration.
Expand All @@ -31,6 +36,12 @@ export class AzureMonitorTraceExporter extends AzureMonitorBaseExporter implemen
spans: ReadableSpan[],
resultCallback: (result: ExportResult) => void
): Promise<void> {
if (this._isShutdown) {
diag.info("Exporter shut down. Failed to export spans.");
setTimeout(() => resultCallback({ code: ExportResultCode.FAILED }), 0);
return;
}

diag.info(`Exporting ${spans.length} span(s). Converting to envelopes...`);

let envelopes: Envelope[] = [];
Expand All @@ -48,7 +59,8 @@ export class AzureMonitorTraceExporter extends AzureMonitorBaseExporter implemen
* Shutdown AzureMonitorTraceExporter.
*/
async shutdown(): Promise<void> {
diag.info("Azure Monitor Trace Exporter shutting down");
this._isShutdown = true;
diag.info("AzureMonitorTraceExporter shutting down");
return this._shutdown();
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,23 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import { MetricAttributes } from "@opentelemetry/api-metrics";
import { DataPointType, Histogram, ResourceMetrics } from "@opentelemetry/sdk-metrics-base";
import { TelemetryItem as Envelope, MetricsData, MetricDataPoint } from "../generated";
import { createTagsFromResource } from "./resourceUtils";

function createPropertiesFromMetricAttributes(attributes?: MetricAttributes): {
[propertyName: string]: string;
} {
const properties: { [propertyName: string]: string } = {};
if (attributes) {
for (const key of Object.keys(attributes)) {
properties[key] = attributes[key] as string;
}
}
return properties;
}

/**
* Metric to Azure envelope parsing.
* @internal
Expand All @@ -16,12 +29,14 @@ export function resourceMetricsToEnvelope(metrics: ResourceMetrics, ikey: string
const tags = createTagsFromResource(metrics.resource);

metrics.scopeMetrics.forEach((scopeMetric) => {
let baseData: MetricsData = {
metrics: [],
version: 2,
};
scopeMetric.metrics.forEach((metric) => {
metric.dataPoints.forEach((dataPoint) => {
let baseData: MetricsData = {
metrics: [],
version: 2,
properties: {},
};
baseData.properties = createPropertiesFromMetricAttributes(dataPoint.attributes);
var metricDataPoint: MetricDataPoint = {
name: metric.descriptor.name,
value: 0,
Expand All @@ -40,23 +55,23 @@ export function resourceMetricsToEnvelope(metrics: ResourceMetrics, ikey: string
metricDataPoint.min = (dataPoint.value as Histogram).min;
}
baseData.metrics.push(metricDataPoint);
let envelope: Envelope = {
name: "Microsoft.ApplicationInsights.Metric",
time: time,
sampleRate: 100,
instrumentationKey: instrumentationKey,
tags: tags,
version: 1,
data: {
baseType: "MetricData",
baseData: {
...baseData,
},
},
};
envelopes.push(envelope);
});
});
let envelope: Envelope = {
name: "Microsoft.ApplicationInsights.Metric",
time: time,
sampleRate: 100,
instrumentationKey: instrumentationKey,
tags: tags,
version: 1,
data: {
baseType: "MetricData",
baseData: {
...baseData,
},
},
};
envelopes.push(envelope);
});

return envelopes;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ export const assertTraceExpectation = (actual: Envelope[], expectations: Expecta
export const assertMetricExpectation = (actual: Envelope[], expectations: Expectation[]): void => {
for (const expectation of expectations) {
let envelope: any = null;
if (expectation.data!.baseData!.name) {
if (expectation.data!.baseData!.metrics && expectation.data!.baseData!.metrics.length > 0) {
envelope = actual.filter((e) => {
return (
(e.data!.baseData as MetricsData).metrics[0].name ===
Expand Down
61 changes: 60 additions & 1 deletion sdk/monitor/monitor-opentelemetry-exporter/test/utils/basic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,13 +209,18 @@ export class MetricBasicScenario implements Scenario {
async run(): Promise<void> {
const meter = this._provider.getMeter("basic");
let counter = meter.createCounter("testCounter");
let counter2 = meter.createCounter("testCounter2");
let histogram = meter.createHistogram("testHistogram");
let histogram2 = meter.createHistogram("testHistogram2");
let attributes = { testAttribute: "testValue" };
counter.add(1);
counter.add(2);
counter2.add(12, attributes);
histogram.record(1);
histogram.record(2);
histogram.record(3);
histogram.record(4);
histogram2.record(12, attributes);
await delay(0);
}

Expand All @@ -225,7 +230,6 @@ export class MetricBasicScenario implements Scenario {

flush(): Promise<void> {
return delay(100);
// return metricReader.forceFlush();
}

expectation: Expectation[] = [
Expand All @@ -243,6 +247,39 @@ export class MetricBasicScenario implements Scenario {
count: 1,
dataPointType: "Aggregation",
},
],
} as any,
},
children: [],
},
{
...COMMON_ENVELOPE_PARAMS,
name: "Microsoft.ApplicationInsights.Metric",
data: {
baseType: "MetricData",
baseData: {
version: 2,
metrics: [
{
name: "testCounter2",
value: 12,
count: 1,
dataPointType: "Aggregation",
},
],
properties: { testAttribute: "testValue" },
} as any,
},
children: [],
},
{
...COMMON_ENVELOPE_PARAMS,
name: "Microsoft.ApplicationInsights.Metric",
data: {
baseType: "MetricData",
baseData: {
version: 2,
metrics: [
{
name: "testHistogram",
value: 10,
Expand All @@ -256,5 +293,27 @@ export class MetricBasicScenario implements Scenario {
},
children: [],
},
{
...COMMON_ENVELOPE_PARAMS,
name: "Microsoft.ApplicationInsights.Metric",
data: {
baseType: "MetricData",
baseData: {
version: 2,
metrics: [
{
name: "testHistogram2",
value: 12,
count: 1,
max: 12,
min: 12,
dataPointType: "Aggregation",
},
],
properties: { testAttribute: "testValue" },
} as any,
},
children: [],
},
];
}