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

Remove metric telemetry for resource #38697

Merged
merged 6 commits into from
Sep 14, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,14 @@ public async Task ValidateTelemetryExport()
// Telemetry is serialized as json, and then byte encoded.
// Need to parse the request content into something assertable.
var data = ParseJsonRequestContent<ParsedData>(transport.Requests);
Assert.Equal(16, data.Count); // Total telemetry items
Assert.Equal(15, data.Count); // Total telemetry items

// Group all parsed telemetry by name and get the count per name.
var summary = data.GroupBy(x => x.name).ToDictionary(x => x.Key!, x => x.Count());

Assert.Equal(4, summary.Count); // Total unique telemetry items
Assert.Equal(8, summary["Message"]); // Count of telemetry items
Assert.Equal(6, summary["Metric"]);
Assert.Equal(5, summary["Metric"]);
Assert.Equal(1, summary["RemoteDependency"]);
Assert.Equal(1, summary["Request"]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,10 @@ internal static class EnvironmentVariableConstants
/// INTERNAL ONLY. Used by Statsbeat to get the App Service Website Name.
/// </summary>
public const string WEBSITE_SITE_NAME = "WEBSITE_SITE_NAME";

/// <summary>
/// When set to true, exporter will emit resources as metric telemetry.
/// </summary>
public const string EXPORT_RESOURCE_METRIC = "OTEL_DOTNET_AZURE_MONITOR_ENABLE_RESOURCE_METRICS";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,20 @@ internal static class ResourceExtensions
}
}

if (metricsData != null)
bool shouldReportMetricTelemetry = false;
try
{
var exportResource = Environment.GetEnvironmentVariable(EnvironmentVariableConstants.EXPORT_RESOURCE_METRIC);
Copy link
Contributor

Choose a reason for hiding this comment

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

This should be changed to use the Platform abstraction

if (exportResource.Equals("true", StringComparison.OrdinalIgnoreCase))
{
shouldReportMetricTelemetry = true;
}
}
catch
{
}

if (shouldReportMetricTelemetry && metricsData != null)
{
azureMonitorResource.MetricTelemetry = new TelemetryItem(DateTime.UtcNow, azureMonitorResource, instrumentationKey!)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Collections.Generic;
using System.Net;
using Azure.Monitor.OpenTelemetry.Exporter.Internals;
Expand All @@ -26,16 +27,35 @@ public void NullResource(string? instrumentationKey)
}

[Theory]
[InlineData(null)]
[InlineData(InstrumentationKey)]
public void DefaultResource(string? instrumentationKey)
[InlineData(null, "true")]
[InlineData(null, "false")]
[InlineData(null, null)]
[InlineData(InstrumentationKey, "false")]
[InlineData(InstrumentationKey, "true")]
[InlineData(InstrumentationKey, null)]
public void DefaultResource(string? instrumentationKey, string envVarValue)
{
var resource = CreateTestResource();
var azMonResource = resource.CreateAzureMonitorResource(instrumentationKey);

Assert.StartsWith("unknown_service", azMonResource?.RoleName);
Assert.Equal(Dns.GetHostName(), azMonResource?.RoleInstance);
Assert.Equal(instrumentationKey != null, azMonResource?.MetricTelemetry != null);
try
{
Environment.SetEnvironmentVariable(EnvironmentVariableConstants.EXPORT_RESOURCE_METRIC, envVarValue);
var resource = CreateTestResource();
var azMonResource = resource.CreateAzureMonitorResource(instrumentationKey);

Assert.StartsWith("unknown_service", azMonResource?.RoleName);
Assert.Equal(Dns.GetHostName(), azMonResource?.RoleInstance);
if (envVarValue == "true")
{
Assert.Equal(instrumentationKey != null, azMonResource?.MetricTelemetry != null);
}
else
{
Assert.Null(azMonResource?.MetricTelemetry);
}
}
finally
{
Environment.SetEnvironmentVariable(EnvironmentVariableConstants.EXPORT_RESOURCE_METRIC, null);
}
}

