diff --git a/NETCORE/ThirdPartyNotices.txt b/NETCORE/ThirdPartyNotices.txt index f5f711e27..4f45614bf 100644 --- a/NETCORE/ThirdPartyNotices.txt +++ b/NETCORE/ThirdPartyNotices.txt @@ -216,4 +216,25 @@ http://www.apache.org/licenses/ See the License for the specific language governing permissions and limitations under the License. ========================================= -END OF xunit and dotnet.test.xunit NOTICES, INFORMATION, AND LICENSE \ No newline at end of file +END OF xunit and dotnet.test.xunit NOTICES, INFORMATION, AND LICENSE + + +3. OpenTelemetry .NET Contrib (https://github.com/open-telemetry/opentelemetry-dotnet-contrib) + +%% OpenTelemetry .NET Contrib NOTICES, INFORMATION, AND LICENSE BEGIN HERE +========================================= +Copyright 2026 OpenTelemetry Authors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +========================================= +END OF OpenTelemetry .NET Contrib NOTICES, INFORMATION, AND LICENSE \ No newline at end of file diff --git a/NETCORE/src/Shared/Shared.projitems b/NETCORE/src/Shared/Shared.projitems index 73ed2cbc9..789859897 100644 --- a/NETCORE/src/Shared/Shared.projitems +++ b/NETCORE/src/Shared/Shared.projitems @@ -13,5 +13,15 @@ + + + + + + + + + + \ No newline at end of file diff --git a/NETCORE/src/Shared/Vendoring/OpenTelemetry.Resources.Azure/AppServiceResourceDetector.cs b/NETCORE/src/Shared/Vendoring/OpenTelemetry.Resources.Azure/AppServiceResourceDetector.cs new file mode 100644 index 000000000..fbace0841 --- /dev/null +++ b/NETCORE/src/Shared/Vendoring/OpenTelemetry.Resources.Azure/AppServiceResourceDetector.cs @@ -0,0 +1,82 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 +#nullable enable + +namespace Microsoft.ApplicationInsights.Shared.Vendoring.OpenTelemetry.Resources.Azure +{ + using System; + using System.Collections.Generic; + using global::OpenTelemetry.Resources; + + /// + /// Resource detector for Azure AppService environment. + /// + internal sealed class AppServiceResourceDetector : IResourceDetector + { + internal static readonly IReadOnlyDictionary AppServiceResourceAttributes = new Dictionary + { + { ResourceSemanticConventions.AttributeCloudRegion, ResourceAttributeConstants.AppServiceRegionNameEnvVar }, + { ResourceSemanticConventions.AttributeDeploymentEnvironment, ResourceAttributeConstants.AppServiceSlotNameEnvVar }, + { ResourceSemanticConventions.AttributeHostId, ResourceAttributeConstants.AppServiceHostNameEnvVar }, + { ResourceSemanticConventions.AttributeServiceInstance, ResourceAttributeConstants.AppServiceInstanceIdEnvVar }, + { ResourceAttributeConstants.AzureAppServiceStamp, ResourceAttributeConstants.AppServiceStampNameEnvVar }, + }; + + /// + public Resource Detect() + { + List> attributeList = new List>(); + + try + { + var websiteSiteName = Environment.GetEnvironmentVariable(ResourceAttributeConstants.AppServiceSiteNameEnvVar); + + if (websiteSiteName != null) + { + attributeList.Add(new KeyValuePair(ResourceSemanticConventions.AttributeServiceName, websiteSiteName)); + attributeList.Add(new KeyValuePair(ResourceSemanticConventions.AttributeCloudProvider, ResourceAttributeConstants.AzureCloudProviderValue)); + attributeList.Add(new KeyValuePair(ResourceSemanticConventions.AttributeCloudPlatform, ResourceAttributeConstants.AzureAppServicePlatformValue)); + + var azureResourceUri = GetAzureResourceURI(websiteSiteName); + if (azureResourceUri != null) + { + attributeList.Add(new KeyValuePair(ResourceSemanticConventions.AttributeCloudResourceId, azureResourceUri)); + } + + foreach (var kvp in AppServiceResourceAttributes) + { + var attributeValue = Environment.GetEnvironmentVariable(kvp.Value); + if (attributeValue != null) + { + attributeList.Add(new KeyValuePair(kvp.Key, attributeValue)); + } + } + } + } + catch + { + // TODO: log exception. + return Resource.Empty; + } + + return new Resource(attributeList); + } + + private static string? GetAzureResourceURI(string websiteSiteName) + { + var websiteResourceGroup = Environment.GetEnvironmentVariable(ResourceAttributeConstants.AppServiceResourceGroupEnvVar); + var websiteOwnerName = Environment.GetEnvironmentVariable(ResourceAttributeConstants.AppServiceOwnerNameEnvVar) ?? string.Empty; + +#if NET + var idx = websiteOwnerName.IndexOf('+', StringComparison.Ordinal); +#else + var idx = websiteOwnerName.IndexOf("+", StringComparison.Ordinal); +#endif + var subscriptionId = idx > 0 ? websiteOwnerName.Substring(0, idx) : websiteOwnerName; + + return string.IsNullOrEmpty(websiteResourceGroup) || string.IsNullOrEmpty(subscriptionId) + ? null + : $"/subscriptions/{subscriptionId}/resourceGroups/{websiteResourceGroup}/providers/Microsoft.Web/sites/{websiteSiteName}"; + } + } +} diff --git a/NETCORE/src/Shared/Vendoring/OpenTelemetry.Resources.Azure/AzureContainerAppsResourceDetector.cs b/NETCORE/src/Shared/Vendoring/OpenTelemetry.Resources.Azure/AzureContainerAppsResourceDetector.cs new file mode 100644 index 000000000..3cb9f5cd2 --- /dev/null +++ b/NETCORE/src/Shared/Vendoring/OpenTelemetry.Resources.Azure/AzureContainerAppsResourceDetector.cs @@ -0,0 +1,77 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +namespace Microsoft.ApplicationInsights.Shared.Vendoring.OpenTelemetry.Resources.Azure +{ + using System; + using System.Collections.Generic; + using global::OpenTelemetry.Resources; + + /// + /// Resource detector for Azure Container Apps environment. + /// + internal sealed class AzureContainerAppsResourceDetector : IResourceDetector + { + internal static readonly IReadOnlyDictionary AzureContainerAppResourceAttributes = new Dictionary + { + { ResourceSemanticConventions.AttributeServiceInstance, ResourceAttributeConstants.AzureContainerAppsReplicaNameEnvVar }, + { ResourceSemanticConventions.AttributeServiceVersion, ResourceAttributeConstants.AzureContainerAppsRevisionEnvVar }, + }; + + internal static readonly IReadOnlyDictionary AzureContainerAppJobResourceAttributes = new Dictionary + { + { ResourceSemanticConventions.AttributeServiceInstance, ResourceAttributeConstants.AzureContainerAppsReplicaNameEnvVar }, + { ResourceSemanticConventions.AttributeServiceVersion, ResourceAttributeConstants.AzureContainerAppJobExecutionNameEnvVar }, + }; + + /// + public Resource Detect() + { + List> attributeList = new List>(); + try + { + var containerAppName = Environment.GetEnvironmentVariable(ResourceAttributeConstants.AzureContainerAppsNameEnvVar); + var containerAppJobName = Environment.GetEnvironmentVariable(ResourceAttributeConstants.AzureContainerAppJobNameEnvVar); + + if (containerAppName != null) + { + AddBaseAttributes(attributeList, containerAppName); + + AddResourceAttributes(attributeList, AzureContainerAppResourceAttributes); + } + else if (containerAppJobName != null) + { + AddBaseAttributes(attributeList, containerAppJobName); + + AddResourceAttributes(attributeList, AzureContainerAppJobResourceAttributes); + } + } + catch + { + // TODO: log exception. + return Resource.Empty; + } + + return new Resource(attributeList); + } + + private static void AddResourceAttributes(List> attributeList, IReadOnlyDictionary resourceAttributes) + { + foreach (var kvp in resourceAttributes) + { + var attributeValue = Environment.GetEnvironmentVariable(kvp.Value); + if (attributeValue != null) + { + attributeList.Add(new KeyValuePair(kvp.Key, attributeValue)); + } + } + } + + private static void AddBaseAttributes(List> attributeList, string serviceName) + { + attributeList.Add(new KeyValuePair(ResourceSemanticConventions.AttributeServiceName, serviceName)); + attributeList.Add(new KeyValuePair(ResourceSemanticConventions.AttributeCloudProvider, ResourceAttributeConstants.AzureCloudProviderValue)); + attributeList.Add(new KeyValuePair(ResourceSemanticConventions.AttributeCloudPlatform, ResourceAttributeConstants.AzureContainerAppsPlatformValue)); + } + } +} diff --git a/NETCORE/src/Shared/Vendoring/OpenTelemetry.Resources.Azure/AzureResourceBuilderExtensions.cs b/NETCORE/src/Shared/Vendoring/OpenTelemetry.Resources.Azure/AzureResourceBuilderExtensions.cs new file mode 100644 index 000000000..4ebfd2b3d --- /dev/null +++ b/NETCORE/src/Shared/Vendoring/OpenTelemetry.Resources.Azure/AzureResourceBuilderExtensions.cs @@ -0,0 +1,47 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +namespace Microsoft.ApplicationInsights.Shared.Vendoring.OpenTelemetry.Resources +{ + using global::OpenTelemetry.Resources; + using Microsoft.ApplicationInsights.Shared.Vendoring.OpenTelemetry.Resources.Azure; + + /// + /// Extension methods to simplify registering of Azure resource detectors. + /// + internal static class AzureResourceBuilderExtensions + { + /// + /// Enables Azure App Service resource detector. + /// + /// The being configured. + /// The instance of being configured. + public static ResourceBuilder AddAzureAppServiceDetector(this ResourceBuilder builder) + { + Guard.ThrowIfNull(builder); + return builder.AddDetector(new AppServiceResourceDetector()); + } + + /// + /// Enables Azure VM resource detector. + /// + /// The being configured. + /// The instance of being configured. + public static ResourceBuilder AddAzureVMDetector(this ResourceBuilder builder) + { + Guard.ThrowIfNull(builder); + return builder.AddDetector(new AzureVMResourceDetector()); + } + + /// + /// Enables Azure Container Apps resource detector. + /// + /// The being configured. + /// The instance of being configured. + public static ResourceBuilder AddAzureContainerAppsDetector(this ResourceBuilder builder) + { + Guard.ThrowIfNull(builder); + return builder.AddDetector(new AzureContainerAppsResourceDetector()); + } + } +} diff --git a/NETCORE/src/Shared/Vendoring/OpenTelemetry.Resources.Azure/AzureVMResourceDetector.cs b/NETCORE/src/Shared/Vendoring/OpenTelemetry.Resources.Azure/AzureVMResourceDetector.cs new file mode 100644 index 000000000..69c6737f5 --- /dev/null +++ b/NETCORE/src/Shared/Vendoring/OpenTelemetry.Resources.Azure/AzureVMResourceDetector.cs @@ -0,0 +1,72 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 +#nullable enable + +namespace Microsoft.ApplicationInsights.Shared.Vendoring.OpenTelemetry.Resources.Azure +{ + using System.Collections.Generic; + using global::OpenTelemetry; + using global::OpenTelemetry.Resources; + + /// + /// Resource detector for Azure VM environment. + /// + internal sealed class AzureVMResourceDetector : IResourceDetector + { + internal static readonly IReadOnlyCollection ExpectedAzureAmsFields = + [ + ResourceAttributeConstants.AzureVmScaleSetName, + ResourceAttributeConstants.AzureVmSku, + ResourceSemanticConventions.AttributeCloudPlatform, + ResourceSemanticConventions.AttributeCloudProvider, + ResourceSemanticConventions.AttributeCloudRegion, + ResourceSemanticConventions.AttributeCloudResourceId, + ResourceSemanticConventions.AttributeHostId, + ResourceSemanticConventions.AttributeHostName, + ResourceSemanticConventions.AttributeHostType, + ResourceSemanticConventions.AttributeOsType, + ResourceSemanticConventions.AttributeOsVersion, + ResourceSemanticConventions.AttributeServiceInstance + ]; + + private static Resource? vmResource; + + /// + public Resource Detect() + { + try + { + if (vmResource != null) + { + return vmResource; + } + + // Prevents the http operations from being instrumented. + using var scope = SuppressInstrumentationScope.Begin(); + + var vmMetaDataResponse = AzureVmMetaDataRequestor.GetAzureVmMetaDataResponse(); + if (vmMetaDataResponse == null) + { + vmResource = Resource.Empty; + + return vmResource; + } + + var attributeList = new List>(ExpectedAzureAmsFields.Count); + foreach (var field in ExpectedAzureAmsFields) + { + attributeList.Add(new KeyValuePair(field, vmMetaDataResponse.GetValueForField(field))); + } + + vmResource = new Resource(attributeList); + } + catch + { + // TODO: log exception. + vmResource = Resource.Empty; + } + + return vmResource; + } + } +} diff --git a/NETCORE/src/Shared/Vendoring/OpenTelemetry.Resources.Azure/AzureVmMetaDataRequestor.cs b/NETCORE/src/Shared/Vendoring/OpenTelemetry.Resources.Azure/AzureVmMetaDataRequestor.cs new file mode 100644 index 000000000..1c4e9df0d --- /dev/null +++ b/NETCORE/src/Shared/Vendoring/OpenTelemetry.Resources.Azure/AzureVmMetaDataRequestor.cs @@ -0,0 +1,40 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 +namespace Microsoft.ApplicationInsights.Shared.Vendoring.OpenTelemetry.Resources.Azure +{ + using System; + using System.Net.Http; +#nullable enable + + using System.Text.Json; + + internal static class AzureVmMetaDataRequestor + { + private const string AzureVmMetadataEndpointURL = "http://169.254.169.254/metadata/instance/compute?api-version=2021-12-13&format=json"; + + public static Func GetAzureVmMetaDataResponse { get; internal set; } = GetAzureVmMetaDataResponseDefault!; + + public static AzureVmMetadataResponse? GetAzureVmMetaDataResponseDefault() + { + using var httpClient = new HttpClient() { Timeout = TimeSpan.FromSeconds(2) }; + + httpClient.DefaultRequestHeaders.Add("Metadata", "True"); +#pragma warning disable AZC0102 // Do not use GetAwaiter().GetResult(). +#pragma warning disable AZC0104 // Use EnsureCompleted() directly on asynchronous method return value. + var res = httpClient.GetStringAsync(new Uri(AzureVmMetadataEndpointURL)).ConfigureAwait(false).GetAwaiter().GetResult(); +#pragma warning restore AZC0104 // Use EnsureCompleted() directly on asynchronous method return value. +#pragma warning restore AZC0102 // Do not use GetAwaiter().GetResult(). + + if (res != null) + { +#if NET + return JsonSerializer.Deserialize(res, SourceGenerationContext.Default.AzureVmMetadataResponse); +#else + return JsonSerializer.Deserialize(res); +#endif + } + + return null; + } + } +} diff --git a/NETCORE/src/Shared/Vendoring/OpenTelemetry.Resources.Azure/AzureVmMetadataResponse.cs b/NETCORE/src/Shared/Vendoring/OpenTelemetry.Resources.Azure/AzureVmMetadataResponse.cs new file mode 100644 index 000000000..cc6e51200 --- /dev/null +++ b/NETCORE/src/Shared/Vendoring/OpenTelemetry.Resources.Azure/AzureVmMetadataResponse.cs @@ -0,0 +1,92 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 +#nullable enable + +namespace Microsoft.ApplicationInsights.Shared.Vendoring.OpenTelemetry.Resources.Azure +{ + using System.Text.Json.Serialization; + + internal sealed class AzureVmMetadataResponse + { + [JsonPropertyName("location")] + public string? Location { get; set; } + + [JsonPropertyName("name")] + public string? Name { get; set; } + + [JsonPropertyName("osType")] + public string? OsType { get; set; } + + [JsonPropertyName("resourceGroupName")] + public string? ResourceGroupName { get; set; } + + [JsonPropertyName("resourceId")] + public string? ResourceId { get; set; } + + [JsonPropertyName("sku")] + public string? Sku { get; set; } + + [JsonPropertyName("subscriptionId")] + public string? SubscriptionId { get; set; } + + [JsonPropertyName("version")] + public string? Version { get; set; } + + [JsonPropertyName("vmId")] + public string? VmId { get; set; } + + [JsonPropertyName("vmScaleSetName")] + public string? VmScaleSetName { get; set; } + + [JsonPropertyName("vmSize")] + public string? VmSize { get; set; } + + internal string GetValueForField(string fieldName) + { + string? amsValue = null; + switch (fieldName) + { + case ResourceSemanticConventions.AttributeCloudPlatform: + amsValue = ResourceAttributeConstants.AzureVmCloudPlatformValue; + break; + case ResourceSemanticConventions.AttributeCloudProvider: + amsValue = ResourceAttributeConstants.AzureCloudProviderValue; + break; + case ResourceSemanticConventions.AttributeCloudRegion: + amsValue = this.Location; + break; + case ResourceSemanticConventions.AttributeCloudResourceId: + amsValue = this.ResourceId; + break; + case ResourceSemanticConventions.AttributeHostId: + case ResourceSemanticConventions.AttributeServiceInstance: + amsValue = this.VmId; + break; + case ResourceSemanticConventions.AttributeHostName: + amsValue = this.Name; + break; + case ResourceSemanticConventions.AttributeHostType: + amsValue = this.VmSize; + break; + case ResourceSemanticConventions.AttributeOsType: + amsValue = this.OsType; + break; + case ResourceSemanticConventions.AttributeOsVersion: + amsValue = this.Version; + break; + case ResourceAttributeConstants.AzureVmScaleSetName: + amsValue = this.VmScaleSetName; + break; + case ResourceAttributeConstants.AzureVmSku: + amsValue = this.Sku; + break; + default: + break; + } + + amsValue ??= string.Empty; + + return amsValue; + } + } +} diff --git a/NETCORE/src/Shared/Vendoring/OpenTelemetry.Resources.Azure/Guard.cs b/NETCORE/src/Shared/Vendoring/OpenTelemetry.Resources.Azure/Guard.cs new file mode 100644 index 000000000..c2aed56fe --- /dev/null +++ b/NETCORE/src/Shared/Vendoring/OpenTelemetry.Resources.Azure/Guard.cs @@ -0,0 +1,203 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 +#nullable enable + +// Note: For some targets this file will contain more than one type/namespace. +#pragma warning disable IDE0161 // Convert to file-scoped namespace +#pragma warning disable SA1200 // Using directives should be placed correctly +using System; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; +using System.Runtime.CompilerServices; +using System.Threading; +#pragma warning restore SA1200 // Using directives should be placed correctly +#pragma warning disable SA1402 // File may only contain a single type +#pragma warning disable SA1403 // File may only contain a single namespace +#pragma warning disable SA1649 // File name should match first type name + +#if !NET +namespace System.Runtime.CompilerServices +{ + /// Allows capturing of the expressions passed to a method. + [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] + internal sealed class CallerArgumentExpressionAttribute : Attribute + { + public CallerArgumentExpressionAttribute(string parameterName) + { + this.ParameterName = parameterName; + } + + public string ParameterName { get; } + } +} +#endif + +#if !NET && !NETSTANDARD2_1_OR_GREATER +namespace System.Diagnostics.CodeAnalysis +{ + /// Specifies that an output is not even if + /// the corresponding type allows it. Specifies that an input argument was + /// not when the call returns. + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, Inherited = false)] + internal sealed class NotNullAttribute : Attribute + { + } +} +#endif + +namespace Microsoft.ApplicationInsights.Shared.Vendoring.OpenTelemetry.Resources.Azure +{ + /// + /// Methods for guarding against exception throwing values. + /// + internal static class Guard + { + /// + /// Throw an exception if the value is null. + /// + /// The value to check. + /// The parameter name to use in the thrown exception. + [DebuggerHidden] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ThrowIfNull([NotNull] object? value, [CallerArgumentExpression(nameof(value))] string? paramName = null) + { + if (value is null) + { + throw new ArgumentNullException(paramName, "Must not be null"); + } + } + + /// + /// Throw an exception if the value is null or empty. + /// + /// The value to check. + /// The parameter name to use in the thrown exception. + [DebuggerHidden] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ThrowIfNullOrEmpty([NotNull] string? value, [CallerArgumentExpression(nameof(value))] string? paramName = null) +#pragma warning disable CS8777 // Parameter must have a non-null value when exiting. + { + if (string.IsNullOrEmpty(value)) + { + throw new ArgumentException("Must not be null or empty", paramName); + } + } +#pragma warning restore CS8777 // Parameter must have a non-null value when exiting. + + /// + /// Throw an exception if the value is null or whitespace. + /// + /// The value to check. + /// The parameter name to use in the thrown exception. + [DebuggerHidden] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ThrowIfNullOrWhitespace([NotNull] string? value, [CallerArgumentExpression(nameof(value))] string? paramName = null) +#pragma warning disable CS8777 // Parameter must have a non-null value when exiting. + { + if (string.IsNullOrWhiteSpace(value)) + { + throw new ArgumentException("Must not be null or whitespace", paramName); + } + } +#pragma warning restore CS8777 // Parameter must have a non-null value when exiting. + + /// + /// Throw an exception if the value is zero. + /// + /// The value to check. + /// The message to use in the thrown exception. + /// The parameter name to use in the thrown exception. + [DebuggerHidden] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ThrowIfZero(int value, string message = "Must not be zero", [CallerArgumentExpression(nameof(value))] string? paramName = null) + { + if (value == 0) + { + throw new ArgumentException(message, paramName); + } + } + + /// + /// Throw an exception if the value is not considered a valid timeout. + /// + /// The value to check. + /// The parameter name to use in the thrown exception. + [DebuggerHidden] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ThrowIfInvalidTimeout(int value, [CallerArgumentExpression(nameof(value))] string? paramName = null) + { + ThrowIfOutOfRange(value, paramName, min: Timeout.Infinite, message: $"Must be non-negative or '{nameof(Timeout)}.{nameof(Timeout.Infinite)}'"); + } + + /// + /// Throw an exception if the value is not within the given range. + /// + /// The value to check. + /// The parameter name to use in the thrown exception. + /// The inclusive lower bound. + /// The inclusive upper bound. + /// The name of the lower bound. + /// The name of the upper bound. + /// An optional custom message to use in the thrown exception. + [DebuggerHidden] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ThrowIfOutOfRange(int value, [CallerArgumentExpression(nameof(value))] string? paramName = null, int min = int.MinValue, int max = int.MaxValue, string? minName = null, string? maxName = null, string? message = null) + { + Range(value, paramName, min, max, minName, maxName, message); + } + + /// + /// Throw an exception if the value is not within the given range. + /// + /// The value to check. + /// The parameter name to use in the thrown exception. + /// The inclusive lower bound. + /// The inclusive upper bound. + /// The name of the lower bound. + /// The name of the upper bound. + /// An optional custom message to use in the thrown exception. + [DebuggerHidden] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ThrowIfOutOfRange(double value, [CallerArgumentExpression(nameof(value))] string? paramName = null, double min = double.MinValue, double max = double.MaxValue, string? minName = null, string? maxName = null, string? message = null) + { + Range(value, paramName, min, max, minName, maxName, message); + } + + /// + /// Throw an exception if the value is not of the expected type. + /// + /// The value to check. + /// The parameter name to use in the thrown exception. + /// The type attempted to convert to. + /// The value casted to the specified type. + [DebuggerHidden] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T ThrowIfNotOfType([NotNull] object? value, [CallerArgumentExpression(nameof(value))] string? paramName = null) + { + return value is not T result + ? throw new InvalidCastException($"Cannot cast '{paramName}' from '{value?.GetType().ToString() ?? "null"}' to '{typeof(T)}'") + : result; + } + + [DebuggerHidden] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void Range(T value, string? paramName, T min, T max, string? minName, string? maxName, string? message) + where T : IComparable + { + if (value.CompareTo(min) < 0 || value.CompareTo(max) > 0) + { + var minMessage = minName != null ? $": {minName}" : string.Empty; + var maxMessage = maxName != null ? $": {maxName}" : string.Empty; + var exMessage = message ?? string.Format( + CultureInfo.InvariantCulture, + "Must be in the range: [{0}{1}, {2}{3}]", + min, + minMessage, + max, + maxMessage); + throw new ArgumentOutOfRangeException(paramName, value, exMessage); + } + } + } +} diff --git a/NETCORE/src/Shared/Vendoring/OpenTelemetry.Resources.Azure/ResourceAttributeConstants.cs b/NETCORE/src/Shared/Vendoring/OpenTelemetry.Resources.Azure/ResourceAttributeConstants.cs new file mode 100644 index 000000000..c0c86a043 --- /dev/null +++ b/NETCORE/src/Shared/Vendoring/OpenTelemetry.Resources.Azure/ResourceAttributeConstants.cs @@ -0,0 +1,39 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +namespace Microsoft.ApplicationInsights.Shared.Vendoring.OpenTelemetry.Resources.Azure; + +internal sealed class ResourceAttributeConstants +{ + // AppService resource attributes + internal const string AzureAppServiceStamp = "azure.app.service.stamp"; + + // Azure VM resource attributes + internal const string AzureVmScaleSetName = "azure.vm.scaleset.name"; + internal const string AzureVmSku = "azure.vm.sku"; + + // AppService environment variables + internal const string AppServiceHostNameEnvVar = "WEBSITE_HOSTNAME"; + internal const string AppServiceInstanceIdEnvVar = "WEBSITE_INSTANCE_ID"; + internal const string AppServiceOwnerNameEnvVar = "WEBSITE_OWNER_NAME"; + internal const string AppServiceRegionNameEnvVar = "REGION_NAME"; + internal const string AppServiceResourceGroupEnvVar = "WEBSITE_RESOURCE_GROUP"; + internal const string AppServiceSiteNameEnvVar = "WEBSITE_SITE_NAME"; + internal const string AppServiceSlotNameEnvVar = "WEBSITE_SLOT_NAME"; + internal const string AppServiceStampNameEnvVar = "WEBSITE_HOME_STAMPNAME"; + + // Azure Container Apps environment variables + internal const string AzureContainerAppsNameEnvVar = "CONTAINER_APP_NAME"; + internal const string AzureContainerAppsReplicaNameEnvVar = "CONTAINER_APP_REPLICA_NAME"; + internal const string AzureContainerAppsRevisionEnvVar = "CONTAINER_APP_REVISION"; + + // Azure Container Apps Jobs environment variables + internal const string AzureContainerAppJobNameEnvVar = "CONTAINER_APP_JOB_NAME"; + internal const string AzureContainerAppJobExecutionNameEnvVar = "CONTAINER_APP_JOB_EXECUTION_NAME"; + + // Azure resource attributes constant values + internal const string AzureAppServicePlatformValue = "azure_app_service"; + internal const string AzureCloudProviderValue = "azure"; + internal const string AzureVmCloudPlatformValue = "azure_vm"; + internal const string AzureContainerAppsPlatformValue = "azure_container_apps"; +} diff --git a/NETCORE/src/Shared/Vendoring/OpenTelemetry.Resources.Azure/ResourceSemanticConventions.cs b/NETCORE/src/Shared/Vendoring/OpenTelemetry.Resources.Azure/ResourceSemanticConventions.cs new file mode 100644 index 000000000..383e41e01 --- /dev/null +++ b/NETCORE/src/Shared/Vendoring/OpenTelemetry.Resources.Azure/ResourceSemanticConventions.cs @@ -0,0 +1,59 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +namespace Microsoft.ApplicationInsights.Shared.Vendoring.OpenTelemetry.Resources.Azure; + +internal static class ResourceSemanticConventions +{ + public const string AttributeServiceName = "service.name"; + public const string AttributeServiceNamespace = "service.namespace"; + public const string AttributeServiceInstance = "service.instance.id"; + public const string AttributeServiceVersion = "service.version"; + + public const string AttributeTelemetrySdkName = "telemetry.sdk.name"; + public const string AttributeTelemetrySdkLanguage = "telemetry.sdk.language"; + public const string AttributeTelemetrySdkVersion = "telemetry.sdk.version"; + + public const string AttributeContainerName = "container.name"; + public const string AttributeContainerImage = "container.image.name"; + public const string AttributeContainerTag = "container.image.tag"; + + public const string AttributeFaasName = "faas.name"; + public const string AttributeFaasId = "faas.id"; + public const string AttributeFaasVersion = "faas.version"; + public const string AttributeFaasInstance = "faas.instance"; + + public const string AttributeK8sCluster = "k8s.cluster.name"; + public const string AttributeK8sNamespace = "k8s.namespace.name"; + public const string AttributeK8sPod = "k8s.pod.name"; + public const string AttributeK8sDeployment = "k8s.deployment.name"; + + public const string AttributeHostHostname = "host.hostname"; + public const string AttributeHostId = "host.id"; + public const string AttributeHostName = "host.name"; + public const string AttributeHostType = "host.type"; + public const string AttributeHostImageName = "host.image.name"; + public const string AttributeHostImageId = "host.image.id"; + public const string AttributeHostImageVersion = "host.image.version"; + + public const string AttributeProcessId = "process.id"; + public const string AttributeProcessExecutableName = "process.executable.name"; + public const string AttributeProcessExecutablePath = "process.executable.path"; + public const string AttributeProcessCommand = "process.command"; + public const string AttributeProcessCommandLine = "process.command_line"; + public const string AttributeProcessUsername = "process.username"; + + public const string AttributeCloudAccount = "cloud.account.id"; + public const string AttributeCloudAvailabilityZone = "cloud.availability_zone"; + public const string AttributeCloudPlatform = "cloud.platform"; + public const string AttributeCloudProvider = "cloud.provider"; + public const string AttributeCloudRegion = "cloud.region"; + public const string AttributeCloudResourceId = "cloud.resource_id"; + public const string AttributeCloudZone = "cloud.zone"; + public const string AttributeComponent = "component"; + + public const string AttributeOsType = "os.type"; + public const string AttributeOsVersion = "os.version"; + + public const string AttributeDeploymentEnvironment = "deployment.environment"; +} diff --git a/NETCORE/src/Shared/Vendoring/OpenTelemetry.Resources.Azure/SourceGenerationContext.cs b/NETCORE/src/Shared/Vendoring/OpenTelemetry.Resources.Azure/SourceGenerationContext.cs new file mode 100644 index 000000000..f193022b4 --- /dev/null +++ b/NETCORE/src/Shared/Vendoring/OpenTelemetry.Resources.Azure/SourceGenerationContext.cs @@ -0,0 +1,22 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#if NET +namespace Microsoft.ApplicationInsights.Shared.Vendoring.OpenTelemetry.Resources.Azure +{ + using System.Text.Json.Serialization; + + /// + /// "Source Generation" is feature added to System.Text.Json in .NET 6.0. + /// This is a performance optimization that avoids runtime reflection when performing serialization. + /// Serialization metadata will be computed at compile-time and included in the assembly. + /// . + /// . + /// . + /// + [JsonSerializable(typeof(AzureVmMetadataResponse))] + internal sealed partial class SourceGenerationContext : JsonSerializerContext + { + } +} +#endif