diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 229f08131b..d0f4aa71b2 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -54,6 +54,7 @@ body: - OpenTelemetry.ResourceDetectors.Host - OpenTelemetry.ResourceDetectors.Process - OpenTelemetry.ResourceDetectors.ProcessRuntime + - OpenTelemetry.Resources.Gcp - OpenTelemetry.Sampler.AWS - OpenTelemetry.SemanticConventions validations: diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml index 9fecb78998..2d8c7483d7 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -54,6 +54,7 @@ body: - OpenTelemetry.ResourceDetectors.Host - OpenTelemetry.ResourceDetectors.Process - OpenTelemetry.ResourceDetectors.ProcessRuntime + - OpenTelemetry.Resources.Gcp - OpenTelemetry.Sampler.AWS - OpenTelemetry.SemanticConventions diff --git a/.github/codecov.yml b/.github/codecov.yml index 93c6e5eb08..3981524084 100644 --- a/.github/codecov.yml +++ b/.github/codecov.yml @@ -119,6 +119,11 @@ flags: paths: - src/OpenTelemetry.ResourceDetectors.Azure + unittests-Resources.Gcp: + carryforward: true + paths: + - src/OpenTelemetry.Resources.Gcp + unittests-ResourceDetectors.Host: carryforward: true paths: diff --git a/.github/component_owners.yml b/.github/component_owners.yml index 73aba2c284..7df093a797 100644 --- a/.github/component_owners.yml +++ b/.github/component_owners.yml @@ -79,6 +79,9 @@ components: src/OpenTelemetry.ResourceDetectors.ProcessRuntime/: - Kielek - lachmatt + src/OpenTelemetry.Resources.Gcp/: + - matt-hensley + - pyohannes src/OpenTelemetry.Sampler.AWS/: - srprash - atshaw43 @@ -169,6 +172,9 @@ components: test/OpenTelemetry.ResourceDetectors.ProcessRuntime.Tests/: - Kielek - lachmatt + test/OpenTelemetry.Resources.Gcp.Tests/: + - matt-hensley + - pyohannes test/OpenTelemetry.Sampler.AWS.Tests/: - srprash - atshaw43 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a6e0614a40..f07c34505b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,6 +30,7 @@ jobs: eventcounters: ['*/OpenTelemetry.Instrumentation.EventCounters*/**', 'examples/event-counters/**', '!**/*.md'] extensions: ['*/OpenTelemetry.Extensions/**', '*/OpenTelemetry.Extensions.Tests/**', '!**/*.md'] geneva: ['*/OpenTelemetry.Exporter.Geneva*/**', '!**/*.md'] + gcp: ['*/OpenTelemetry.Resources.Gcp*/**', '!**/*.md'] grpcnetclient: ['*/OpenTelemetry.Instrumentation.GrpcNetClient*/**', '!**/*.md'] host: ['*/OpenTelemetry.ResourceDetectors.Host*/**', '!**/*.md'] http: ['*/OpenTelemetry.Instrumentation.Http*/**', '!**/*.md'] @@ -59,6 +60,7 @@ jobs: '!*/OpenTelemetry.ResourceDetectors.Process.Tests/**', '!*/OpenTelemetry.ResourceDetectors.ProcessRuntime/**', '!*/OpenTelemetry.ResourceDetectors.ProcessRuntime.Tests/**', + '!*/OpenTelemetry.Resources.Gcp*/**', '!*/OpenTelemetry.Instrumentation.EventCounters*/**', '!examples/event-counters/**', '!*/OpenTelemetry.Extensions/**', @@ -167,6 +169,17 @@ jobs: project-name: OpenTelemetry.Exporter.Geneva code-cov-name: Exporter.Geneva + build-test-gcp: + needs: detect-changes + if: | + contains(needs.detect-changes.outputs.changes, 'gcp') + || contains(needs.detect-changes.outputs.changes, 'build') + || contains(needs.detect-changes.outputs.changes, 'shared') + uses: ./.github/workflows/Component.BuildTest.yml + with: + project-name: OpenTelemetry.Resources.Gcp + code-cov-name: Resources.Gcp + build-test-grpcnetclient: needs: detect-changes if: | @@ -379,7 +392,8 @@ jobs: OpenTelemetry.ResourceDetectors.Azure.Tests.csproj, OpenTelemetry.ResourceDetectors.Host.Tests.csproj, OpenTelemetry.ResourceDetectors.Process.Tests.csproj, - OpenTelemetry.ResourceDetectors.ProcessRuntime.Tests.csproj + OpenTelemetry.ResourceDetectors.ProcessRuntime.Tests.csproj, + OpenTelemetry.Resources.Gcp.Tests.csproj $failedProjects = @() @@ -426,6 +440,7 @@ jobs: || contains(needs.detect-changes.outputs.changes, 'aws') || contains(needs.detect-changes.outputs.changes, 'azure') || contains(needs.detect-changes.outputs.changes, 'extensions') + || contains(needs.detect-changes.outputs.changes, 'gcp') || contains(needs.detect-changes.outputs.changes, 'grpcnetclient') || contains(needs.detect-changes.outputs.changes, 'host') || contains(needs.detect-changes.outputs.changes, 'http') @@ -454,6 +469,7 @@ jobs: build-test-eventcounters, build-test-extensions, build-test-geneva, + build-test-gcp, build-test-grpcnetclient, build-test-host, build-test-http, diff --git a/.github/workflows/package-Resources.Gcp.yml b/.github/workflows/package-Resources.Gcp.yml new file mode 100644 index 0000000000..a10b917607 --- /dev/null +++ b/.github/workflows/package-Resources.Gcp.yml @@ -0,0 +1,21 @@ +name: Pack OpenTelemetry.Resources.Gcp + +on: + workflow_dispatch: + inputs: + logLevel: + description: 'Log level' + required: true + default: 'warning' + push: + tags: + - 'Resources.Gcp-*' # trigger when we create a tag with prefix "Resources.Gcp-" + +jobs: + call-build-test-pack: + permissions: + contents: write + uses: ./.github/workflows/Component.Package.yml + with: + project-name: OpenTelemetry.Resources.Gcp + secrets: inherit diff --git a/build/Projects/OpenTelemetry.Resources.Gcp.proj b/build/Projects/OpenTelemetry.Resources.Gcp.proj new file mode 100644 index 0000000000..19364c3155 --- /dev/null +++ b/build/Projects/OpenTelemetry.Resources.Gcp.proj @@ -0,0 +1,32 @@ + + + + $([System.IO.Directory]::GetParent($(MSBuildThisFileDirectory)).Parent.Parent.FullName) + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/opentelemetry-dotnet-contrib.sln b/opentelemetry-dotnet-contrib.sln index 0809cbac97..e8bfaa1c85 100644 --- a/opentelemetry-dotnet-contrib.sln +++ b/opentelemetry-dotnet-contrib.sln @@ -338,6 +338,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Projects", "Projects", "{04 build\Projects\OpenTelemetry.ResourceDetectors.Host.proj = build\Projects\OpenTelemetry.ResourceDetectors.Host.proj build\Projects\OpenTelemetry.ResourceDetectors.Process.proj = build\Projects\OpenTelemetry.ResourceDetectors.Process.proj build\Projects\OpenTelemetry.ResourceDetectors.ProcessRuntime.proj = build\Projects\OpenTelemetry.ResourceDetectors.ProcessRuntime.proj + build\Projects\OpenTelemetry.Resources.Gcp.proj = build\Projects\OpenTelemetry.Resources.Gcp.proj build\Projects\OpenTelemetry.SemanticConventions.proj = build\Projects\OpenTelemetry.SemanticConventions.proj EndProjectSection EndProject @@ -355,6 +356,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.ResourceDetec EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.PersistentStorage.Abstractions.Tests", "test\OpenTelemetry.PersistentStorage.Abstractions.Tests\OpenTelemetry.PersistentStorage.Abstractions.Tests.csproj", "{7AD707F9-DC6D-430A-8834-D5DCD517BF6E}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Resources.Gcp", "src\OpenTelemetry.Resources.Gcp\OpenTelemetry.Resources.Gcp.csproj", "{CBC6D677-D1FF-470E-A244-477E8616A245}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Resources.Gcp.Tests", "test\OpenTelemetry.Resources.Gcp.Tests\OpenTelemetry.Resources.Gcp.Tests.csproj", "{EECE8D5F-C319-42E8-B37C-A41D6FF43E4A}" +EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Instrumentation.SqlClient", "src\OpenTelemetry.Instrumentation.SqlClient\OpenTelemetry.Instrumentation.SqlClient.csproj", "{737D1A9E-5A1A-4F4F-830B-E98ED100994C}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Instrumentation.SqlClient.Tests", "test\OpenTelemetry.Instrumentation.SqlClient.Tests\OpenTelemetry.Instrumentation.SqlClient.Tests.csproj", "{9C996130-74D7-4FB7-8277-2EE6EBA2BFA6}" @@ -749,6 +754,14 @@ Global {1156D564-2E3C-47D6-97C1-FF3ADEDC41C8}.Debug|Any CPU.Build.0 = Debug|Any CPU {1156D564-2E3C-47D6-97C1-FF3ADEDC41C8}.Release|Any CPU.ActiveCfg = Release|Any CPU {1156D564-2E3C-47D6-97C1-FF3ADEDC41C8}.Release|Any CPU.Build.0 = Release|Any CPU + {CBC6D677-D1FF-470E-A244-477E8616A245}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CBC6D677-D1FF-470E-A244-477E8616A245}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CBC6D677-D1FF-470E-A244-477E8616A245}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CBC6D677-D1FF-470E-A244-477E8616A245}.Release|Any CPU.Build.0 = Release|Any CPU + {EECE8D5F-C319-42E8-B37C-A41D6FF43E4A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EECE8D5F-C319-42E8-B37C-A41D6FF43E4A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EECE8D5F-C319-42E8-B37C-A41D6FF43E4A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EECE8D5F-C319-42E8-B37C-A41D6FF43E4A}.Release|Any CPU.Build.0 = Release|Any CPU {0156E342-CE63-46F5-992D-691A7CCB50F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0156E342-CE63-46F5-992D-691A7CCB50F8}.Debug|Any CPU.Build.0 = Debug|Any CPU {0156E342-CE63-46F5-992D-691A7CCB50F8}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -882,6 +895,8 @@ Global {BE92357F-DE09-477D-AFDB-6AD1D7AC7BA1} = {22DF5DC0-1290-4E83-A9D8-6BB7DE3B3E63} {7371E920-ECD0-403A-A009-7A1A301D9763} = {2097345F-4DD3-477D-BC54-A922F9B2B402} {1156D564-2E3C-47D6-97C1-FF3ADEDC41C8} = {2097345F-4DD3-477D-BC54-A922F9B2B402} + {CBC6D677-D1FF-470E-A244-477E8616A245} = {22DF5DC0-1290-4E83-A9D8-6BB7DE3B3E63} + {EECE8D5F-C319-42E8-B37C-A41D6FF43E4A} = {2097345F-4DD3-477D-BC54-A922F9B2B402} {0156E342-CE63-46F5-992D-691A7CCB50F8} = {22DF5DC0-1290-4E83-A9D8-6BB7DE3B3E63} {2E1A5759-1431-4724-8885-3E9447FBF617} = {2097345F-4DD3-477D-BC54-A922F9B2B402} {A8FF0DEB-F371-42FC-8A53-A8C25FE408FC} = {22DF5DC0-1290-4E83-A9D8-6BB7DE3B3E63} diff --git a/src/OpenTelemetry.Resources.Gcp/.publicApi/PublicAPI.Shipped.txt b/src/OpenTelemetry.Resources.Gcp/.publicApi/PublicAPI.Shipped.txt new file mode 100644 index 0000000000..7dc5c58110 --- /dev/null +++ b/src/OpenTelemetry.Resources.Gcp/.publicApi/PublicAPI.Shipped.txt @@ -0,0 +1 @@ +#nullable enable diff --git a/src/OpenTelemetry.Resources.Gcp/.publicApi/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Resources.Gcp/.publicApi/PublicAPI.Unshipped.txt new file mode 100644 index 0000000000..2cd50017d2 --- /dev/null +++ b/src/OpenTelemetry.Resources.Gcp/.publicApi/PublicAPI.Unshipped.txt @@ -0,0 +1,2 @@ +OpenTelemetry.Resources.GcpResourceBuilderExtensions +static OpenTelemetry.Resources.GcpResourceBuilderExtensions.AddGcpDetector(this OpenTelemetry.Resources.ResourceBuilder! builder) -> OpenTelemetry.Resources.ResourceBuilder! diff --git a/src/OpenTelemetry.Resources.Gcp/AssemblyInfo.cs b/src/OpenTelemetry.Resources.Gcp/AssemblyInfo.cs new file mode 100644 index 0000000000..0751701190 --- /dev/null +++ b/src/OpenTelemetry.Resources.Gcp/AssemblyInfo.cs @@ -0,0 +1,10 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +using System.Runtime.CompilerServices; + +#if SIGNED +[assembly: InternalsVisibleTo("OpenTelemetry.Resources.Gcp.Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010051c1562a090fb0c9f391012a32198b5e5d9a60e9b80fa2d7b434c9e5ccb7259bd606e66f9660676afc6692b8cdc6793d190904551d2103b7b22fa636dcbb8208839785ba402ea08fc00c8f1500ccef28bbf599aa64ffb1e1d5dc1bf3420a3777badfe697856e9d52070a50c3ea5821c80bef17ca3acffa28f89dd413f096f898")] +#else +[assembly: InternalsVisibleTo("OpenTelemetry.Resources.Gcp.Tests")] +#endif diff --git a/src/OpenTelemetry.Resources.Gcp/CHANGELOG.md b/src/OpenTelemetry.Resources.Gcp/CHANGELOG.md new file mode 100644 index 0000000000..e1852ed3a7 --- /dev/null +++ b/src/OpenTelemetry.Resources.Gcp/CHANGELOG.md @@ -0,0 +1,9 @@ +# Changelog + +## Unreleased + +* Add Google Cloud Platform resource detector for GKE, GAE, GCR, and GCE. Dectector + is accessible via `AddGcpDetector` extension method on `ResourceBuilder`. + ([#1691](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/1691)) + +For more details, please refer to the [README](README.md). diff --git a/src/OpenTelemetry.Resources.Gcp/GcpResourceBuilderExtensions.cs b/src/OpenTelemetry.Resources.Gcp/GcpResourceBuilderExtensions.cs new file mode 100644 index 0000000000..154242bb04 --- /dev/null +++ b/src/OpenTelemetry.Resources.Gcp/GcpResourceBuilderExtensions.cs @@ -0,0 +1,24 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +using OpenTelemetry.Internal; +using OpenTelemetry.Resources.Gcp; + +namespace OpenTelemetry.Resources; + +/// +/// Extension methods to simplify registering of Google Cloud Platform resource detectors. +/// +public static class GcpResourceBuilderExtensions +{ + /// + /// Enables Google Cloud Platform resource detector. + /// + /// being configured. + /// The instance of being configured. + public static ResourceBuilder AddGcpDetector(this ResourceBuilder builder) + { + Guard.ThrowIfNull(builder); + return builder.AddDetector(new GcpResourceDetector()); + } +} diff --git a/src/OpenTelemetry.Resources.Gcp/GcpResourceDetector.cs b/src/OpenTelemetry.Resources.Gcp/GcpResourceDetector.cs new file mode 100644 index 0000000000..de5d212484 --- /dev/null +++ b/src/OpenTelemetry.Resources.Gcp/GcpResourceDetector.cs @@ -0,0 +1,92 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +using System.Collections.Generic; +using Google.Api.Gax; +using OpenTelemetry.Trace; + +namespace OpenTelemetry.Resources.Gcp; + +/// +/// Resource detector for Google Cloud Platform (GCP). +/// +internal sealed class GcpResourceDetector : IResourceDetector +{ + /// + public Resource Detect() + { + var platform = Platform.Instance(); + + if (platform == null || platform.ProjectId == null) + { + return Resource.Empty; + } + + var attributeList = platform.Type switch + { + PlatformType.Gke => ExtractGkeResourceAttributes(platform), + PlatformType.CloudRun => ExtractCloudRunResourceAttributes(platform), + PlatformType.Gae => ExtractGaeResourceAttributes(platform), + PlatformType.Gce => ExtractGceResourceAttributes(platform), + _ => ExtractGceResourceAttributes(platform), + }; + + return new Resource(attributeList); + } + + internal static List> ExtractGkeResourceAttributes(Platform platform) + { + List> attributeList = new() + { + new(ResourceSemanticConventions.AttributeCloudProvider, ResourceAttributeConstants.GcpCloudProviderValue), + new(ResourceSemanticConventions.AttributeCloudAccount, platform.ProjectId), + new(ResourceSemanticConventions.AttributeCloudPlatform, ResourceAttributeConstants.GcpGkePlatformValue), + new(ResourceSemanticConventions.AttributeCloudZone, platform.GkeDetails.Zone), + new(ResourceSemanticConventions.AttributeHostId, platform.GkeDetails.InstanceId), + new(ResourceSemanticConventions.AttributeK8sCluster, platform.GkeDetails.ClusterName), + new(ResourceSemanticConventions.AttributeK8sNamespace, platform.GkeDetails.NamespaceId), + new(ResourceSemanticConventions.AttributeK8sPod, platform.GkeDetails.HostName), + }; + + return attributeList; + } + + internal static List> ExtractCloudRunResourceAttributes(Platform platform) + { + List> attributeList = new() + { + new(ResourceSemanticConventions.AttributeCloudProvider, ResourceAttributeConstants.GcpCloudProviderValue), + new(ResourceSemanticConventions.AttributeCloudAccount, platform.ProjectId), + new(ResourceSemanticConventions.AttributeCloudAvailabilityZone, platform.CloudRunDetails.Zone), + new(ResourceSemanticConventions.AttributeCloudPlatform, ResourceAttributeConstants.GcpCloudRunPlatformValue), + new(ResourceSemanticConventions.AttributeCloudRegion, platform.CloudRunDetails.Region), + }; + + return attributeList; + } + + internal static List> ExtractGaeResourceAttributes(Platform platform) + { + List> attributeList = new() + { + new(ResourceSemanticConventions.AttributeCloudProvider, ResourceAttributeConstants.GcpCloudProviderValue), + new(ResourceSemanticConventions.AttributeCloudAccount, platform.ProjectId), + new(ResourceSemanticConventions.AttributeCloudPlatform, ResourceAttributeConstants.GcpGaePlatformValue), + }; + return attributeList; + } + + internal static List> ExtractGceResourceAttributes(Platform platform) + { + List> attributeList = new() + { + new(ResourceSemanticConventions.AttributeCloudProvider, ResourceAttributeConstants.GcpCloudProviderValue), + new(ResourceSemanticConventions.AttributeCloudAccount, platform.ProjectId), + new(ResourceSemanticConventions.AttributeCloudPlatform, ResourceAttributeConstants.GcpGcePlatformValue), + new(ResourceSemanticConventions.AttributeHostId, platform.GceDetails.InstanceId), + new(ResourceSemanticConventions.AttributeCloudAvailabilityZone, platform.GceDetails.Location), + }; + + return attributeList; + } +} diff --git a/src/OpenTelemetry.Resources.Gcp/OpenTelemetry.Resources.Gcp.csproj b/src/OpenTelemetry.Resources.Gcp/OpenTelemetry.Resources.Gcp.csproj new file mode 100644 index 0000000000..e0b3c71433 --- /dev/null +++ b/src/OpenTelemetry.Resources.Gcp/OpenTelemetry.Resources.Gcp.csproj @@ -0,0 +1,25 @@ + + + net6.0;netstandard2.0 + OpenTelemetry Resource Detectors for Google Cloud Platform environments + $(PackageTags);ResourceDetector + Resources.Gcp- + + + + + true + + + + + + + + + + + + + diff --git a/src/OpenTelemetry.Resources.Gcp/README.md b/src/OpenTelemetry.Resources.Gcp/README.md new file mode 100644 index 0000000000..3171fa579c --- /dev/null +++ b/src/OpenTelemetry.Resources.Gcp/README.md @@ -0,0 +1,85 @@ +# Resource Detectors for Google Cloud Platform environments + +[![NuGet version badge](https://img.shields.io/nuget/v/OpenTelemetry.Resources.Gcp)](https://www.nuget.org/packages/OpenTelemetry.Resources.Gcp) +[![NuGet download count badge](https://img.shields.io/nuget/dt/OpenTelemetry.ResourceDetectors.Azure)](https://www.nuget.org/packages/OpenTelemetry.ResourceDetectors.Azure) + +This package contains [Resource +Detectors](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/sdk.md#detecting-resource-information-from-the-environment) +for applications running in Google Cloud Platform environments. + +## Installation + +```shell +dotnet add package --prerelease OpenTelemetry.Resources.Gcp +``` + +```csharp +using OpenTelemetry; +using OpenTelemetry.Resources; + +using var meterProvider = Sdk.CreateMeterProviderBuilder() + // other configurations + .ConfigureResource(resource => resource.AddGcpDetector()) + .Build(); + +using var tracerProvider = Sdk.CreateTracerProviderBuilder() + // other configurations + .ConfigureResource(resource => resource.AddGcpDetector()) + .Build(); + +using var loggerFactory = LoggerFactory.Create(builder => +{ + builder.AddOpenTelemetry(options => + { + options.SetResourceBuilder(ResourceBuilder + .CreateDefault() + .AddGcpDetector()); + }); +}); +``` + +## Resource Attributes + +The following OpenTelemetry semantic conventions will be detected depending on +which Google Cloud Platform environment an application is running in. + +### Google Kubernetes Engine + +|-------------------------|-----------------------| +| Attribute | Value | +| cloud.provider | gcp | +| cloud.platform | gcp_kubernetes_engine | +| cloud.account.id | auto | +| cloud.availability_zone | auto | +| host.id | auto | +| k8s.cluster.name | auto | +| k8s.namespace.name | auto | +| k8s.pod.name | auto | + +### Google App Engine + +|-------------------------|----------------| +| Attribute | Value | +| cloud.provider | gcp | +| cloud.platform | gcp_app_engine | +| cloud.account.id | auto | + +### Google Cloud Run + +|-------------------------|---------------| +| Attribute | Value | +| cloud.provider | gcp | +| cloud.platform | gcp_cloud_run | +| cloud.account.id | auto | +| cloud.availability_zone | auto | +| cloud.region | auto | + +### Google Compute Engine + +|-------------------------|--------------------| +| Attribute | Value | +| cloud.provider | gcp | +| cloud.platform | gcp_compute_engine | +| cloud.account.id | auto | +| cloud.availability_zone | auto | +| host.id | auto | diff --git a/src/OpenTelemetry.Resources.Gcp/ResourceAttributeConstants.cs b/src/OpenTelemetry.Resources.Gcp/ResourceAttributeConstants.cs new file mode 100644 index 0000000000..6c9a0b8c36 --- /dev/null +++ b/src/OpenTelemetry.Resources.Gcp/ResourceAttributeConstants.cs @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +namespace OpenTelemetry.Resources.Gcp; + +internal sealed class ResourceAttributeConstants +{ + // GCP resource attributes constant values + internal const string GcpCloudProviderValue = "gcp"; + internal const string GcpGcePlatformValue = "gcp_compute_engine"; + internal const string GcpGaePlatformValue = "gcp_app_engine"; + internal const string GcpCloudRunPlatformValue = "gcp_cloud_run"; + internal const string GcpGkePlatformValue = "gcp_kubernetes_engine"; +} diff --git a/src/Shared/ResourceSemanticConventions.cs b/src/Shared/ResourceSemanticConventions.cs index 4b4aa6a9ea..22903d04bc 100644 --- a/src/Shared/ResourceSemanticConventions.cs +++ b/src/Shared/ResourceSemanticConventions.cs @@ -44,6 +44,7 @@ internal static class ResourceSemanticConventions 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"; diff --git a/test/OpenTelemetry.Resources.Gcp.Tests/GcpResourceDetectorTests.cs b/test/OpenTelemetry.Resources.Gcp.Tests/GcpResourceDetectorTests.cs new file mode 100644 index 0000000000..6369d7fda2 --- /dev/null +++ b/test/OpenTelemetry.Resources.Gcp.Tests/GcpResourceDetectorTests.cs @@ -0,0 +1,96 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +using System.Linq; +using Google.Api.Gax; +using OpenTelemetry.Trace; + +namespace OpenTelemetry.Resources.Gcp.Tests; + +public class GcpResourceDetectorTests +{ + [Fact] + public void TestExtractGkeResourceAttributes() + { + var details = new GkePlatformDetails( + metadataJson: "json", + projectId: "projectId", + clusterName: "clusterName", + location: "location", + hostName: "hostName", + instanceId: "instanceId", + zone: "us-central1-a", + namespaceId: "namespaceId", + podId: "podId", + containerName: "containerName", + clusterLocation: "clusterLocation"); + var platform = new Platform(details); + var attrs = GcpResourceDetector.ExtractGkeResourceAttributes(platform).ToDictionary(x => x.Key, x => x.Value); + Assert.NotNull(attrs); + Assert.Equal(8, attrs.Count); + Assert.Equal(ResourceAttributeConstants.GcpCloudProviderValue, attrs[ResourceSemanticConventions.AttributeCloudProvider]); + Assert.Equal("projectId", attrs[ResourceSemanticConventions.AttributeCloudAccount]); + Assert.Equal(ResourceAttributeConstants.GcpGkePlatformValue, attrs[ResourceSemanticConventions.AttributeCloudPlatform]); + Assert.Equal("us-central1-a", attrs[ResourceSemanticConventions.AttributeCloudZone]); + Assert.Equal("instanceId", attrs[ResourceSemanticConventions.AttributeHostId]); + Assert.Equal("clusterName", attrs[ResourceSemanticConventions.AttributeK8sCluster]); + Assert.Equal("namespaceId", attrs[ResourceSemanticConventions.AttributeK8sNamespace]); + Assert.Equal("hostName", attrs[ResourceSemanticConventions.AttributeK8sPod]); + } + + [Fact] + public void TestExtractCloudRunResourceAttributes() + { + var details = new CloudRunPlatformDetails( + metadataJson: "json", + projectId: "projectId", + zone: "us-central1-a", + serviceName: "serviceName", + revisionName: "revisionName", + configurationName: "configurationName"); + var platform = new Platform(details); + var attrs = GcpResourceDetector.ExtractCloudRunResourceAttributes(platform).ToDictionary(x => x.Key, x => x.Value); + Assert.NotNull(attrs); + Assert.Equal(5, attrs.Count); + Assert.Equal(ResourceAttributeConstants.GcpCloudProviderValue, attrs[ResourceSemanticConventions.AttributeCloudProvider]); + Assert.Equal("projectId", attrs[ResourceSemanticConventions.AttributeCloudAccount]); + Assert.Equal("us-central1-a", attrs[ResourceSemanticConventions.AttributeCloudAvailabilityZone]); + Assert.Equal(ResourceAttributeConstants.GcpCloudRunPlatformValue, attrs[ResourceSemanticConventions.AttributeCloudPlatform]); + Assert.Equal("us-central1", attrs[ResourceSemanticConventions.AttributeCloudRegion]); + } + + [Fact] + public void TestExtractGaeResourceAttributes() + { + var details = new GaePlatformDetails( + gcloudProject: "gcloudProject", + gaeInstance: "gaeInstance", + gaeService: "gaeService", + gaeVersion: "gaeVersion"); + var platform = new Platform(details); + var attrs = GcpResourceDetector.ExtractGaeResourceAttributes(platform).ToDictionary(x => x.Key, x => x.Value); + Assert.NotNull(attrs); + Assert.Equal(3, attrs.Count); + Assert.Equal(ResourceAttributeConstants.GcpCloudProviderValue, attrs[ResourceSemanticConventions.AttributeCloudProvider]); + Assert.Equal("gcloudProject", attrs[ResourceSemanticConventions.AttributeCloudAccount]); + Assert.Equal(ResourceAttributeConstants.GcpGaePlatformValue, attrs[ResourceSemanticConventions.AttributeCloudPlatform]); + } + + [Fact] + public void TestExtractGceResourceAttributes() + { + var details = new GcePlatformDetails( + metadataJson: "json", + projectId: "projectId", + instanceId: "instanceId", + zoneName: "projects/12345/zones/us-central1-a"); + var platform = new Platform(details); + var attrs = GcpResourceDetector.ExtractGceResourceAttributes(platform).ToDictionary(x => x.Key, x => x.Value); + Assert.NotNull(attrs); + Assert.Equal(5, attrs.Count); + Assert.Equal(ResourceAttributeConstants.GcpCloudProviderValue, attrs[ResourceSemanticConventions.AttributeCloudProvider]); + Assert.Equal("projectId", attrs[ResourceSemanticConventions.AttributeCloudAccount]); + Assert.Equal(ResourceAttributeConstants.GcpGcePlatformValue, attrs[ResourceSemanticConventions.AttributeCloudPlatform]); + Assert.Equal("instanceId", attrs[ResourceSemanticConventions.AttributeHostId]); + } +} diff --git a/test/OpenTelemetry.Resources.Gcp.Tests/GlobalUsings.cs b/test/OpenTelemetry.Resources.Gcp.Tests/GlobalUsings.cs new file mode 100644 index 0000000000..c9112be5f0 --- /dev/null +++ b/test/OpenTelemetry.Resources.Gcp.Tests/GlobalUsings.cs @@ -0,0 +1,4 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +global using Xunit; diff --git a/test/OpenTelemetry.Resources.Gcp.Tests/OpenTelemetry.Resources.Gcp.Tests.csproj b/test/OpenTelemetry.Resources.Gcp.Tests/OpenTelemetry.Resources.Gcp.Tests.csproj new file mode 100644 index 0000000000..e1df281415 --- /dev/null +++ b/test/OpenTelemetry.Resources.Gcp.Tests/OpenTelemetry.Resources.Gcp.Tests.csproj @@ -0,0 +1,18 @@ + + + + Unit test project for GCP Detector for OpenTelemetry + + $(SupportedNetTargets) + $(TargetFrameworks);$(NetFrameworkMinimumSupportedVersion) + + + + + + + + + + +