[Fact]
Expand Down Expand Up @@ -185,73 +205,91 @@ public void EmptyPrefixResourceDoesNotSetSdkPrefix()
[Fact]
public void SdkPrefixIsNotInResourceMetrics()
{
// SDK version is static, preserve to clean up later.
var sdkVersion = SdkVersionUtils.s_sdkVersion;
var testAttributes = new Dictionary<string, object>
try
{
{"foo", "bar" },
{ "ai.sdk.prefix", "pre_" }
};
Environment.SetEnvironmentVariable(EnvironmentVariableConstants.EXPORT_RESOURCE_METRIC, "true");

var resource = ResourceBuilder.CreateDefault().AddAttributes(testAttributes).Build();
var azMonResource = resource.CreateAzureMonitorResource(InstrumentationKey);
// SDK version is static, preserve to clean up later.
var sdkVersion = SdkVersionUtils.s_sdkVersion;
var testAttributes = new Dictionary<string, object>
{
{"foo", "bar" },
{ "ai.sdk.prefix", "pre_" }
};

Assert.Equal("Metric", azMonResource!.MetricTelemetry!.Name);
var resource = ResourceBuilder.CreateDefault().AddAttributes(testAttributes).Build();
var azMonResource = resource.CreateAzureMonitorResource(InstrumentationKey);

var monitorBase = azMonResource.MetricTelemetry.Data;
var metricsData = monitorBase.BaseData as MetricsData;
Assert.Equal("Metric", azMonResource!.MetricTelemetry!.Name);

var metricDataPoint = metricsData?.Metrics[0];
Assert.Equal("bar", metricsData?.Properties["foo"]);
Assert.False(metricsData?.Properties.ContainsKey("ai.sdk.prefix"));
var monitorBase = azMonResource.MetricTelemetry.Data;
var metricsData = monitorBase.BaseData as MetricsData;

// Clean up
SdkVersionUtils.s_sdkVersion = sdkVersion;
var metricDataPoint = metricsData?.Metrics[0];
Assert.Equal("bar", metricsData?.Properties["foo"]);
Assert.False(metricsData?.Properties.ContainsKey("ai.sdk.prefix"));

// Clean up
SdkVersionUtils.s_sdkVersion = sdkVersion;
}
finally
{
Environment.SetEnvironmentVariable(EnvironmentVariableConstants.EXPORT_RESOURCE_METRIC, null);
}
}

[Theory]
[InlineData(null)]
[InlineData(InstrumentationKey)]
public void MetricTelemetryHasAllResourceAttributes(string? instrumentationKey)
{
var testAttributes = new Dictionary<string, object>
try
{
{SemanticConventions.AttributeServiceName, "my-service" },
{SemanticConventions.AttributeServiceNamespace, "my-namespace" },
{SemanticConventions.AttributeServiceInstance, "my-instance" },
{SemanticConventions.AttributeK8sDeployment, "my-deployment" },
{SemanticConventions.AttributeK8sPod, "my-pod" },
{ "foo", "bar" }
};

var resource = ResourceBuilder.CreateEmpty().AddAttributes(testAttributes).Build();
var azMonResource = resource.CreateAzureMonitorResource(instrumentationKey);

Assert.Equal(instrumentationKey != null, azMonResource?.MetricTelemetry != null);

if (instrumentationKey != null)
Environment.SetEnvironmentVariable(EnvironmentVariableConstants.EXPORT_RESOURCE_METRIC, "true");

var testAttributes = new Dictionary<string, object>
{
{SemanticConventions.AttributeServiceName, "my-service" },
{SemanticConventions.AttributeServiceNamespace, "my-namespace" },
{SemanticConventions.AttributeServiceInstance, "my-instance" },
{SemanticConventions.AttributeK8sDeployment, "my-deployment" },
{SemanticConventions.AttributeK8sPod, "my-pod" },
{ "foo", "bar" }
};

var resource = ResourceBuilder.CreateEmpty().AddAttributes(testAttributes).Build();
var azMonResource = resource.CreateAzureMonitorResource(instrumentationKey);

Assert.Equal(instrumentationKey != null, azMonResource?.MetricTelemetry != null);

if (instrumentationKey != null)
{
Assert.Equal("Metric", azMonResource!.MetricTelemetry!.Name);
Assert.Equal(3, azMonResource.MetricTelemetry.Tags.Count);
Assert.NotNull(azMonResource.MetricTelemetry.Data);

var monitorBase = azMonResource.MetricTelemetry.Data;
var metricsData = monitorBase.BaseData as MetricsData;

Assert.NotNull(metricsData?.Metrics);

var metricDataPoint = metricsData?.Metrics[0];
Assert.Equal("_OTELRESOURCE_", metricDataPoint?.Name);
Assert.Equal(0, metricDataPoint?.Value);

Assert.Equal(6, metricsData?.Properties.Count);

Assert.Equal("my-service", metricsData?.Properties[SemanticConventions.AttributeServiceName]);
Assert.Equal("my-namespace", metricsData?.Properties[SemanticConventions.AttributeServiceNamespace]);
Assert.Equal("my-instance", metricsData?.Properties[SemanticConventions.AttributeServiceInstance]);
Assert.Equal("my-deployment", metricsData?.Properties[SemanticConventions.AttributeK8sDeployment]);
Assert.Equal("my-pod", metricsData?.Properties[SemanticConventions.AttributeK8sPod]);
Assert.Equal("bar", metricsData?.Properties["foo"]);
}
}
finally
{
Assert.Equal("Metric", azMonResource!.MetricTelemetry!.Name);
Assert.Equal(3, azMonResource.MetricTelemetry.Tags.Count);
Assert.NotNull(azMonResource.MetricTelemetry.Data);

var monitorBase = azMonResource.MetricTelemetry.Data;
var metricsData = monitorBase.BaseData as MetricsData;

Assert.NotNull(metricsData?.Metrics);

var metricDataPoint = metricsData?.Metrics[0];
Assert.Equal("_OTELRESOURCE_", metricDataPoint?.Name);
Assert.Equal(0, metricDataPoint?.Value);

Assert.Equal(6, metricsData?.Properties.Count);

Assert.Equal("my-service", metricsData?.Properties[SemanticConventions.AttributeServiceName]);
Assert.Equal("my-namespace", metricsData?.Properties[SemanticConventions.AttributeServiceNamespace]);
Assert.Equal("my-instance", metricsData?.Properties[SemanticConventions.AttributeServiceInstance]);
Assert.Equal("my-deployment", metricsData?.Properties[SemanticConventions.AttributeK8sDeployment]);
Assert.Equal("my-pod", metricsData?.Properties[SemanticConventions.AttributeK8sPod]);
Assert.Equal("bar", metricsData?.Properties["foo"]);
Environment.SetEnvironmentVariable(EnvironmentVariableConstants.EXPORT_RESOURCE_METRIC, null);
}
}

Expand Down Expand Up @@ -312,6 +350,34 @@ public void ResourceWithEmptyKubernetesAttributes()
Assert.Equal(Dns.GetHostName(), azMonResource?.RoleInstance);
}

[Theory]
[InlineData(null)]
[InlineData("true")]
[InlineData("false")]
public void MetricTelemetryIsAddedToResourceBasedOnEnvVar(string envVarValue)
{
try
{
Environment.SetEnvironmentVariable(EnvironmentVariableConstants.EXPORT_RESOURCE_METRIC, envVarValue);

var resource = ResourceBuilder.CreateDefault().Build();
var azMonResource = resource.CreateAzureMonitorResource(InstrumentationKey);

if (envVarValue == "true")
{
Assert.NotNull(azMonResource?.MetricTelemetry);
}
else
{
Assert.Null(azMonResource?.MetricTelemetry);
}
}
finally
{
Environment.SetEnvironmentVariable(EnvironmentVariableConstants.EXPORT_RESOURCE_METRIC, null);
}
}

/// <summary>
/// If SERVICE.NAME is not defined, it will fall-back to "unknown_service".
/// (https://github.com/open-telemetry/opentelemetry-specification/tree/main/specification/resource/semantic_conventions#semantic-attributes-with-sdk-provided-default-value).
Expand Down