├── .github ├── CODEOWNERS ├── header-checker-lint.yml ├── trusted-contribution.yml └── workflows │ ├── ci.yml │ └── codeql-analysis.yml ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── RELEASING.md ├── SECURITY.md ├── cloudbuild-e2e-cloud-functions-gen2.yaml ├── cloudbuild-e2e-cloud-run.yaml ├── cloudbuild-e2e-gae-standard.yaml ├── cloudbuild-e2e-gae.yaml ├── cloudbuild-e2e-gce.yaml ├── cloudbuild-e2e-gke.yaml ├── cloudbuild-e2e-image.yaml ├── cloudbuild-e2e-local.yaml ├── cloudbuild-integration-tests.yaml ├── detectors └── gcp │ ├── README.md │ ├── app_engine.go │ ├── app_engine_test.go │ ├── bms.go │ ├── bms_test.go │ ├── detector.go │ ├── detector_print_test.go │ ├── detector_test.go │ ├── faas.go │ ├── faas_test.go │ ├── gce.go │ ├── gce_test.go │ ├── gke.go │ ├── gke_test.go │ ├── go.mod │ ├── go.sum │ └── utils_test.go ├── doc.go ├── docs ├── code-of-conduct.md └── contributing.md ├── e2e-test-server ├── Dockerfile ├── README.md ├── app.go ├── cloud_functions │ ├── cloud_functions.go │ ├── go.mod │ └── go.sum ├── endtoendserver │ ├── constants.go │ ├── pull_server.go │ ├── push_server.go │ └── server.go ├── go.mod ├── go.sum ├── scenarios │ ├── constants.go │ ├── handler.go │ └── scenarios.go └── wait-for-image.sh ├── example ├── metric │ ├── README.md │ ├── collector │ │ ├── example.go │ │ ├── go.mod │ │ ├── go.sum │ │ └── sample-collector-config.yaml │ ├── dashboards │ │ ├── exponential_histogram_dashboard.json │ │ └── sdk_dashboard.json │ ├── exponential_histogram │ │ ├── README.md │ │ ├── create_dashboard.sh │ │ ├── example.go │ │ ├── go.mod │ │ └── go.sum │ ├── images │ │ ├── exponential_histogram_charts.png │ │ └── sdk_charts.png │ ├── otlpgrpc │ │ ├── README.md │ │ ├── example.go │ │ ├── go.mod │ │ └── go.sum │ └── sdk │ │ ├── README.md │ │ ├── create_dashboard.sh │ │ ├── example.go │ │ ├── go.mod │ │ └── go.sum └── trace │ ├── http │ ├── README.md │ ├── client │ │ └── client.go │ ├── cloudtrace.png │ ├── go.mod │ ├── go.sum │ └── server │ │ └── server.go │ ├── otlpgrpc │ ├── example.go │ ├── go.mod │ └── go.sum │ └── otlphttp │ ├── example.go │ ├── go.mod │ └── go.sum ├── exporter ├── collector │ ├── README.md │ ├── benchmark_test.go │ ├── breaking-changes.md │ ├── config.go │ ├── config_test.go │ ├── go.mod │ ├── go.sum │ ├── googlemanagedprometheus │ │ ├── config.go │ │ ├── extra_metrics.go │ │ ├── extra_metrics_test.go │ │ ├── go.mod │ │ ├── go.sum │ │ ├── monitoredresource.go │ │ ├── monitoredresource_test.go │ │ ├── naming.go │ │ └── naming_test.go │ ├── integrationtest │ │ ├── cmd │ │ │ └── recordfixtures │ │ │ │ └── main.go │ │ ├── config │ │ │ └── config_test.go │ │ ├── diff.go │ │ ├── factory_test.go │ │ ├── go.mod │ │ ├── go.sum │ │ ├── inmemoryotelexporter.go │ │ ├── integration_selfobs_test.go │ │ ├── logs_integration_test.go │ │ ├── logs_test.go │ │ ├── metrics_integration_test.go │ │ ├── metrics_test.go │ │ ├── protos │ │ │ ├── fixtures.go │ │ │ ├── fixtures.pb.go │ │ │ ├── fixtures.proto │ │ │ ├── logging_service.proto │ │ │ ├── metric_service.proto │ │ │ └── tracing_service.proto │ │ ├── testcases │ │ │ ├── conversion.go │ │ │ ├── exporter_settings.go │ │ │ ├── testcase.go │ │ │ ├── testcases_logs.go │ │ │ ├── testcases_metrics.go │ │ │ └── testcases_traces.go │ │ ├── testdata │ │ │ ├── config.yaml │ │ │ ├── fixtures │ │ │ │ ├── logs │ │ │ │ │ ├── logs_apache_access.json │ │ │ │ │ ├── logs_apache_access_batches_expected.json │ │ │ │ │ ├── logs_apache_access_expected.json │ │ │ │ │ ├── logs_apache_access_resource_attributes.json │ │ │ │ │ ├── logs_apache_access_resource_attributes_expected.json │ │ │ │ │ ├── logs_apache_error.json │ │ │ │ │ ├── logs_apache_error_expected.json │ │ │ │ │ ├── logs_apache_error_scope.json │ │ │ │ │ ├── logs_apache_error_scope_expected.json │ │ │ │ │ ├── logs_apache_json_error_reporting_expected.json │ │ │ │ │ ├── logs_apache_text_error.json │ │ │ │ │ ├── logs_apache_text_error_reporting_expected.json │ │ │ │ │ ├── logs_multi_project.json │ │ │ │ │ ├── logs_multi_project_destination_quota_expected.json │ │ │ │ │ ├── logs_multi_project_expected.json │ │ │ │ │ ├── logs_span_trace_id.json │ │ │ │ │ ├── logs_span_trace_id_expected.json │ │ │ │ │ └── logs_user_agent_expected.json │ │ │ │ ├── metrics │ │ │ │ │ ├── batching.json │ │ │ │ │ ├── batching_expect.json │ │ │ │ │ ├── bms_ops_agent_host_metrics.json │ │ │ │ │ ├── bms_ops_agent_host_metrics_expect.json │ │ │ │ │ ├── boolean_gauge.json │ │ │ │ │ ├── boolean_gauge_expect.json │ │ │ │ │ ├── counter.json │ │ │ │ │ ├── counter_compressed_expect.json │ │ │ │ │ ├── counter_expect.json │ │ │ │ │ ├── counter_gmp_expect.json │ │ │ │ │ ├── counter_notfound_expect.json │ │ │ │ │ ├── counter_unknown_domain_expect.json │ │ │ │ │ ├── counter_user_agent_expect.json │ │ │ │ │ ├── counter_wal_deadline_expect.json │ │ │ │ │ ├── counter_wal_expect.json │ │ │ │ │ ├── counter_wal_unavailable_expect.json │ │ │ │ │ ├── counter_workloadgoogleapis_prefix_expect.json │ │ │ │ │ ├── create_service_timeseries.json │ │ │ │ │ ├── create_service_timeseries_expect.json │ │ │ │ │ ├── create_service_timeseries_wal_expect.json │ │ │ │ │ ├── delta_counter.json │ │ │ │ │ ├── delta_counter_expect.json │ │ │ │ │ ├── delta_counter_gmp_expect.json │ │ │ │ │ ├── exponential_histogram.json │ │ │ │ │ ├── exponential_histogram_expect.json │ │ │ │ │ ├── exponential_histogram_gmp_expect.json │ │ │ │ │ ├── gauge.json │ │ │ │ │ ├── gauge_expect.json │ │ │ │ │ ├── gauge_gmp_expect.json │ │ │ │ │ ├── gke_control_plane.json │ │ │ │ │ ├── gke_control_plane_expect.json │ │ │ │ │ ├── gke_metrics_agent.json │ │ │ │ │ ├── gke_metrics_agent_expect.json │ │ │ │ │ ├── google_managed_prometheus.json │ │ │ │ │ ├── google_managed_prometheus_expect.json │ │ │ │ │ ├── google_managed_prometheus_untyped_name_normalized_expect.json │ │ │ │ │ ├── histogram.json │ │ │ │ │ ├── histogram_expect.json │ │ │ │ │ ├── histogram_gmp_expect.json │ │ │ │ │ ├── multi_project.json │ │ │ │ │ ├── multi_project_expected.json │ │ │ │ │ ├── nonmonotonic_counter.json │ │ │ │ │ ├── nonmonotonic_counter_expect.json │ │ │ │ │ ├── nonmonotonic_counter_gmp_expect.json │ │ │ │ │ ├── ops_agent_host_metrics.json │ │ │ │ │ ├── ops_agent_host_metrics_expect.json │ │ │ │ │ ├── ops_agent_self_metrics.json │ │ │ │ │ ├── ops_agent_self_metrics_expect.json │ │ │ │ │ ├── prometheus.json │ │ │ │ │ ├── prometheus_empty_buckets.json │ │ │ │ │ ├── prometheus_empty_buckets_expected.json │ │ │ │ │ ├── prometheus_expect.json │ │ │ │ │ ├── prometheus_stale.json │ │ │ │ │ ├── prometheus_stale_expect.json │ │ │ │ │ ├── prometheus_wal_expect.json │ │ │ │ │ ├── summary.json │ │ │ │ │ ├── summary_expect.json │ │ │ │ │ ├── summary_gmp_expect.json │ │ │ │ │ ├── untyped_gauge.json │ │ │ │ │ ├── untyped_gauge_expect.json │ │ │ │ │ ├── untyped_gauge_gmp_expect.json │ │ │ │ │ ├── with_resource_filter.json │ │ │ │ │ ├── with_resource_filter_expect.json │ │ │ │ │ ├── workload_metrics.json │ │ │ │ │ └── workload_metrics_expect.json │ │ │ │ └── traces │ │ │ │ │ ├── traces_basic.json │ │ │ │ │ ├── traces_basic_expected.json │ │ │ │ │ └── traces_user_agent_expected.json │ │ │ └── gmp_config.yaml │ │ ├── traces_integration_test.go │ │ └── traces_test.go │ ├── integrationtests.md │ ├── internal │ │ ├── datapointstorage │ │ │ ├── benchmark_test.go │ │ │ ├── datapointcache.go │ │ │ └── datapointcache_test.go │ │ ├── logsutil │ │ │ └── logsutil.go │ │ └── normalization │ │ │ ├── benchmark_test.go │ │ │ ├── disabled_normalizer.go │ │ │ ├── standard_normalizer.go │ │ │ └── types.go │ ├── logs.go │ ├── logs_test.go │ ├── metrics.go │ ├── metrics_test.go │ ├── monitoredresource.go │ ├── monitoredresource_test.go │ ├── spandata.go │ ├── spandata_test.go │ ├── spansnapshot.go │ ├── traces.go │ ├── traces_test.go │ └── version.go ├── metric │ ├── README.md │ ├── cloudmonitoring.go │ ├── cloudmonitoring_test.go │ ├── constants.go │ ├── error.go │ ├── example_test.go │ ├── go.mod │ ├── go.sum │ ├── metric.go │ ├── metric_test.go │ ├── option.go │ └── version.go └── trace │ ├── README.md │ ├── cloudtrace.go │ ├── cloudtrace_test.go │ ├── go.mod │ ├── go.sum │ ├── trace.go │ ├── trace_proto.go │ ├── trace_proto_test.go │ └── version.go ├── extension └── googleclientauthextension │ ├── README.md │ ├── config.go │ ├── config_test.go │ ├── doc.go │ ├── factory.go │ ├── factory_test.go │ ├── go.mod │ ├── go.sum │ ├── grpc.go │ ├── grpc_test.go │ ├── http.go │ ├── http_test.go │ └── testdata │ ├── fake_creds.json │ ├── fake_creds_no_project.json │ └── fake_isa_creds.json ├── get_main_pkgs.sh ├── go.mod ├── go.sum ├── golangci.yml ├── internal ├── buildscripts │ └── update-dep ├── cloudmock │ ├── go.mod │ ├── go.sum │ ├── logs.go │ ├── metrics.go │ └── traces.go └── resourcemapping │ ├── go.mod │ ├── go.sum │ └── resourcemapping.go ├── propagator ├── README.md ├── go.mod ├── go.sum ├── propagator.go └── propagator_test.go ├── renovate.json ├── tools ├── go.mod ├── go.sum ├── release.go └── tools.go └── verify_examples.sh /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Global owners 16 | * @GoogleCloudPlatform/opentelemetry-ops 17 | -------------------------------------------------------------------------------- /.github/header-checker-lint.yml: -------------------------------------------------------------------------------- 1 | allowedCopyrightHolders: 2 | - Google LLC 3 | - OpenTelemetry Authors 4 | allowedLicenses: 5 | - Apache-2.0 6 | sourceFileExtensions: 7 | - go 8 | - sh 9 | -------------------------------------------------------------------------------- /.github/trusted-contribution.yml: -------------------------------------------------------------------------------- 1 | # Config reference: 2 | # https://github.com/googleapis/repo-automation-bots/tree/main/packages/trusted-contribution 3 | 4 | trustedContributors: 5 | - renovate-bot 6 | annotations: 7 | # Automatically run Cloud Build tests 8 | - type: comment 9 | text: /gcbrun 10 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | name: "CodeQL Analysis" 2 | permissions: read-all 3 | on: 4 | workflow_dispatch: 5 | schedule: 6 | # ┌───────────── minute (0 - 59) 7 | # │ ┌───────────── hour (0 - 23) 8 | # │ │ ┌───────────── day of the month (1 - 31) 9 | # │ │ │ ┌───────────── month (1 - 12 or JAN-DEC) 10 | # │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT) 11 | # │ │ │ │ │ 12 | # │ │ │ │ │ 13 | # │ │ │ │ │ 14 | # * * * * * 15 | - cron: '30 1 * * *' 16 | push: 17 | branches: [ main ] 18 | pull_request: 19 | 20 | jobs: 21 | CodeQL-Build: 22 | runs-on: ubuntu-latest 23 | 24 | steps: 25 | - name: Checkout repository 26 | uses: actions/checkout@v4 27 | 28 | # Initializes the CodeQL tools for scanning. 29 | - name: Initialize CodeQL 30 | uses: github/codeql-action/init@v3 31 | with: 32 | languages: go 33 | 34 | - name: Autobuild 35 | uses: github/codeql-action/autobuild@v3 36 | 37 | - name: Perform CodeQL Analysis 38 | uses: github/codeql-action/analyze@v3 39 | 40 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | Thumbs.db 3 | 4 | .combined-go.sum 5 | .tools/ 6 | .idea/ 7 | .vscode/ 8 | *.iml 9 | *.so 10 | coverage.* 11 | 12 | /example/metric/collector/metrics 13 | /example/metric/collector/collector 14 | /example/metric/sdk/metrics 15 | /example/metric/sdk/sdk 16 | /example/metric/otlpgrpc/otlpgrpc 17 | /example/trace/otlpgrpc/otlpgrpc 18 | /example/metric/exponential_histogram/exponential_histogram 19 | /example/trace/otlphttp/otlphttp 20 | go.work 21 | go.work.sum -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Open-Telemetry Operations Exporters for Go 2 | 3 | [![Build Status][circleci-image]][circleci-url] 4 | 5 | This repository contains the source code of 2 packages of OpenTelemetry exporters to [Google Cloud Trace](https://cloud.google.com/trace) and [Google Cloud Monitoring](https://cloud.google.com/monitoring). 6 | 7 | To get started with instrumentation in Google Cloud, see [Generate traces and metrics with 8 | Go](https://cloud.google.com/stackdriver/docs/instrumentation/setup/go). 9 | 10 | To learn more about instrumentation and observability, including opinionated recommendations 11 | for Google Cloud Observability, visit [Instrumentation and 12 | observability](https://cloud.google.com/stackdriver/docs/instrumentation/overview). 13 | 14 | ## OpenTelemetry Google Cloud Trace Exporter 15 | 16 | OpenTelemetry Google Cloud Trace Exporter allow the user to send collected traces and spans to Google Cloud. 17 | 18 | See [README.md](https://github.com/GoogleCloudPlatform/opentelemetry-operations-go/blob/main/exporter/trace/README.md) for setup and usage information. 19 | 20 | ## OpenTelemetry Google Cloud Monitoring Exporter 21 | 22 | OpenTelemetry Google Cloud Monitoring Exporter allows the user to send collected metrics to Google Cloud Monitoring. 23 | 24 | See [README.md](https://github.com/GoogleCloudPlatform/opentelemetry-operations-go/blob/main/exporter/metric/README.md) for setup and usage information. 25 | 26 | [circleci-image]: https://circleci.com/gh/GoogleCloudPlatform/opentelemetry-operations-go.svg?style=shield 27 | [circleci-url]: https://circleci.com/gh/GoogleCloudPlatform/opentelemetry-operations-go 28 | -------------------------------------------------------------------------------- /RELEASING.md: -------------------------------------------------------------------------------- 1 | # Release Process 2 | 3 | ## Pre-Release 4 | 5 | ``` 6 | $ git fetch 7 | $ git checkout origin/main -b pre-release 8 | $ # ensure that version numbers in tools/release.go are what you want 9 | $ make prepare-release 10 | $ git commit -a 11 | $ git push -u origin HEAD 12 | $ # create a PR with a link to draft release notes 13 | $ # get the PR reviewed and merged 14 | ``` 15 | 16 | ## Release 17 | 18 | ``` 19 | $ # Ensure that the `origin` remote points to the main repository and NOT your fork 20 | $ git remote -v 21 | $ # do this after the pre-release PR is merged 22 | $ git fetch 23 | $ git checkout origin/main 24 | $ make release 25 | $ # make sure you don't have any stray tags lying around 26 | $ git push --tags --dry-run 27 | $ # manually inspect the dry run output to ensure correct tags will be pushed 28 | $ git push --tags 29 | ``` 30 | 31 | ***IMPORTANT***: It is critical you use the same tag that you used in the Pre-Release step! 32 | Failure to do so will leave things in a broken state. 33 | 34 | ***IMPORTANT***: [There is currently no way to remove an incorrectly tagged version of a Go module](https://github.com/golang/go/issues/34189). 35 | It is critical you make sure the version you push upstream is correct. 36 | [Failure to do so will lead to minor emergencies and tough to work around](https://github.com/open-telemetry/opentelemetry-go/issues/331). 37 | 38 | ## Post-release 39 | 40 | * Verify the examples 41 | ``` 42 | ./verify_examples.sh 43 | ``` 44 | 45 | The script copies examples into a different directory removes any `replace` declarations in `go.mod` and builds them. 46 | This ensures they build with the published release, not the local copy. 47 | 48 | * Update the examples maintained outside this repo at https://github.com/GoogleCloudPlatform/golang-samples/tree/master/opentelemetry. 49 | 50 | * Update the collector exporter 51 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | We support only the last minor version of each supported major release: bug fixes are released either as part of the next minor version or as an on-demand patch version. Independent of which version is next, all patch versions are cumulative, meaning that they represent the state of our main branch at the moment of the release. For instance, if the latest version is 0.10.0, bug fixes are released either as part of 0.11.0 or 0.10.1. 6 | 7 | Major releases are supported for 12 months after a new major version is released: https://opensource.google/documentation/policies/library-breaking-change. 8 | 9 | Security fixes are given priority and might be enough to cause a new version to be released. 10 | 11 | ## Reporting a Vulnerability 12 | 13 | In order for the vulnerability reports to reach maintainers as soon as possible, please use the `Report a vulnerability` button on the `Security` tab in the respective GitHub repository. It creates a private communication channel between the reporter and the maintainers. 14 | 15 | -------------------------------------------------------------------------------- /cloudbuild-e2e-cloud-functions-gen2.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | steps: 16 | # Vendor dependencies, and zip the code. 17 | - name: golang:1.23.8 18 | id: zip-code 19 | entrypoint: /bin/bash 20 | args: 21 | - '-c' 22 | - | 23 | apt-get update && \ 24 | apt-get install zip --assume-yes && \ 25 | cd e2e-test-server/cloud_functions/ && \ 26 | go mod vendor && \ 27 | zip -r function-source * 28 | 29 | # Run the test 30 | - name: $_TEST_RUNNER_IMAGE 31 | id: run-tests-cloudfunction 32 | dir: / 33 | env: ["PROJECT_ID=$PROJECT_ID"] 34 | args: 35 | - cloud-functions-gen2 36 | - --runtime=go123 37 | - --functionsource=/workspace/e2e-test-server/cloud_functions/function-source.zip 38 | - --entrypoint=HandleCloudFunction 39 | 40 | logsBucket: gs://opentelemetry-ops-e2e-cloud-build-logs 41 | substitutions: 42 | _TEST_RUNNER_IMAGE: us-central1-docker.pkg.dev/${PROJECT_ID}/e2e-testing/opentelemetry-operations-e2e-testing:0.20.1 43 | _TEST_SERVER_IMAGE: us-central1-docker.pkg.dev/${PROJECT_ID}/e2e-testing/opentelemetry-operations-go-e2e-test-server:${SHORT_SHA} 44 | -------------------------------------------------------------------------------- /cloudbuild-e2e-cloud-run.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | steps: 16 | # Wait for the image to exist 17 | - name: "docker" 18 | id: wait-for-image 19 | entrypoint: "sh" 20 | timeout: 3m 21 | env: ["_TEST_SERVER_IMAGE=${_TEST_SERVER_IMAGE}"] 22 | args: 23 | - e2e-test-server/wait-for-image.sh 24 | 25 | # Run the test 26 | - name: $_TEST_RUNNER_IMAGE 27 | id: run-tests-cloudrun 28 | dir: / 29 | timeout: 10m 30 | env: ["PROJECT_ID=$PROJECT_ID"] 31 | args: 32 | - cloud-run 33 | - --image=$_TEST_SERVER_IMAGE 34 | 35 | logsBucket: gs://opentelemetry-ops-e2e-cloud-build-logs 36 | substitutions: 37 | _TEST_RUNNER_IMAGE: us-central1-docker.pkg.dev/${PROJECT_ID}/e2e-testing/opentelemetry-operations-e2e-testing:0.20.1 38 | _TEST_SERVER_IMAGE: us-central1-docker.pkg.dev/${PROJECT_ID}/e2e-testing/opentelemetry-operations-go-e2e-test-server:${SHORT_SHA} 39 | -------------------------------------------------------------------------------- /cloudbuild-e2e-gae-standard.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2024 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | steps: 16 | # Vendor dependencies, and zip the code. 17 | - name: golang:1.23.8 18 | id: zip-code 19 | entrypoint: /bin/bash 20 | args: 21 | - '-c' 22 | - | 23 | apt-get update && \ 24 | apt-get install zip --assume-yes && \ 25 | cd e2e-test-server/ && \ 26 | go mod vendor && \ 27 | zip -r appsource * 28 | 29 | # Run the test 30 | - name: $_TEST_RUNNER_IMAGE 31 | id: run-tests-gae-standard 32 | dir: / 33 | env: ["PROJECT_ID=$PROJECT_ID"] 34 | args: 35 | - gae-standard 36 | - --runtime=go123 37 | - --appsource=/workspace/e2e-test-server/appsource.zip 38 | logsBucket: gs://opentelemetry-ops-e2e-cloud-build-logs 39 | substitutions: 40 | _TEST_RUNNER_IMAGE: us-central1-docker.pkg.dev/${PROJECT_ID}/e2e-testing/opentelemetry-operations-e2e-testing:0.20.1 41 | _TEST_SERVER_IMAGE: us-central1-docker.pkg.dev/${PROJECT_ID}/e2e-testing/opentelemetry-operations-go-e2e-test-server:${SHORT_SHA} 42 | -------------------------------------------------------------------------------- /cloudbuild-e2e-gae.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | steps: 16 | # Wait for the image to exist 17 | - name: "docker" 18 | id: wait-for-image 19 | entrypoint: "sh" 20 | timeout: 3m 21 | env: ["_TEST_SERVER_IMAGE=${_TEST_SERVER_IMAGE}"] 22 | args: 23 | - e2e-test-server/wait-for-image.sh 24 | 25 | # Run the test 26 | - name: $_TEST_RUNNER_IMAGE 27 | id: run-tests-gae 28 | dir: / 29 | env: ["PROJECT_ID=$PROJECT_ID"] 30 | args: 31 | - gae 32 | - --image=$_TEST_SERVER_IMAGE 33 | - --runtime=go123 34 | 35 | logsBucket: gs://opentelemetry-ops-e2e-cloud-build-logs 36 | substitutions: 37 | _TEST_RUNNER_IMAGE: us-central1-docker.pkg.dev/${PROJECT_ID}/e2e-testing/opentelemetry-operations-e2e-testing:0.20.1 38 | _TEST_SERVER_IMAGE: us-central1-docker.pkg.dev/${PROJECT_ID}/e2e-testing/opentelemetry-operations-go-e2e-test-server:${SHORT_SHA} 39 | -------------------------------------------------------------------------------- /cloudbuild-e2e-gce.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2021 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | steps: 16 | # Wait for the image to exist 17 | - name: "docker" 18 | id: wait-for-image 19 | entrypoint: "sh" 20 | timeout: 3m 21 | env: ["_TEST_SERVER_IMAGE=${_TEST_SERVER_IMAGE}"] 22 | args: 23 | - e2e-test-server/wait-for-image.sh 24 | 25 | # Run the test 26 | - name: $_TEST_RUNNER_IMAGE 27 | id: run-tests-gce 28 | dir: / 29 | env: ["PROJECT_ID=$PROJECT_ID"] 30 | args: 31 | - gce 32 | - --image=$_TEST_SERVER_IMAGE 33 | 34 | logsBucket: gs://opentelemetry-ops-e2e-cloud-build-logs 35 | substitutions: 36 | _TEST_RUNNER_IMAGE: us-central1-docker.pkg.dev/${PROJECT_ID}/e2e-testing/opentelemetry-operations-e2e-testing:0.20.1 37 | _TEST_SERVER_IMAGE: us-central1-docker.pkg.dev/${PROJECT_ID}/e2e-testing/opentelemetry-operations-go-e2e-test-server:${SHORT_SHA} 38 | -------------------------------------------------------------------------------- /cloudbuild-e2e-gke.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2021 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | # See the License for the specific language governing permissions and 12 | # limitations under the License. 13 | 14 | steps: 15 | # Wait for the image to exist 16 | - name: "docker" 17 | id: wait-for-image 18 | entrypoint: "sh" 19 | timeout: 3m 20 | env: ["_TEST_SERVER_IMAGE=${_TEST_SERVER_IMAGE}"] 21 | args: 22 | - e2e-test-server/wait-for-image.sh 23 | 24 | # Run the test 25 | - name: $_TEST_RUNNER_IMAGE 26 | id: run-tests-gke 27 | dir: / 28 | env: ["PROJECT_ID=$PROJECT_ID"] 29 | args: 30 | - gke 31 | - --image=$_TEST_SERVER_IMAGE 32 | 33 | logsBucket: gs://opentelemetry-ops-e2e-cloud-build-logs 34 | substitutions: 35 | _TEST_RUNNER_IMAGE: us-central1-docker.pkg.dev/${PROJECT_ID}/e2e-testing/opentelemetry-operations-e2e-testing:0.20.1 36 | _TEST_SERVER_IMAGE: us-central1-docker.pkg.dev/${PROJECT_ID}/e2e-testing/opentelemetry-operations-go-e2e-test-server:${SHORT_SHA} 37 | -------------------------------------------------------------------------------- /cloudbuild-e2e-image.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2021 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | steps: 16 | - name: docker 17 | entrypoint: "sh" 18 | args: 19 | - -c 20 | - | 21 | if docker manifest inspect ${_TEST_SERVER_IMAGE} > /dev/null; then 22 | echo "Image already exists, will skip building" 23 | exit 24 | fi 25 | docker build --tag=${_TEST_SERVER_IMAGE} --file=e2e-test-server/Dockerfile . 26 | docker push ${_TEST_SERVER_IMAGE} 27 | 28 | logsBucket: gs://opentelemetry-ops-e2e-cloud-build-logs 29 | substitutions: 30 | _TEST_SERVER_IMAGE: ${_TEST_SERVER_IMAGE_NAME}:${SHORT_SHA} 31 | _TEST_SERVER_IMAGE_NAME: us-central1-docker.pkg.dev/${PROJECT_ID}/e2e-testing/opentelemetry-operations-go-e2e-test-server 32 | -------------------------------------------------------------------------------- /cloudbuild-e2e-local.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2021 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | steps: 16 | # Wait for the image to exist 17 | - name: "docker" 18 | id: wait-for-image 19 | entrypoint: "sh" 20 | timeout: 3m 21 | env: ["_TEST_SERVER_IMAGE=${_TEST_SERVER_IMAGE}"] 22 | args: 23 | - e2e-test-server/wait-for-image.sh 24 | 25 | - name: "docker" 26 | id: pull-image 27 | args: 28 | - pull 29 | - $_TEST_SERVER_IMAGE 30 | 31 | # Run the test 32 | - name: $_TEST_RUNNER_IMAGE 33 | id: run-tests-local 34 | dir: / 35 | env: ["PROJECT_ID=$PROJECT_ID"] 36 | args: 37 | - local 38 | - --image=$_TEST_SERVER_IMAGE 39 | - --network=cloudbuild 40 | 41 | logsBucket: gs://opentelemetry-ops-e2e-cloud-build-logs 42 | substitutions: 43 | _TEST_RUNNER_IMAGE: us-central1-docker.pkg.dev/${PROJECT_ID}/e2e-testing/opentelemetry-operations-e2e-testing:0.20.1 44 | _TEST_SERVER_IMAGE: us-central1-docker.pkg.dev/${PROJECT_ID}/e2e-testing/opentelemetry-operations-go-e2e-test-server:${SHORT_SHA} 45 | -------------------------------------------------------------------------------- /cloudbuild-integration-tests.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2021 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | steps: 16 | - name: golang:1.23.8 17 | env: ["SECOND_PROJECT_ID=opentelemetry-ops-e2e-2"] 18 | args: ["make", "integrationtest"] 19 | logsBucket: gs://opentelemetry-ops-e2e-cloud-build-logs 20 | -------------------------------------------------------------------------------- /detectors/gcp/README.md: -------------------------------------------------------------------------------- 1 | # GCP Resource detection library 2 | 3 | This is a library intended to be used by Upstream OpenTelemetry resource detectors. It exists within this repository to allow for integration testing of the detection functions in real GCP environments. 4 | -------------------------------------------------------------------------------- /detectors/gcp/app_engine.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package gcp 16 | 17 | import "context" 18 | 19 | const ( 20 | // See https://cloud.google.com/appengine/docs/flexible/python/migrating#modules 21 | // for the environment variables available in GAE environments. 22 | gaeServiceEnv = "GAE_SERVICE" 23 | gaeVersionEnv = "GAE_VERSION" 24 | gaeInstanceEnv = "GAE_INSTANCE" 25 | gaeEnv = "GAE_ENV" 26 | gaeStandard = "standard" 27 | ) 28 | 29 | func (d *Detector) onAppEngineStandard() bool { 30 | // See https://cloud.google.com/appengine/docs/standard/go111/runtime#environment_variables. 31 | env, found := d.os.LookupEnv(gaeEnv) 32 | return found && env == gaeStandard 33 | } 34 | 35 | func (d *Detector) onAppEngine() bool { 36 | _, found := d.os.LookupEnv(gaeServiceEnv) 37 | return found 38 | } 39 | 40 | // AppEngineServiceName returns the service name of the app engine service. 41 | func (d *Detector) AppEngineServiceName() (string, error) { 42 | if name, found := d.os.LookupEnv(gaeServiceEnv); found { 43 | return name, nil 44 | } 45 | return "", errEnvVarNotFound 46 | } 47 | 48 | // AppEngineServiceVersion returns the service version of the app engine service. 49 | func (d *Detector) AppEngineServiceVersion() (string, error) { 50 | if version, found := d.os.LookupEnv(gaeVersionEnv); found { 51 | return version, nil 52 | } 53 | return "", errEnvVarNotFound 54 | } 55 | 56 | // AppEngineServiceInstance returns the service instance of the app engine service. 57 | func (d *Detector) AppEngineServiceInstance() (string, error) { 58 | if instanceID, found := d.os.LookupEnv(gaeInstanceEnv); found { 59 | return instanceID, nil 60 | } 61 | return "", errEnvVarNotFound 62 | } 63 | 64 | // AppEngineFlexAvailabilityZoneAndRegion returns the zone and region in which this program is running. 65 | func (d *Detector) AppEngineFlexAvailabilityZoneAndRegion() (string, string, error) { 66 | // The GCE metadata server is available on App Engine Flex. 67 | return d.GCEAvailabilityZoneAndRegion() 68 | } 69 | 70 | // AppEngineStandardAvailabilityZone returns the zone the app engine service is running in. 71 | func (d *Detector) AppEngineStandardAvailabilityZone() (string, error) { 72 | return d.metadata.ZoneWithContext(context.TODO()) 73 | } 74 | 75 | // AppEngineStandardCloudRegion returns the region the app engine service is running in. 76 | func (d *Detector) AppEngineStandardCloudRegion() (string, error) { 77 | return d.FaaSCloudRegion() 78 | } 79 | -------------------------------------------------------------------------------- /detectors/gcp/bms.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package gcp 16 | 17 | const ( 18 | bmsProjectIDEnv = "BMS_PROJECT_ID" 19 | bmsRegionEnv = "BMS_REGION" 20 | bmsInstanceIDEnv = "BMS_INSTANCE_ID" 21 | ) 22 | 23 | // onBareMetalSolution checks if the code is running on a Google Cloud Bare Metal Solution (BMS) by verifying 24 | // the presence and non-empty values of BMS_PROJECT_ID, BMS_REGION, and BMS_INSTANCE_ID environment variables. 25 | // For more information on Google Cloud Bare Metal Solution, see: https://cloud.google.com/bare-metal/docs 26 | func (d *Detector) onBareMetalSolution() bool { 27 | projectID, projectIDExists := d.os.LookupEnv(bmsProjectIDEnv) 28 | region, regionExists := d.os.LookupEnv(bmsRegionEnv) 29 | instanceID, instanceIDExists := d.os.LookupEnv(bmsInstanceIDEnv) 30 | return projectIDExists && regionExists && instanceIDExists && projectID != "" && region != "" && instanceID != "" 31 | } 32 | 33 | // BareMetalSolutionInstanceID returns the instance ID from the BMS_INSTANCE_ID environment variable. 34 | func (d *Detector) BareMetalSolutionInstanceID() (string, error) { 35 | if instanceID, found := d.os.LookupEnv(bmsInstanceIDEnv); found { 36 | return instanceID, nil 37 | } 38 | return "", errEnvVarNotFound 39 | } 40 | 41 | // BareMetalSolutionCloudRegion returns the region from the BMS_REGION environment variable. 42 | func (d *Detector) BareMetalSolutionCloudRegion() (string, error) { 43 | if region, found := d.os.LookupEnv(bmsRegionEnv); found { 44 | return region, nil 45 | } 46 | return "", errEnvVarNotFound 47 | } 48 | 49 | // BareMetalSolutionProjectID returns the project ID from the BMS_PROJECT_ID environment variable. 50 | func (d *Detector) BareMetalSolutionProjectID() (string, error) { 51 | if project, found := d.os.LookupEnv(bmsProjectIDEnv); found { 52 | return project, nil 53 | } 54 | return "", errEnvVarNotFound 55 | } 56 | -------------------------------------------------------------------------------- /detectors/gcp/bms_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package gcp 16 | 17 | import ( 18 | "testing" 19 | 20 | "github.com/stretchr/testify/assert" 21 | ) 22 | 23 | func TestBareMetalSolutionInstanceID(t *testing.T) { 24 | d := NewTestDetector(&FakeMetadataTransport{}, &FakeOSProvider{ 25 | Vars: map[string]string{ 26 | bmsInstanceIDEnv: "my-host-123", 27 | }, 28 | }) 29 | instanceID, err := d.BareMetalSolutionInstanceID() 30 | assert.NoError(t, err) 31 | assert.Equal(t, "my-host-123", instanceID) 32 | } 33 | 34 | func TestBareMetalSolutionInstanceIDErr(t *testing.T) { 35 | d := NewTestDetector(&FakeMetadataTransport{}, &FakeOSProvider{ 36 | Vars: map[string]string{}, 37 | }) 38 | instanceID, err := d.BareMetalSolutionInstanceID() 39 | assert.Error(t, err) 40 | assert.Equal(t, "", instanceID) 41 | } 42 | 43 | func TestBareMetalSolutionCloudRegion(t *testing.T) { 44 | d := NewTestDetector(&FakeMetadataTransport{}, &FakeOSProvider{ 45 | Vars: map[string]string{ 46 | bmsRegionEnv: "us-central1", 47 | }, 48 | }) 49 | region, err := d.BareMetalSolutionCloudRegion() 50 | assert.NoError(t, err) 51 | assert.Equal(t, "us-central1", region) 52 | } 53 | 54 | func TestBareMetalSolutionCloudRegionErr(t *testing.T) { 55 | d := NewTestDetector(&FakeMetadataTransport{}, &FakeOSProvider{ 56 | Vars: map[string]string{}, 57 | }) 58 | region, err := d.BareMetalSolutionCloudRegion() 59 | assert.Error(t, err) 60 | assert.Equal(t, "", region) 61 | } 62 | 63 | func TestBareMetalSolutionProjectID(t *testing.T) { 64 | d := NewTestDetector(&FakeMetadataTransport{}, &FakeOSProvider{ 65 | Vars: map[string]string{ 66 | bmsProjectIDEnv: "my-test-project", 67 | }, 68 | }) 69 | projectID, err := d.BareMetalSolutionProjectID() 70 | assert.NoError(t, err) 71 | assert.Equal(t, "my-test-project", projectID) 72 | } 73 | 74 | func TestBareMetalSolutionProjectIDErr(t *testing.T) { 75 | d := NewTestDetector(&FakeMetadataTransport{}, &FakeOSProvider{ 76 | Vars: map[string]string{}, 77 | }) 78 | projectID, err := d.BareMetalSolutionProjectID() 79 | assert.Error(t, err) 80 | assert.Equal(t, "", projectID) 81 | } 82 | -------------------------------------------------------------------------------- /detectors/gcp/detector.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package gcp 16 | 17 | import ( 18 | "context" 19 | "errors" 20 | "os" 21 | "strings" 22 | 23 | "cloud.google.com/go/compute/metadata" 24 | ) 25 | 26 | var errEnvVarNotFound = errors.New("environment variable not found") 27 | 28 | // NewDetector returns a *Detector which can get detect the platform, 29 | // and fetch attributes of the platform on which it is running. 30 | func NewDetector() *Detector { 31 | return &Detector{metadata: metadata.NewClient(nil), os: realOSProvider{}} 32 | } 33 | 34 | type Platform int64 35 | 36 | const ( 37 | UnknownPlatform Platform = iota 38 | GKE 39 | GCE 40 | CloudRun 41 | CloudRunJob 42 | CloudFunctions 43 | AppEngineStandard 44 | AppEngineFlex 45 | BareMetalSolution 46 | ) 47 | 48 | // CloudPlatform returns the platform on which this program is running. 49 | func (d *Detector) CloudPlatform() Platform { 50 | switch { 51 | case d.onBareMetalSolution(): 52 | return BareMetalSolution 53 | case d.onGKE(): 54 | return GKE 55 | case d.onCloudFunctions(): 56 | return CloudFunctions 57 | case d.onCloudRun(): 58 | return CloudRun 59 | case d.onCloudRunJob(): 60 | return CloudRunJob 61 | case d.onAppEngineStandard(): 62 | return AppEngineStandard 63 | case d.onAppEngine(): 64 | return AppEngineFlex 65 | case d.onGCE(): 66 | return GCE 67 | } 68 | return UnknownPlatform 69 | } 70 | 71 | // ProjectID returns the ID of the project in which this program is running. 72 | func (d *Detector) ProjectID() (string, error) { 73 | // N.B. d.metadata.ProjectIDWithContext(context.TODO()) is cached globally, so if we use it here it's untestable. 74 | s, err := d.metadata.GetWithContext(context.TODO(), "project/project-id") 75 | return strings.TrimSpace(s), err 76 | } 77 | 78 | // instanceID returns the ID of the project in which this program is running. 79 | func (d *Detector) instanceID() (string, error) { 80 | // N.B. d.metadata.InstanceIDWithContext(context.TODO()) is cached globally, so if we use it here it's untestable. 81 | s, err := d.metadata.GetWithContext(context.TODO(), "instance/id") 82 | return strings.TrimSpace(s), err 83 | } 84 | 85 | // Detector collects resource information for all GCP platforms. 86 | type Detector struct { 87 | metadata *metadata.Client 88 | os osProvider 89 | } 90 | 91 | // osProvider contains the subset of the os package functions used by. 92 | type osProvider interface { 93 | LookupEnv(string) (string, bool) 94 | } 95 | 96 | // realOSProvider uses the os package to lookup env vars. 97 | type realOSProvider struct{} 98 | 99 | func (realOSProvider) LookupEnv(env string) (string, bool) { 100 | return os.LookupEnv(env) 101 | } 102 | -------------------------------------------------------------------------------- /detectors/gcp/gke.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package gcp 16 | 17 | import ( 18 | "context" 19 | "fmt" 20 | "strings" 21 | ) 22 | 23 | const ( 24 | // If the kubernetes.default.svc service exists in the cluster, 25 | // then the KUBERNETES_SERVICE_HOST env var will be populated. 26 | // Use this as an indication that we are running on kubernetes. 27 | k8sServiceHostEnv = "KUBERNETES_SERVICE_HOST" 28 | // See the available GKE metadata: 29 | // https://cloud.google.com/kubernetes-engine/docs/concepts/workload-identity#instance_metadata 30 | clusterNameMetadataAttr = "cluster-name" 31 | clusterLocationMetadataAttr = "cluster-location" 32 | ) 33 | 34 | func (d *Detector) onGKE() bool { 35 | // Check if we are on k8s first 36 | _, found := d.os.LookupEnv(k8sServiceHostEnv) 37 | if !found { 38 | return false 39 | } 40 | // If we are on k8s, make sure that we are actually on GKE, and not a 41 | // different managed k8s platform. 42 | _, err := d.metadata.InstanceAttributeValueWithContext(context.TODO(), clusterLocationMetadataAttr) 43 | return err == nil 44 | } 45 | 46 | // GKEHostID returns the instance ID of the instance on which this program is running. 47 | func (d *Detector) GKEHostID() (string, error) { 48 | return d.GCEHostID() 49 | } 50 | 51 | // GKEClusterName returns the name if the GKE cluster in which this program is running. 52 | func (d *Detector) GKEClusterName() (string, error) { 53 | return d.metadata.InstanceAttributeValueWithContext(context.TODO(), clusterNameMetadataAttr) 54 | } 55 | 56 | type LocationType int64 57 | 58 | const ( 59 | UndefinedLocation LocationType = iota 60 | Zone 61 | Region 62 | ) 63 | 64 | // GKEAvailabilityZoneOrRegion returns the location of the cluster and whether the cluster is zonal or regional. 65 | func (d *Detector) GKEAvailabilityZoneOrRegion() (string, LocationType, error) { 66 | clusterLocation, err := d.metadata.InstanceAttributeValueWithContext(context.TODO(), clusterLocationMetadataAttr) 67 | if err != nil { 68 | return "", UndefinedLocation, err 69 | } 70 | switch strings.Count(clusterLocation, "-") { 71 | case 1: 72 | return clusterLocation, Region, nil 73 | case 2: 74 | return clusterLocation, Zone, nil 75 | default: 76 | return "", UndefinedLocation, fmt.Errorf("unrecognized format for cluster location: %v", clusterLocation) 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /detectors/gcp/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp 2 | 3 | go 1.23.0 4 | 5 | require ( 6 | cloud.google.com/go/compute/metadata v0.7.0 7 | github.com/stretchr/testify v1.10.0 8 | ) 9 | 10 | require ( 11 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect 12 | github.com/kr/pretty v0.3.1 // indirect 13 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect 14 | github.com/rogpeppe/go-internal v1.13.1 // indirect 15 | golang.org/x/sys v0.33.0 // indirect 16 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect 17 | gopkg.in/yaml.v3 v3.0.1 // indirect 18 | ) 19 | -------------------------------------------------------------------------------- /detectors/gcp/go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go/compute/metadata v0.7.0 h1:PBWF+iiAerVNe8UCHxdOt6eHLVc3ydFeOCw78U8ytSU= 2 | cloud.google.com/go/compute/metadata v0.7.0/go.mod h1:j5MvL9PprKL39t166CoB1uVHfQMs4tFQZZcKwksXUjo= 3 | github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 4 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= 5 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 6 | github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= 7 | github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= 8 | github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 9 | github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= 10 | github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= 11 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 12 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 13 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 14 | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 15 | github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= 16 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= 17 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 18 | github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= 19 | github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= 20 | github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= 21 | github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= 22 | github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 23 | golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= 24 | golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 25 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 26 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= 27 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= 28 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 29 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 30 | -------------------------------------------------------------------------------- /doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package operations 16 | -------------------------------------------------------------------------------- /docs/code-of-conduct.md: -------------------------------------------------------------------------------- 1 | # Google Open Source Community Guidelines 2 | 3 | At Google, we recognize and celebrate the creativity and collaboration of open 4 | source contributors and the diversity of skills, experiences, cultures, and 5 | opinions they bring to the projects and communities they participate in. 6 | 7 | Every one of Google's open source projects and communities are inclusive 8 | environments, based on treating all individuals respectfully, regardless of 9 | gender identity and expression, sexual orientation, disabilities, 10 | neurodiversity, physical appearance, body size, ethnicity, nationality, race, 11 | age, religion, or similar personal characteristic. 12 | 13 | We value diverse opinions, but we value respectful behavior more. 14 | 15 | Respectful behavior includes: 16 | 17 | * Being considerate, kind, constructive, and helpful. 18 | * Not engaging in demeaning, discriminatory, harassing, hateful, sexualized, or 19 | physically threatening behavior, speech, and imagery. 20 | * Not engaging in unwanted physical contact. 21 | 22 | Some Google open source projects [may adopt][] an explicit project code of 23 | conduct, which may have additional detailed expectations for participants. Most 24 | of those projects will use our [modified Contributor Covenant][]. 25 | 26 | [may adopt]: https://opensource.google/docs/releasing/preparing/#conduct 27 | [modified Contributor Covenant]: https://opensource.google/docs/releasing/template/CODE_OF_CONDUCT/ 28 | 29 | ## Resolve peacefully 30 | 31 | We do not believe that all conflict is necessarily bad; healthy debate and 32 | disagreement often yields positive results. However, it is never okay to be 33 | disrespectful. 34 | 35 | If you see someone behaving disrespectfully, you are encouraged to address the 36 | behavior directly with those involved. Many issues can be resolved quickly and 37 | easily, and this gives people more control over the outcome of their dispute. 38 | If you are unable to resolve the matter for any reason, or if the behavior is 39 | threatening or harassing, report it. We are dedicated to providing an 40 | environment where participants feel welcome and safe. 41 | 42 | ## Reporting problems 43 | 44 | Some Google open source projects may adopt a project-specific code of conduct. 45 | In those cases, a Google employee will be identified as the Project Steward, 46 | who will receive and handle reports of code of conduct violations. In the event 47 | that a project hasn’t identified a Project Steward, you can report problems by 48 | emailing opensource@google.com. 49 | 50 | We will investigate every complaint, but you may not receive a direct response. 51 | We will use our discretion in determining when and how to follow up on reported 52 | incidents, which may range from not taking action to permanent expulsion from 53 | the project and project-sponsored spaces. We will notify the accused of the 54 | report and provide them an opportunity to discuss it before any action is 55 | taken. The identity of the reporter will be omitted from the details of the 56 | report supplied to the accused. In potentially harmful situations, such as 57 | ongoing harassment or threats to anyone's safety, we may take action without 58 | notice. 59 | 60 | *This document was adapted from the [IndieWeb Code of Conduct][] and can also 61 | be found at .* 62 | 63 | [IndieWeb Code of Conduct]: https://indieweb.org/code-of-conduct 64 | -------------------------------------------------------------------------------- /docs/contributing.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | We'd love to accept your patches and contributions to this project. There are 4 | just a few small guidelines you need to follow. 5 | 6 | ## Contributor License Agreement 7 | 8 | Contributions to this project must be accompanied by a Contributor License 9 | Agreement. You (or your employer) retain the copyright to your contribution; 10 | this simply gives us permission to use and redistribute your contributions as 11 | part of the project. Head over to to see 12 | your current agreements on file or to sign a new one. 13 | 14 | You generally only need to submit a CLA once, so if you've already submitted one 15 | (even if it was for a different project), you probably don't need to do it 16 | again. 17 | 18 | ## Code reviews 19 | 20 | All submissions, including submissions by project members, require review. We 21 | use GitHub pull requests for this purpose. Consult 22 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more 23 | information on using pull requests. 24 | 25 | ## Community Guidelines 26 | 27 | This project follows [Google's Open Source Community 28 | Guidelines](https://opensource.google/conduct/). 29 | -------------------------------------------------------------------------------- /e2e-test-server/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2021 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | FROM golang:1.23.8 as builder 16 | 17 | WORKDIR /workspace/e2e-test-server/ 18 | 19 | # In-repo dependencies 20 | COPY exporter/trace/ ../exporter/trace/ 21 | COPY internal/resourcemapping/ ../internal/resourcemapping 22 | COPY detectors/gcp/ ../detectors/gcp/ 23 | 24 | # cache deps before copying source so that source changes don't invalidate our 25 | # downloaded layer and we don't need to re-download as much. 26 | COPY e2e-test-server/go.mod e2e-test-server/go.sum ./ 27 | RUN go mod download 28 | 29 | # Copy the go source 30 | COPY e2e-test-server/app.go ./ 31 | COPY e2e-test-server/scenarios/ scenarios/ 32 | COPY e2e-test-server/endtoendserver/ endtoendserver/ 33 | 34 | # Build 35 | RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -o app app.go 36 | 37 | # Use distroless as minimal base image to package the manager binary 38 | # Refer to https://github.com/GoogleContainerTools/distroless for more details 39 | FROM gcr.io/distroless/static 40 | WORKDIR / 41 | COPY --from=builder /workspace/e2e-test-server/app ./ 42 | 43 | ENTRYPOINT ["/app"] 44 | -------------------------------------------------------------------------------- /e2e-test-server/README.md: -------------------------------------------------------------------------------- 1 | # E2E Test Server 2 | 3 | This unpublished package is for e2e testing. Build a docker image from 4 | the repository root: 5 | 6 | ```bash 7 | docker build --tag=ops-go-e2e:local --file=e2e-test-server/Dockerfile . 8 | ``` 9 | 10 | and run it with the test server (not yet published). 11 | -------------------------------------------------------------------------------- /e2e-test-server/app.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package main 16 | 17 | import ( 18 | "context" 19 | "log" 20 | "os" 21 | "os/signal" 22 | "time" 23 | 24 | "github.com/GoogleCloudPlatform/opentelemetry-operations-go/e2e-test-server/endtoendserver" 25 | ) 26 | 27 | func main() { 28 | runCtx, cancelRunning := context.WithCancel(context.Background()) 29 | 30 | // Gracefully close on SIGINT 31 | interrupted := make(chan os.Signal, 1) 32 | signal.Notify(interrupted, os.Interrupt) 33 | go func() { 34 | <-interrupted 35 | log.Println("Received interrupt signal, shutting down.") 36 | cancelRunning() 37 | }() 38 | 39 | server, err := endtoendserver.New() 40 | if err != nil { 41 | log.Fatalf("Could not initialize server: %v", err) 42 | } 43 | 44 | if err = server.Run(runCtx); err != nil { 45 | log.Printf("Unexpected error occurred: %v", err) 46 | } 47 | 48 | log.Print("Shutting down") 49 | shutdownCtx, cancelShutdown := context.WithTimeout(context.Background(), 10*time.Second) 50 | defer cancelShutdown() 51 | if err = server.Shutdown(shutdownCtx); err != nil { 52 | log.Printf("Unexpected error occurred: %v", err) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /e2e-test-server/cloud_functions/cloud_functions.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cloudfunctions 16 | 17 | import ( 18 | "context" 19 | "encoding/json" 20 | "fmt" 21 | "log" 22 | "os" 23 | 24 | "cloud.google.com/go/pubsub" 25 | // funcframework is required to make this build on cloud functions. See 26 | // https://github.com/GoogleCloudPlatform/functions-framework-go/issues/78 27 | _ "github.com/GoogleCloudPlatform/functions-framework-go/funcframework" 28 | "github.com/GoogleCloudPlatform/functions-framework-go/functions" 29 | "github.com/cloudevents/sdk-go/v2/event" 30 | 31 | "github.com/GoogleCloudPlatform/opentelemetry-operations-go/e2e-test-server/scenarios" 32 | ) 33 | 34 | var projectID string 35 | 36 | func init() { 37 | // Register a CloudEvent function with the Functions Framework 38 | functions.CloudEvent("HandleCloudFunction", handleCloudFunction) 39 | projectID = os.Getenv("PROJECT_ID") 40 | if projectID == "" { 41 | log.Fatalf("environment variable PROJECT_ID must be set") 42 | } 43 | } 44 | 45 | // PubSubMessage is the payload of a Pub/Sub event. 46 | type PubSubMessage struct { 47 | Message struct { 48 | Attributes map[string]string `json:"attributes,omitempty"` 49 | } `json:"message"` 50 | } 51 | 52 | // handleCloudFunction accepts and handles a CloudEvent object. It decodes the 53 | // pubsub message contained within the event and handles it. 54 | func handleCloudFunction(ctx context.Context, e event.Event) error { 55 | var m PubSubMessage 56 | if err := json.Unmarshal(e.Data(), &m); err != nil { 57 | return fmt.Errorf("json.Unmarshal: %w", err) 58 | } 59 | pubsubClient, err := pubsub.NewClient(context.Background(), projectID) 60 | if err != nil { 61 | return fmt.Errorf("error creating pubsub client: %v", err) 62 | } 63 | defer pubsubClient.Close() 64 | return scenarios.HandleMessage(ctx, pubsubClient, m.Message.Attributes) 65 | } 66 | -------------------------------------------------------------------------------- /e2e-test-server/endtoendserver/constants.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package endtoendserver 16 | 17 | import ( 18 | "log" 19 | "os" 20 | ) 21 | 22 | var ( 23 | subscriptionMode string 24 | projectID string 25 | requestSubscriptionName string 26 | port string 27 | ) 28 | 29 | func init() { 30 | subscriptionMode = os.Getenv("SUBSCRIPTION_MODE") 31 | if subscriptionMode == "" { 32 | log.Fatalf("environment variable SUBSCRIPTION_MODE must be set") 33 | } 34 | projectID = os.Getenv("PROJECT_ID") 35 | if projectID == "" { 36 | log.Fatalf("environment variable PROJECT_ID must be set") 37 | } 38 | requestSubscriptionName = os.Getenv("REQUEST_SUBSCRIPTION_NAME") 39 | if requestSubscriptionName == "" { 40 | log.Fatalf("environment variable REQUEST_SUBSCRIPTION_NAME must be set") 41 | } 42 | port = os.Getenv("PORT") 43 | if port == "" && subscriptionMode == "push" { 44 | log.Fatalf("environment variable PORT must be set for push subscription") 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /e2e-test-server/endtoendserver/pull_server.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package endtoendserver 16 | 17 | import ( 18 | "context" 19 | "log" 20 | 21 | "cloud.google.com/go/pubsub" 22 | 23 | "github.com/GoogleCloudPlatform/opentelemetry-operations-go/e2e-test-server/scenarios" 24 | ) 25 | 26 | // pullServer is an end-to-end test service. 27 | type pullServer struct { 28 | pubsubClient *pubsub.Client 29 | } 30 | 31 | // New instantiates a new end-to-end test service. 32 | func NewPullServer() (Server, error) { 33 | pubsubClient, err := pubsub.NewClient(context.Background(), projectID) 34 | if err != nil { 35 | return nil, err 36 | } 37 | 38 | return &pullServer{ 39 | pubsubClient: pubsubClient, 40 | }, nil 41 | } 42 | 43 | // Run the end-to-end test service. This method will block until the context is 44 | // cancel, or an unrecoverable error is encountered. 45 | func (s *pullServer) Run(ctx context.Context) error { 46 | sub := s.pubsubClient.Subscription(requestSubscriptionName) 47 | log.Printf("End-to-end test service listening on %s", sub) 48 | return sub.Receive(ctx, func(ctx context.Context, m *pubsub.Message) { s.onReceive(ctx, m) }) 49 | } 50 | 51 | // Shutdown gracefully shuts down the service, flushing and closing resources as 52 | // appropriate. 53 | func (s *pullServer) Shutdown(ctx context.Context) error { 54 | return s.pubsubClient.Close() 55 | } 56 | 57 | // onReceive executes a scenario based on the incoming message from the test runner. 58 | func (s *pullServer) onReceive(ctx context.Context, m *pubsub.Message) { 59 | defer m.Ack() 60 | if err := scenarios.HandleMessage(ctx, s.pubsubClient, m.Attributes); err != nil { 61 | log.Println(err) 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /e2e-test-server/endtoendserver/server.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package endtoendserver 16 | 17 | import ( 18 | "context" 19 | "fmt" 20 | ) 21 | 22 | // Server is an end-to-end test service. 23 | type Server interface { 24 | Run(context.Context) error 25 | Shutdown(ctx context.Context) error 26 | } 27 | 28 | // New instantiates a new end-to-end test service. 29 | func New() (Server, error) { 30 | switch subscriptionMode { 31 | case "pull": 32 | return NewPullServer() 33 | case "push": 34 | return NewPushServer() 35 | default: 36 | return nil, fmt.Errorf("server does not support subscription mode %v", subscriptionMode) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /e2e-test-server/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/GoogleCloudPlatform/opentelemetry-operations-go/e2e-test-server 2 | 3 | go 1.23.0 4 | 5 | require ( 6 | cloud.google.com/go/pubsub v1.49.0 7 | github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v1.28.0 8 | go.opentelemetry.io/contrib/detectors/gcp v1.35.0 9 | go.opentelemetry.io/otel v1.36.0 10 | go.opentelemetry.io/otel/sdk v1.36.0 11 | go.opentelemetry.io/otel/trace v1.36.0 12 | google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 13 | ) 14 | 15 | require ( 16 | cloud.google.com/go v0.120.0 // indirect 17 | cloud.google.com/go/auth v0.16.1 // indirect 18 | cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect 19 | cloud.google.com/go/compute/metadata v0.7.0 // indirect 20 | cloud.google.com/go/iam v1.5.2 // indirect 21 | cloud.google.com/go/trace v1.11.6 // indirect 22 | github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.28.0 // indirect 23 | github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.52.0 // indirect 24 | github.com/felixge/httpsnoop v1.0.4 // indirect 25 | github.com/go-logr/logr v1.4.3 // indirect 26 | github.com/go-logr/stdr v1.2.2 // indirect 27 | github.com/google/s2a-go v0.1.9 // indirect 28 | github.com/google/uuid v1.6.0 // indirect 29 | github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect 30 | github.com/googleapis/gax-go/v2 v2.14.2 // indirect 31 | go.opencensus.io v0.24.0 // indirect 32 | go.opentelemetry.io/auto/sdk v1.1.0 // indirect 33 | go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 // indirect 34 | go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect 35 | go.opentelemetry.io/otel/metric v1.36.0 // indirect 36 | golang.org/x/crypto v0.38.0 // indirect 37 | golang.org/x/net v0.40.0 // indirect 38 | golang.org/x/oauth2 v0.30.0 // indirect 39 | golang.org/x/sync v0.14.0 // indirect 40 | golang.org/x/sys v0.33.0 // indirect 41 | golang.org/x/text v0.25.0 // indirect 42 | golang.org/x/time v0.11.0 // indirect 43 | google.golang.org/api v0.234.0 // indirect 44 | google.golang.org/genproto v0.0.0-20250505200425-f936aa4a68b2 // indirect 45 | google.golang.org/genproto/googleapis/api v0.0.0-20250505200425-f936aa4a68b2 // indirect 46 | google.golang.org/grpc v1.72.2 // indirect 47 | google.golang.org/protobuf v1.36.6 // indirect 48 | ) 49 | 50 | replace github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace => ../exporter/trace 51 | 52 | replace github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping => ../internal/resourcemapping 53 | 54 | replace github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp => ../detectors/gcp 55 | 56 | replace github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock => ../internal/cloudmock 57 | 58 | retract v1.0.0-RC1 59 | -------------------------------------------------------------------------------- /e2e-test-server/scenarios/constants.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package scenarios 16 | 17 | import ( 18 | "log" 19 | "os" 20 | "time" 21 | ) 22 | 23 | const ( 24 | instrumentingModuleName = "opentelemetry-ops-e2e-test-server" 25 | scenarioKey = "scenario" 26 | testIDKey = "test_id" 27 | statusCodeKey = "status_code" 28 | traceIDKey = "trace_id" 29 | 30 | // This is set small to reduce the latency in sending traces so that the tests finish faster. 31 | traceBatchTimeout = 100 * time.Millisecond 32 | ) 33 | 34 | var ( 35 | projectID string 36 | responseTopicName string 37 | ) 38 | 39 | func init() { 40 | projectID = os.Getenv("PROJECT_ID") 41 | if projectID == "" { 42 | log.Fatalf("environment variable PROJECT_ID must be set") 43 | } 44 | responseTopicName = os.Getenv("RESPONSE_TOPIC_NAME") 45 | if responseTopicName == "" { 46 | log.Fatalf("environment variable RESPONSE_TOPIC_NAME must be set") 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /e2e-test-server/wait-for-image.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright 2021 Google LLC 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | while true; do 18 | if docker manifest inspect ${_TEST_SERVER_IMAGE} > /dev/null; then 19 | echo "Image is available, continuing onto test" 20 | break 21 | else 22 | echo "Image not available yet, will continue to retry" 23 | fi 24 | sleep 5 25 | done 26 | -------------------------------------------------------------------------------- /example/metric/README.md: -------------------------------------------------------------------------------- 1 | # Google Cloud Monitoring exporter example 2 | 3 | This example shows how to use [`go.opentelemetry.io/otel`](https://pkg.go.dev/go.opentelemetry.io/otel/) to instrument a simple Go application with metrics and export the metrics to [Google Cloud Monitoring](https://cloud.google.com/monitoring/) 4 | 5 | ## Setup environment 6 | 7 | Before sending metrics to Google Cloud Monitoring, confirm the Cloud Monitoring API is enabled for the project you will use to access the API as described in [this document](https://cloud.google.com/monitoring/api/enable-api). 8 | 9 | You can find your current project ID using the command: 10 | 11 | ``` 12 | $ gcloud config get-value project 13 | Your active configuration is: [example] 14 | foo-project-214354 15 | ``` 16 | 17 | In this case, the project ID is `foo-project-214354`. 18 | 19 | Next, set this project ID to the environment variable `GOOGLE_PROJECT_ID` using the following command: 20 | 21 | ``` 22 | export GOOGLE_PROJECT_ID=$(gcloud config get-value project) 23 | ``` 24 | 25 | ### Enable experimental features 26 | The `exponential_histogram` example can optionally export [exemplars](https://opentelemetry.io/docs/specs/otel/metrics/data-model/#exemplars). Enable experimental [exemplar sampling](https://github.com/open-telemetry/opentelemetry-go/blob/main/sdk/metric/internal/x/README.md#exemplars) support with : 27 | ``` 28 | export OTEL_GO_X_EXEMPLAR=true 29 | export OTEL_METRICS_EXEMPLAR_FILTER=always_on 30 | ``` 31 | 32 | ## Build and run the application 33 | 34 | Once you ensure the API is enabled, then build the example application and run the executable. There are three separate examples showcasing the following - 35 | 1. Exporting metrics via the SDK - [sdk](./sdk/) directory. 36 | 2. Exporting metrics via the OpenTelemetry Collector - [collector](./collector/). 37 | 3. Exporting histogram metrics via the SDK - [exponential_histogram](./exponential_histogram/). 38 | 39 | Change the current directory to the example you wish to run, e.g. `cd sdk` or `cd exponential_histogram`, and then run the example using following commands: 40 | 41 | ``` 42 | $ go build -o metrics 43 | $ ./metrics 44 | ... 45 | ``` 46 | 47 | To ensure you have enough data to create interesting charts for the exported metrics generated by the example, keep the application running for at least five minutes. 48 | 49 | *Note: For running the collector example, you need to have a locally running OpenTelemetry Collector, configured using the provided [sample config](./collector/sample-collector-config.yaml). Instructions for running OpenTelemetry Collector on your system can be found [here](https://opentelemetry.io/docs/collector/getting-started/#local).* 50 | 51 | ## Visualize exported metrics 52 | 53 | https://console.cloud.google.com/monitoring/dashboards?project= 54 | 55 | Once you think you have sent sufficient data, then create a dashboard. If you are learning how to use Google Cloud Monitoring, you can follow how to use charts step by step on [this document](https://cloud.google.com/monitoring/charts). 56 | 57 | When filling in the **Find resource type and metric box**, use the metric names with the prefix "custom.googleapis.com/opentelemetry/counter-a", "custom.googleapis.com/opentelemetry/observer-a" or with prefix "workload.googleapis.com/latency_" (for example "workload.googleapis.com/latency_a"). 58 | 59 | Go to the individual example sub-directories [sdk](./sdk/) or [exponential_histogram](./exponential_histogram/) for further instructions on how to `Create a dashboard` to visualize the exported metrics. 60 | -------------------------------------------------------------------------------- /example/metric/collector/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/GoogleCloudPlatform/opentelemetry-operations-go/example/metric/collector 2 | 3 | go 1.23.0 4 | 5 | require ( 6 | go.opentelemetry.io/otel v1.36.0 7 | go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.34.0 8 | go.opentelemetry.io/otel/metric v1.36.0 9 | go.opentelemetry.io/otel/sdk/metric v1.36.0 10 | ) 11 | 12 | require ( 13 | github.com/cenkalti/backoff/v4 v4.3.0 // indirect 14 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect 15 | github.com/go-logr/logr v1.4.3 // indirect 16 | github.com/go-logr/stdr v1.2.2 // indirect 17 | github.com/google/uuid v1.6.0 // indirect 18 | github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.0 // indirect 19 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect 20 | go.opentelemetry.io/auto/sdk v1.1.0 // indirect 21 | go.opentelemetry.io/otel/sdk v1.36.0 // indirect 22 | go.opentelemetry.io/otel/trace v1.36.0 // indirect 23 | go.opentelemetry.io/proto/otlp v1.5.0 // indirect 24 | golang.org/x/net v0.40.0 // indirect 25 | golang.org/x/sys v0.33.0 // indirect 26 | golang.org/x/text v0.25.0 // indirect 27 | google.golang.org/genproto/googleapis/api v0.0.0-20250505200425-f936aa4a68b2 // indirect 28 | google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect 29 | google.golang.org/grpc v1.72.2 // indirect 30 | google.golang.org/protobuf v1.36.6 // indirect 31 | ) 32 | -------------------------------------------------------------------------------- /example/metric/collector/sample-collector-config.yaml: -------------------------------------------------------------------------------- 1 | # This is a sample config file which can be used with an opentelemetry collector 2 | # This sample is configured to recieve OTLP metrics over HTTP on localhost:4318 3 | # and export the recieved metrics to a Google Cloud project. 4 | receivers: 5 | otlp: 6 | protocols: 7 | http: 8 | endpoint: "localhost:4318" 9 | 10 | processors: 11 | memory_limiter: 12 | check_interval: 1s 13 | limit_percentage: 65 14 | spike_limit_percentage: 20 15 | batch: 16 | 17 | exporters: 18 | googlecloud: 19 | retry_on_failure: 20 | enabled: false 21 | 22 | extensions: 23 | health_check: 24 | pprof: 25 | zpages: 26 | 27 | service: 28 | telemetry: 29 | metrics: 30 | address: ":8888" 31 | extensions: [health_check, pprof, zpages] 32 | pipelines: 33 | metrics: 34 | receivers: [otlp] 35 | processors: [memory_limiter, batch] 36 | exporters: [googlecloud] 37 | logs: 38 | receivers: [otlp] 39 | processors: [memory_limiter, batch] 40 | exporters: [googlecloud] 41 | -------------------------------------------------------------------------------- /example/metric/dashboards/sdk_dashboard.json: -------------------------------------------------------------------------------- 1 | { 2 | "displayName": "OpenTelemetry exporter example/metric", 3 | "gridLayout": { 4 | "columns": "1", 5 | "widgets": [ 6 | { 7 | "title": "custom/opentelemetry/counter-a", 8 | "xyChart": { 9 | "chartOptions": { 10 | "mode": "COLOR" 11 | }, 12 | "dataSets": [ 13 | { 14 | "minAlignmentPeriod": "60s", 15 | "plotType": "LINE", 16 | "timeSeriesQuery": { 17 | "timeSeriesFilter": { 18 | "aggregation": { 19 | "crossSeriesReducer": "REDUCE_SUM", 20 | "perSeriesAligner": "ALIGN_DELTA" 21 | }, 22 | "filter": "metric.type=\"workload.googleapis.com/counter-a\"", 23 | "secondaryAggregation": {} 24 | }, 25 | "unitOverride": "1" 26 | } 27 | } 28 | ], 29 | "timeshiftDuration": "0s", 30 | "yAxis": { 31 | "label": "total count", 32 | "scale": "LINEAR" 33 | } 34 | } 35 | }, 36 | { 37 | "title": "custom/opentelemetry/observer-a", 38 | "xyChart": { 39 | "chartOptions": { 40 | "mode": "COLOR" 41 | }, 42 | "dataSets": [ 43 | { 44 | "minAlignmentPeriod": "60s", 45 | "plotType": "LINE", 46 | "timeSeriesQuery": { 47 | "timeSeriesFilter": { 48 | "aggregation": { 49 | "perSeriesAligner": "ALIGN_MEAN" 50 | }, 51 | "filter": "metric.type=\"workload.googleapis.com/observer-a\"", 52 | "secondaryAggregation": {} 53 | }, 54 | "unitOverride": "1" 55 | } 56 | } 57 | ], 58 | "timeshiftDuration": "0s", 59 | "yAxis": { 60 | "label": "guage value", 61 | "scale": "LINEAR" 62 | } 63 | } 64 | } 65 | ] 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /example/metric/exponential_histogram/README.md: -------------------------------------------------------------------------------- 1 | # Google Cloud Monitoring exponential histogram example 2 | 3 | This example shows how to use [`go.opentelemetry.io/otel`](https://pkg.go.dev/go.opentelemetry.io/otel/) to instrument a simple Go application with metrics and export the metrics to [Google Cloud Monitoring](https://cloud.google.com/monitoring/) 4 | 5 | ## Example details 6 | 7 | This example simulates server latency by sampling a [Log-Normal Distribution](https://en.wikipedia.org/wiki/Log-normal_distribution) with the parameters $\mu = 3.5 , 5.5$ and $\sigma = .5$. We generate the following three example of server latency : 8 | 9 | 1. Latency with Log-Normal Distribution. 10 | 2. Latency with Shifted Mean Distribution. 11 | 3. Latency with Multimodal Distribution (mixture of 1. and 2.). 12 | 13 | We explore the resulting distributions with three types of histograms : 14 | 15 | 1. Opentelemetry Default Linear Buckets Histogram. Buckets are `0, 5, 10, 25, 50, 75, 100, 250, 500, 1000` 16 | 2. Opentelemetry Linear Buckets Histogram. Buckets are `0, 10, 20, 30, ..., 340, 350`. 17 | 3. Opentelemetry Exponential Buckets Histogram with default parameters. 18 | 19 | ## Build and run the application 20 | 21 | Go to the [example/metric/README.md](../README.md) instructions that describe how to build and run all examples. 22 | 23 | ## Sample execution 24 | 25 | ``` 26 | $ ./metrics 27 | 2024/03/21 15:38:58 Sent Latency Data (Original Distribution): #points 1000 , mean 36.64255895183214, sdv 19.670797833645373 28 | 2024/03/21 15:38:58 Sent Latency Data (Shifted Distribution): #points 1000 , mean 277.70002931783233, sdv 143.59582355437485 29 | 2024/03/21 15:38:58 Sent Latency Data (Multimodal Distribution): #points 1000 , mean 151.49111863163805, sdv 159.2187295223318 30 | ... 31 | ``` 32 | 33 | ## Create dashboard 34 | 35 | When filling in the **Find resource type and metric box**, use the metric names with the prefix "workload.googleapis.com/latency_" to observe histogram metrics (for example "workload.googleapis.com/latency_a"). 36 | 37 | If you already know how to use Cloud Monitoring and would just like to confirm the data is properly received, you can run the dashboard creation script bundled in this directory. This command requires at least the [roles/monitoring.dashboardEditor](https://cloud.google.com/monitoring/access-control#dashboard_roles_desc) permissions to create a new dashboard. 38 | 39 | ``` 40 | $ ./create_dashboard.sh 41 | ``` 42 | 43 | This script creates a dashboard titled "OpenTelemetry - Exponential Histogram example". 44 | 45 | You should be able to view histogram charts like below once you create the dashboard. 46 | 47 | 2 charts in dashboard 48 | -------------------------------------------------------------------------------- /example/metric/exponential_histogram/create_dashboard.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2024 Google LLC 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | # This dashboard is intended to show the metrics emit from the example 18 | # in the same directory. 19 | # https://cloud.google.com/monitoring/dashboards/api-dashboard 20 | gcloud monitoring dashboards create --config-from-file=--config-from-file=../dashboards/exponential_histogram_dashboard.json 21 | -------------------------------------------------------------------------------- /example/metric/exponential_histogram/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/GoogleCloudPlatform/opentelemetry-operations-go/example/metric/exponential_histogram 2 | 3 | go 1.23.0 4 | 5 | require ( 6 | github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.52.0 7 | go.opentelemetry.io/contrib/detectors/gcp v1.35.0 8 | go.opentelemetry.io/otel v1.36.0 9 | go.opentelemetry.io/otel/metric v1.36.0 10 | go.opentelemetry.io/otel/sdk v1.36.0 11 | go.opentelemetry.io/otel/sdk/metric v1.36.0 12 | gonum.org/v1/gonum v0.15.1 13 | ) 14 | 15 | require ( 16 | cloud.google.com/go/auth v0.16.1 // indirect 17 | cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect 18 | cloud.google.com/go/compute/metadata v0.7.0 // indirect 19 | cloud.google.com/go/monitoring v1.24.2 // indirect 20 | github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.28.0 // indirect 21 | github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.52.0 // indirect 22 | github.com/go-logr/logr v1.4.3 // indirect 23 | github.com/go-logr/stdr v1.2.2 // indirect 24 | github.com/google/s2a-go v0.1.9 // indirect 25 | github.com/google/uuid v1.6.0 // indirect 26 | github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect 27 | github.com/googleapis/gax-go/v2 v2.14.2 // indirect 28 | go.opentelemetry.io/auto/sdk v1.1.0 // indirect 29 | go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 // indirect 30 | go.opentelemetry.io/otel/trace v1.36.0 // indirect 31 | golang.org/x/crypto v0.38.0 // indirect 32 | golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 // indirect 33 | golang.org/x/net v0.40.0 // indirect 34 | golang.org/x/oauth2 v0.30.0 // indirect 35 | golang.org/x/sync v0.14.0 // indirect 36 | golang.org/x/sys v0.33.0 // indirect 37 | golang.org/x/text v0.25.0 // indirect 38 | golang.org/x/time v0.11.0 // indirect 39 | google.golang.org/api v0.234.0 // indirect 40 | google.golang.org/genproto v0.0.0-20250505200425-f936aa4a68b2 // indirect 41 | google.golang.org/genproto/googleapis/api v0.0.0-20250505200425-f936aa4a68b2 // indirect 42 | google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect 43 | google.golang.org/grpc v1.72.2 // indirect 44 | google.golang.org/protobuf v1.36.6 // indirect 45 | ) 46 | 47 | replace github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric => ../../../exporter/metric 48 | 49 | replace github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock => ../../../internal/cloudmock 50 | 51 | replace github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping => ../../../internal/resourcemapping 52 | 53 | replace github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp => ../../../detectors/gcp 54 | -------------------------------------------------------------------------------- /example/metric/images/exponential_histogram_charts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/opentelemetry-operations-go/6658b3aae40518709f8f7763b3e5f0881507ffc1/example/metric/images/exponential_histogram_charts.png -------------------------------------------------------------------------------- /example/metric/images/sdk_charts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/opentelemetry-operations-go/6658b3aae40518709f8f7763b3e5f0881507ffc1/example/metric/images/sdk_charts.png -------------------------------------------------------------------------------- /example/metric/otlpgrpc/README.md: -------------------------------------------------------------------------------- 1 | # OTLP Metric with Google Auth Example 2 | 3 | Run this sample to connect to an endpoint that is protected by GCP authentication. 4 | 5 | #### Prerequisites 6 | 7 | Get Google credentials on your machine: 8 | 9 | ```sh 10 | gcloud auth application-default login 11 | ``` 12 | 13 | #### Run the Sample 14 | 15 | ```sh 16 | # export necessary OTEL environment variables 17 | export PROJECT_ID= 18 | export OTEL_EXPORTER_OTLP_ENDPOINT= 19 | export OTEL_RESOURCE_ATTRIBUTES="gcp.project_id=$PROJECT_ID,service.name=otlp-sample,service.instance.id=1" 20 | export OTEL_EXPORTER_OTLP_HEADERS=X-Goog-User-Project=$PROJECT_ID 21 | 22 | # from the samples/otlpmetric repository 23 | cd example/metric/otlpgrpc && go run . 24 | ``` 25 | -------------------------------------------------------------------------------- /example/metric/otlpgrpc/example.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package main 16 | 17 | import ( 18 | "context" 19 | "errors" 20 | "log" 21 | 22 | "go.opentelemetry.io/contrib/detectors/gcp" 23 | "go.opentelemetry.io/otel/attribute" 24 | "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc" 25 | "go.opentelemetry.io/otel/metric" 26 | sdkmetric "go.opentelemetry.io/otel/sdk/metric" 27 | "go.opentelemetry.io/otel/sdk/resource" 28 | semconv "go.opentelemetry.io/otel/semconv/v1.21.0" 29 | "google.golang.org/grpc" 30 | "google.golang.org/grpc/credentials/oauth" 31 | ) 32 | 33 | func main() { 34 | ctx := context.Background() 35 | 36 | creds, err := oauth.NewApplicationDefault(ctx) 37 | if err != nil { 38 | panic(err) 39 | } 40 | 41 | res, err := resource.New( 42 | ctx, 43 | // Use the GCP resource detector to detect information about the GCP platform 44 | resource.WithDetectors(gcp.NewDetector()), 45 | // Keep the default detectors 46 | resource.WithTelemetrySDK(), 47 | // Add attributes from environment variables 48 | resource.WithFromEnv(), 49 | // Add your own custom attributes to identify your application 50 | resource.WithAttributes( 51 | semconv.ServiceNameKey.String("example-application"), 52 | ), 53 | ) 54 | if errors.Is(err, resource.ErrPartialResource) || errors.Is(err, resource.ErrSchemaURLConflict) { 55 | log.Println(err) 56 | } else if err != nil { 57 | panic(err) 58 | } 59 | 60 | // Set endpoint with OTEL_EXPORTER_OTLP_ENDPOINT or OTEL_EXPORTER_OTLP_METRICS_ENDPOINT 61 | metricExporter, err := otlpmetricgrpc.New(ctx, otlpmetricgrpc.WithDialOption(grpc.WithPerRPCCredentials(creds))) 62 | if err != nil { 63 | panic(err) 64 | } 65 | 66 | meterProvider := sdkmetric.NewMeterProvider( 67 | sdkmetric.WithResource(res), 68 | sdkmetric.WithReader(sdkmetric.NewPeriodicReader(metricExporter)), 69 | ) 70 | 71 | defer func() { 72 | if err = meterProvider.Shutdown(ctx); err != nil { 73 | log.Println(err) 74 | } 75 | }() 76 | 77 | meter := meterProvider.Meter("github.com/GoogleCloudPlatform/opentelemetry-operations-go/example/metric/otlpgrpc") 78 | 79 | // Register counter value 80 | counter, err := meter.Int64Counter("counter-a") 81 | if err != nil { 82 | log.Fatalf("Failed to create counter: %v", err) 83 | } 84 | clabels := []attribute.KeyValue{attribute.Key("key").String("value")} 85 | counter.Add(ctx, 100, metric.WithAttributes(clabels...)) 86 | } 87 | -------------------------------------------------------------------------------- /example/metric/otlpgrpc/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/GoogleCloudPlatform/opentelemetry-operations-go/example/metric/otlpgrpc 2 | 3 | go 1.23.0 4 | 5 | require ( 6 | go.opentelemetry.io/contrib/detectors/gcp v1.35.0 7 | go.opentelemetry.io/otel v1.36.0 8 | go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0 9 | go.opentelemetry.io/otel/metric v1.36.0 10 | go.opentelemetry.io/otel/sdk v1.36.0 11 | go.opentelemetry.io/otel/sdk/metric v1.36.0 12 | google.golang.org/grpc v1.72.2 13 | ) 14 | 15 | require ( 16 | cloud.google.com/go/compute/metadata v0.7.0 // indirect 17 | github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.28.0 // indirect 18 | github.com/cenkalti/backoff/v4 v4.3.0 // indirect 19 | github.com/go-logr/logr v1.4.3 // indirect 20 | github.com/go-logr/stdr v1.2.2 // indirect 21 | github.com/google/uuid v1.6.0 // indirect 22 | github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.0 // indirect 23 | go.opentelemetry.io/auto/sdk v1.1.0 // indirect 24 | go.opentelemetry.io/otel/trace v1.36.0 // indirect 25 | go.opentelemetry.io/proto/otlp v1.5.0 // indirect 26 | golang.org/x/net v0.40.0 // indirect 27 | golang.org/x/oauth2 v0.30.0 // indirect 28 | golang.org/x/sys v0.33.0 // indirect 29 | golang.org/x/text v0.25.0 // indirect 30 | google.golang.org/genproto/googleapis/api v0.0.0-20250505200425-f936aa4a68b2 // indirect 31 | google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect 32 | google.golang.org/protobuf v1.36.6 // indirect 33 | ) 34 | 35 | replace github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric => ../../../exporter/metric 36 | 37 | replace github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock => ../../../internal/cloudmock 38 | 39 | replace github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping => ../../../internal/resourcemapping 40 | 41 | replace github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp => ../../../detectors/gcp 42 | -------------------------------------------------------------------------------- /example/metric/sdk/README.md: -------------------------------------------------------------------------------- 1 | # Google Cloud Monitoring exporter example 2 | 3 | This example shows how to use [`go.opentelemetry.io/otel`](https://pkg.go.dev/go.opentelemetry.io/otel/) to instrument a simple Go application with metrics and export the metrics to [Google Cloud Monitoring](https://cloud.google.com/monitoring/) 4 | 5 | ## Build and run the application 6 | 7 | Go to the [example/metric/README.md](../README.md) instructions that describe how to build and run all examples. 8 | 9 | ## Sample execution 10 | 11 | ``` 12 | $ ./metrics 13 | 2020/06/11 21:11:15 Most recent data: counter 110, observer 13.45 14 | 2020/06/11 21:11:15 Most recent data: counter 160, observer 16.02 15 | 2020/06/11 21:11:15 Most recent data: counter 134, observer 14.33 16 | 2020/06/11 21:11:15 Most recent data: counter 125, observer 15.12 17 | ... 18 | ``` 19 | 20 | ## Create dashboard 21 | 22 | When filling in the **Find resource type and metric box**, use the metric names "custom.googleapis.com/opentelemetry/counter-a" and "custom.googleapis.com/opentelemetry/observer-a". 23 | 24 | If you already know how to use Cloud Monitoring and would just like to confirm the data is properly received, you can run the dashboard creation script bundled in this directory. This command requires at least the [roles/monitoring.dashboardEditor](https://cloud.google.com/monitoring/access-control#dashboard_roles_desc) permissions to create a new dashboard. 25 | ``` 26 | $ ./create_dashboard.sh 27 | ``` 28 | 29 | This script creates a dashboard titled "OpenTelemetry exporter example/metric". 30 | 31 | You should be able to view line charts like below once you create the dashboard. 32 | 33 | *Note: This script is configured to create dashboard which displays the metrics generated via the `sdk` example.* 34 | 35 | 2 charts in dashboard -------------------------------------------------------------------------------- /example/metric/sdk/create_dashboard.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2020 Google LLC 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | # This dashboard is intended to show the metrics emit from the example 18 | # in the same directory. 19 | # https://cloud.google.com/monitoring/dashboards/api-dashboard 20 | gcloud monitoring dashboards create --config-from-file=../dashboards/sdk_dashboard.json 21 | -------------------------------------------------------------------------------- /example/metric/sdk/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/GoogleCloudPlatform/opentelemetry-operations-go/example/metric/sdk 2 | 3 | go 1.23.0 4 | 5 | require ( 6 | github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.52.0 7 | go.opentelemetry.io/contrib/detectors/gcp v1.35.0 8 | go.opentelemetry.io/otel v1.36.0 9 | go.opentelemetry.io/otel/metric v1.36.0 10 | go.opentelemetry.io/otel/sdk v1.36.0 11 | go.opentelemetry.io/otel/sdk/metric v1.36.0 12 | ) 13 | 14 | require ( 15 | cloud.google.com/go/auth v0.16.1 // indirect 16 | cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect 17 | cloud.google.com/go/compute/metadata v0.7.0 // indirect 18 | cloud.google.com/go/monitoring v1.24.2 // indirect 19 | github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.28.0 // indirect 20 | github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.52.0 // indirect 21 | github.com/go-logr/logr v1.4.3 // indirect 22 | github.com/go-logr/stdr v1.2.2 // indirect 23 | github.com/google/s2a-go v0.1.9 // indirect 24 | github.com/google/uuid v1.6.0 // indirect 25 | github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect 26 | github.com/googleapis/gax-go/v2 v2.14.2 // indirect 27 | go.opentelemetry.io/auto/sdk v1.1.0 // indirect 28 | go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 // indirect 29 | go.opentelemetry.io/otel/trace v1.36.0 // indirect 30 | golang.org/x/crypto v0.38.0 // indirect 31 | golang.org/x/net v0.40.0 // indirect 32 | golang.org/x/oauth2 v0.30.0 // indirect 33 | golang.org/x/sync v0.14.0 // indirect 34 | golang.org/x/sys v0.33.0 // indirect 35 | golang.org/x/text v0.25.0 // indirect 36 | golang.org/x/time v0.11.0 // indirect 37 | google.golang.org/api v0.234.0 // indirect 38 | google.golang.org/genproto v0.0.0-20250505200425-f936aa4a68b2 // indirect 39 | google.golang.org/genproto/googleapis/api v0.0.0-20250505200425-f936aa4a68b2 // indirect 40 | google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect 41 | google.golang.org/grpc v1.72.2 // indirect 42 | google.golang.org/protobuf v1.36.6 // indirect 43 | ) 44 | 45 | replace github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric => ../../../exporter/metric 46 | 47 | replace github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock => ../../../internal/cloudmock 48 | 49 | replace github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping => ../../../internal/resourcemapping 50 | 51 | replace github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp => ../../../detectors/gcp 52 | -------------------------------------------------------------------------------- /example/trace/http/README.md: -------------------------------------------------------------------------------- 1 | # HTTP Client-Server example 2 | 3 | An HTTP server and client instrumented to send traces to Google Cloud Trace. 4 | 5 | In order to run this example, you'll need to 6 | 7 | 1. [Create a GCP project](https://cloud.google.com/resource-manager/docs/creating-managing-projects) 8 | 2. [Enable billing](https://cloud.google.com/billing/docs/how-to/manage-billing-account#new-billing) 9 | 3. [Enable the Cloud Trace API](https://console.cloud.google.com/apis/library/cloudtrace.googleapis.com) 10 | 4. Obtain authentication credentials 11 | * If you run the code on GCE/GKE/Cloud Run, it will receive the necessary authentication credentials automatically. 12 | * If you run in Cloud Shell or outside of GCP, you'll need to have it [authenticate as a service account](https://cloud.google.com/docs/authentication/production). 13 | 5. In one terminal, run the server 14 | ``` 15 | $ go run ./server 16 | ``` 17 | 6. In another terminal on the same host, run the client 18 | ``` 19 | $ go run ./client 20 | ``` 21 | 7. Open [Google Cloud Trace](https://console.cloud.google.com/traces/list) and examine the trace that was recorded. 22 | ![./cloudtrace.png](./cloudtrace.png) 23 | -------------------------------------------------------------------------------- /example/trace/http/cloudtrace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/opentelemetry-operations-go/6658b3aae40518709f8f7763b3e5f0881507ffc1/example/trace/http/cloudtrace.png -------------------------------------------------------------------------------- /example/trace/http/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/GoogleCloudPlatform/opentelemetry-operations-go/example/trace/http 2 | 3 | go 1.23.0 4 | 5 | require ( 6 | github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v1.28.0 7 | github.com/GoogleCloudPlatform/opentelemetry-operations-go/propagator v0.52.0 8 | go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 9 | go.opentelemetry.io/otel v1.36.0 10 | go.opentelemetry.io/otel/sdk v1.36.0 11 | go.opentelemetry.io/otel/trace v1.36.0 12 | ) 13 | 14 | require ( 15 | cloud.google.com/go/auth v0.16.1 // indirect 16 | cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect 17 | cloud.google.com/go/compute/metadata v0.7.0 // indirect 18 | cloud.google.com/go/trace v1.11.6 // indirect 19 | github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.52.0 // indirect 20 | github.com/felixge/httpsnoop v1.0.4 // indirect 21 | github.com/go-logr/logr v1.4.3 // indirect 22 | github.com/go-logr/stdr v1.2.2 // indirect 23 | github.com/google/s2a-go v0.1.9 // indirect 24 | github.com/google/uuid v1.6.0 // indirect 25 | github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect 26 | github.com/googleapis/gax-go/v2 v2.14.2 // indirect 27 | go.opentelemetry.io/auto/sdk v1.1.0 // indirect 28 | go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 // indirect 29 | go.opentelemetry.io/otel/metric v1.36.0 // indirect 30 | golang.org/x/crypto v0.38.0 // indirect 31 | golang.org/x/net v0.40.0 // indirect 32 | golang.org/x/oauth2 v0.30.0 // indirect 33 | golang.org/x/sync v0.14.0 // indirect 34 | golang.org/x/sys v0.33.0 // indirect 35 | golang.org/x/text v0.25.0 // indirect 36 | golang.org/x/time v0.11.0 // indirect 37 | google.golang.org/api v0.234.0 // indirect 38 | google.golang.org/genproto/googleapis/api v0.0.0-20250505200425-f936aa4a68b2 // indirect 39 | google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect 40 | google.golang.org/grpc v1.72.2 // indirect 41 | google.golang.org/protobuf v1.36.6 // indirect 42 | ) 43 | 44 | replace github.com/GoogleCloudPlatform/opentelemetry-operations-go => ../../.. 45 | 46 | replace github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace => ../../../exporter/trace 47 | 48 | replace github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping => ../../../internal/resourcemapping 49 | 50 | replace github.com/GoogleCloudPlatform/opentelemetry-operations-go/propagator => ../../../propagator 51 | 52 | replace github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock => ../../../internal/cloudmock 53 | 54 | retract ( 55 | v1.0.0 56 | v1.0.0-RC2 57 | v1.0.0-RC1 58 | ) 59 | -------------------------------------------------------------------------------- /example/trace/http/server/server.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenTelemetry Authors 2 | // Copyright 2021 Google LLC 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | package main 17 | 18 | import ( 19 | "context" 20 | "fmt" 21 | "io" 22 | "log" 23 | "net/http" 24 | "os" 25 | 26 | "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" 27 | "go.opentelemetry.io/otel" 28 | "go.opentelemetry.io/otel/attribute" 29 | "go.opentelemetry.io/otel/propagation" 30 | sdktrace "go.opentelemetry.io/otel/sdk/trace" 31 | "go.opentelemetry.io/otel/trace" 32 | 33 | cloudtrace "github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace" 34 | gcppropagator "github.com/GoogleCloudPlatform/opentelemetry-operations-go/propagator" 35 | ) 36 | 37 | func initTracer() (func(), error) { 38 | projectID := os.Getenv("PROJECT_ID") 39 | 40 | // Create Google Cloud Trace exporter to be able to retrieve 41 | // the collected spans. 42 | exporter, err := cloudtrace.New(cloudtrace.WithProjectID(projectID)) 43 | if err != nil { 44 | return nil, err 45 | } 46 | tp := sdktrace.NewTracerProvider( 47 | // For this example code we use sdktrace.AlwaysSample sampler to sample all traces. 48 | // In a production application, use sdktrace.ProbabilitySampler with a desired probability. 49 | sdktrace.WithSampler(sdktrace.AlwaysSample()), 50 | sdktrace.WithBatcher(exporter)) 51 | 52 | otel.SetTracerProvider(tp) 53 | return func() { 54 | err := tp.Shutdown(context.Background()) 55 | if err != nil { 56 | fmt.Printf("error shutting down trace provider: %+v", err) 57 | } 58 | }, nil 59 | } 60 | 61 | func installPropagators() { 62 | otel.SetTextMapPropagator( 63 | propagation.NewCompositeTextMapPropagator( 64 | // Putting the CloudTraceOneWayPropagator first means the TraceContext propagator 65 | // takes precedence if both the traceparent and the XCTC headers exist. 66 | gcppropagator.CloudTraceOneWayPropagator{}, 67 | propagation.TraceContext{}, 68 | propagation.Baggage{}, 69 | )) 70 | } 71 | 72 | func main() { 73 | installPropagators() 74 | shutdown, err := initTracer() 75 | if err != nil { 76 | log.Fatal(err) 77 | } 78 | defer shutdown() 79 | 80 | helloHandler := func(w http.ResponseWriter, req *http.Request) { 81 | ctx := req.Context() 82 | span := trace.SpanFromContext(ctx) 83 | span.SetAttributes(attribute.String("server", "handling this...")) 84 | 85 | _, _ = io.WriteString(w, "Hello, world!\n") 86 | } 87 | otelHandler := otelhttp.NewHandler(http.HandlerFunc(helloHandler), "Hello") 88 | http.Handle("/hello", otelHandler) 89 | err = http.ListenAndServe(":7777", nil) 90 | if err != nil { 91 | panic(err) 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /example/trace/otlpgrpc/example.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenTelemetry Authors 2 | // Copyright 2024 Google LLC 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | package main 17 | 18 | import ( 19 | "context" 20 | "flag" 21 | "fmt" 22 | "log" 23 | "time" 24 | 25 | "go.opentelemetry.io/otel" 26 | "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" 27 | sdktrace "go.opentelemetry.io/otel/sdk/trace" 28 | semconv "go.opentelemetry.io/otel/semconv/v1.24.0" 29 | "go.opentelemetry.io/otel/trace" 30 | 31 | "google.golang.org/grpc" 32 | "google.golang.org/grpc/credentials/oauth" 33 | ) 34 | 35 | var keepRunning = flag.Bool("keepRunning", false, "Set to true for generating spans at a fixed rate indefinitely. Default is false.") 36 | 37 | func initTracer() (func(), error) { 38 | ctx := context.Background() 39 | 40 | creds, err := oauth.NewApplicationDefault(ctx) 41 | if err != nil { 42 | panic(err) 43 | } 44 | 45 | // set OTEL_RESOURCE_ATTRIBUTES="gcp.project_id=" 46 | // set endpoint with OTEL_EXPORTER_OTLP_ENDPOINT=https:// 47 | // set OTEL_EXPORTER_OTLP_HEADERS="x-goog-user-project=" 48 | exporter, err := otlptracegrpc.New(ctx, otlptracegrpc.WithDialOption(grpc.WithPerRPCCredentials(creds))) 49 | if err != nil { 50 | panic(err) 51 | } 52 | 53 | tp := sdktrace.NewTracerProvider( 54 | // For this example code we use sdktrace.AlwaysSample sampler to sample all traces. 55 | // In a production application, use sdktrace.TraceIDRatioBased with a desired probability. 56 | sdktrace.WithSampler(sdktrace.AlwaysSample()), 57 | sdktrace.WithBatcher(exporter)) 58 | 59 | otel.SetTracerProvider(tp) 60 | return func() { 61 | err := tp.Shutdown(context.Background()) 62 | if err != nil { 63 | fmt.Printf("error shutting down trace provider: %+v", err) 64 | } 65 | }, nil 66 | } 67 | 68 | func generateTestSpan(ctx context.Context, tr trace.Tracer, description string) { 69 | fmt.Println("starting span...") 70 | _, span := tr.Start(ctx, description, trace.WithAttributes(semconv.PeerServiceKey.String("ExampleService"))) 71 | defer span.End() 72 | defer fmt.Println("ending span.") 73 | 74 | time.Sleep(3 * time.Second) 75 | } 76 | 77 | func generateSpansAtFixedRate(ctx context.Context, tr trace.Tracer) { 78 | fmt.Println("Generating 1 test span every 10 seconds indefinitely") 79 | ticker := time.NewTicker(10 * time.Second) 80 | defer ticker.Stop() 81 | 82 | for tick := range ticker.C { 83 | go generateTestSpan(ctx, tr, fmt.Sprintf("span-%s", tick)) 84 | } 85 | fmt.Println("Span generation complete.") 86 | } 87 | 88 | func main() { 89 | flag.Parse() 90 | shutdown, err := initTracer() 91 | if err != nil { 92 | log.Fatal(err) 93 | } 94 | defer shutdown() 95 | tr := otel.Tracer("cloudtrace/example/client") 96 | 97 | ctx := context.Background() 98 | if *keepRunning { 99 | generateSpansAtFixedRate(ctx, tr) 100 | } else { 101 | generateTestSpan(ctx, tr, "test span") 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /example/trace/otlpgrpc/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/GoogleCloudPlatform/opentelemetry-operations-go/example/trace/otlpgrpc 2 | 3 | go 1.23.0 4 | 5 | require ( 6 | go.opentelemetry.io/otel v1.36.0 7 | go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 8 | go.opentelemetry.io/otel/sdk v1.36.0 9 | go.opentelemetry.io/otel/trace v1.36.0 10 | google.golang.org/grpc v1.72.2 11 | ) 12 | 13 | require ( 14 | cloud.google.com/go/compute/metadata v0.7.0 // indirect 15 | github.com/cenkalti/backoff/v4 v4.3.0 // indirect 16 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect 17 | github.com/go-logr/logr v1.4.3 // indirect 18 | github.com/go-logr/stdr v1.2.2 // indirect 19 | github.com/google/uuid v1.6.0 // indirect 20 | github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.0 // indirect 21 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect 22 | go.opentelemetry.io/auto/sdk v1.1.0 // indirect 23 | go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 // indirect 24 | go.opentelemetry.io/otel/metric v1.36.0 // indirect 25 | go.opentelemetry.io/otel/sdk/metric v1.36.0 // indirect 26 | go.opentelemetry.io/proto/otlp v1.5.0 // indirect 27 | golang.org/x/net v0.40.0 // indirect 28 | golang.org/x/oauth2 v0.30.0 // indirect 29 | golang.org/x/sys v0.33.0 // indirect 30 | golang.org/x/text v0.25.0 // indirect 31 | google.golang.org/genproto/googleapis/api v0.0.0-20250505200425-f936aa4a68b2 // indirect 32 | google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect 33 | google.golang.org/protobuf v1.36.6 // indirect 34 | ) 35 | -------------------------------------------------------------------------------- /example/trace/otlphttp/example.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenTelemetry Authors 2 | // Copyright 2024 Google LLC 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | package main 17 | 18 | import ( 19 | "context" 20 | "fmt" 21 | "log" 22 | "os" 23 | "time" 24 | 25 | "go.opentelemetry.io/otel" 26 | "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" 27 | sdktrace "go.opentelemetry.io/otel/sdk/trace" 28 | semconv "go.opentelemetry.io/otel/semconv/v1.24.0" 29 | "go.opentelemetry.io/otel/trace" 30 | 31 | "golang.org/x/oauth2/google" 32 | ) 33 | 34 | func initTracer(projectID string) (func(), error) { 35 | ctx := context.Background() 36 | 37 | creds, err := google.FindDefaultCredentials(ctx) 38 | if err != nil { 39 | panic(err) 40 | } 41 | token, err := creds.TokenSource.Token() 42 | if err != nil { 43 | panic(err) 44 | } 45 | 46 | // set OTEL_RESOURCE_ATTRIBUTES="gcp.project_id=" 47 | // set endpoint with OTEL_EXPORTER_OTLP_ENDPOINT=https:// 48 | exporter, err := otlptracehttp.New(ctx, otlptracehttp.WithHeaders(map[string]string{ 49 | "Authorization": fmt.Sprintf("Bearer %s", token.AccessToken), 50 | "x-goog-user-project": projectID, 51 | })) 52 | if err != nil { 53 | panic(err) 54 | } 55 | 56 | tp := sdktrace.NewTracerProvider( 57 | // For this example code we use sdktrace.AlwaysSample sampler to sample all traces. 58 | // In a production application, use sdktrace.ProbabilitySampler with a desired probability. 59 | sdktrace.WithSampler(sdktrace.AlwaysSample()), 60 | sdktrace.WithBatcher(exporter)) 61 | 62 | otel.SetTracerProvider(tp) 63 | return func() { 64 | err := tp.Shutdown(context.Background()) 65 | if err != nil { 66 | fmt.Printf("error shutting down trace provider: %+v", err) 67 | } 68 | }, nil 69 | } 70 | 71 | func main() { 72 | projectID := os.Getenv("GCLOUD_PROJECT") 73 | shutdown, err := initTracer(projectID) 74 | if err != nil { 75 | log.Fatal(err) 76 | } 77 | defer shutdown() 78 | tr := otel.Tracer("cloudtrace/example/client") 79 | 80 | ctx := context.Background() 81 | fmt.Println("starting span...") 82 | _, span := tr.Start(ctx, "test span", trace.WithAttributes(semconv.PeerServiceKey.String("ExampleService"))) 83 | defer span.End() 84 | defer fmt.Println("ending span.") 85 | 86 | time.Sleep(3 * time.Second) 87 | } 88 | -------------------------------------------------------------------------------- /example/trace/otlphttp/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/GoogleCloudPlatform/opentelemetry-operations-go/example/trace/otlphttp 2 | 3 | go 1.23.0 4 | 5 | require ( 6 | go.opentelemetry.io/otel v1.36.0 7 | go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0 8 | go.opentelemetry.io/otel/sdk v1.36.0 9 | go.opentelemetry.io/otel/trace v1.36.0 10 | golang.org/x/oauth2 v0.30.0 11 | ) 12 | 13 | require ( 14 | cloud.google.com/go/compute/metadata v0.7.0 // indirect 15 | github.com/cenkalti/backoff/v4 v4.3.0 // indirect 16 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect 17 | github.com/go-logr/logr v1.4.3 // indirect 18 | github.com/go-logr/stdr v1.2.2 // indirect 19 | github.com/google/uuid v1.6.0 // indirect 20 | github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.0 // indirect 21 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect 22 | go.opentelemetry.io/auto/sdk v1.1.0 // indirect 23 | go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 // indirect 24 | go.opentelemetry.io/otel/metric v1.36.0 // indirect 25 | go.opentelemetry.io/otel/sdk/metric v1.36.0 // indirect 26 | go.opentelemetry.io/proto/otlp v1.5.0 // indirect 27 | golang.org/x/net v0.40.0 // indirect 28 | golang.org/x/sys v0.33.0 // indirect 29 | golang.org/x/text v0.25.0 // indirect 30 | google.golang.org/genproto/googleapis/api v0.0.0-20250505200425-f936aa4a68b2 // indirect 31 | google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect 32 | google.golang.org/grpc v1.72.2 // indirect 33 | google.golang.org/protobuf v1.36.6 // indirect 34 | ) 35 | -------------------------------------------------------------------------------- /exporter/collector/benchmark_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package collector 16 | 17 | import ( 18 | "testing" 19 | 20 | "github.com/stretchr/testify/assert" 21 | "go.opentelemetry.io/collector/pdata/pcommon" 22 | ) 23 | 24 | func BenchmarkAttributesToLabels(b *testing.B) { 25 | attr := pcommon.NewMap() 26 | assert.NoError(b, attr.FromRaw(map[string]interface{}{ 27 | "a": true, 28 | "b": false, 29 | "c": int64(12), 30 | "d": 12.3, 31 | "e": nil, 32 | "f": []byte{0xde, 0xad, 0xbe, 0xef}, 33 | "g": []interface{}{"x", nil, "y"}, 34 | "h": map[string]interface{}{"a": "b"}, 35 | })) 36 | b.ResetTimer() 37 | 38 | for i := 0; i < b.N; i++ { 39 | assert.Len(b, attributesToLabels(attr), 8) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /exporter/collector/googlemanagedprometheus/config.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package googlemanagedprometheus 16 | 17 | // Config provides configuration options specific to the GMP translation. 18 | // It is meant to be embedded in the googlemanagedprometheus configuration. 19 | type Config struct { 20 | // AddMetricSuffixes controls whether suffixes are added to metric names. Defaults to true. 21 | AddMetricSuffixes bool `mapstructure:"add_metric_suffixes"` 22 | // ExtraMetricsConfig configures the target_info and otel_scope_info metrics. 23 | ExtraMetricsConfig ExtraMetricsConfig `mapstructure:"extra_metrics_config"` 24 | } 25 | 26 | // ExtraMetricsConfig controls the inclusion of additional metrics. 27 | type ExtraMetricsConfig struct { 28 | // Add `target_info` metric based on the resource. On by default. 29 | EnableTargetInfo bool `mapstructure:"enable_target_info"` 30 | // Add `otel_scope_info` metric and `scope_name`/`scope_version` attributes to all other metrics. On by default. 31 | EnableScopeInfo bool `mapstructure:"enable_scope_info"` 32 | } 33 | 34 | func DefaultConfig() Config { 35 | return Config{ 36 | AddMetricSuffixes: true, 37 | ExtraMetricsConfig: ExtraMetricsConfig{ 38 | EnableTargetInfo: true, 39 | EnableScopeInfo: true, 40 | }, 41 | } 42 | } 43 | 44 | // Validate checks if the exporter configuration is valid. 45 | func (cfg *Config) Validate() error { 46 | return nil 47 | } 48 | -------------------------------------------------------------------------------- /exporter/collector/googlemanagedprometheus/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/collector/googlemanagedprometheus 2 | 3 | go 1.23.0 4 | 5 | require ( 6 | github.com/prometheus/common v0.62.0 7 | github.com/stretchr/testify v1.10.0 8 | go.opentelemetry.io/collector/featuregate v1.26.0 9 | go.opentelemetry.io/collector/pdata v1.33.0 10 | go.opentelemetry.io/collector/semconv v0.120.0 11 | google.golang.org/genproto/googleapis/api v0.0.0-20250505200425-f936aa4a68b2 12 | ) 13 | 14 | require ( 15 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect 16 | github.com/go-logr/logr v1.4.3 // indirect 17 | github.com/gogo/protobuf v1.3.2 // indirect 18 | github.com/google/go-cmp v0.7.0 // indirect 19 | github.com/hashicorp/go-version v1.7.0 // indirect 20 | github.com/json-iterator/go v1.1.12 // indirect 21 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 22 | github.com/modern-go/reflect2 v1.0.2 // indirect 23 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect 24 | github.com/prometheus/client_model v0.6.1 // indirect 25 | github.com/rogpeppe/go-internal v1.13.1 // indirect 26 | go.opentelemetry.io/otel v1.36.0 // indirect 27 | go.opentelemetry.io/otel/sdk/metric v1.36.0 // indirect 28 | go.uber.org/multierr v1.11.0 // indirect 29 | golang.org/x/net v0.40.0 // indirect 30 | golang.org/x/sys v0.33.0 // indirect 31 | golang.org/x/text v0.25.0 // indirect 32 | google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect 33 | google.golang.org/grpc v1.72.2 // indirect 34 | google.golang.org/protobuf v1.36.6 // indirect 35 | gopkg.in/yaml.v3 v3.0.1 // indirect 36 | ) 37 | 38 | replace ( 39 | github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/collector => ../../collector 40 | github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace => ../../trace 41 | github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping => ../../../internal/resourcemapping 42 | ) 43 | -------------------------------------------------------------------------------- /exporter/collector/integrationtest/diff.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package integrationtest 16 | 17 | import ( 18 | "testing" 19 | 20 | "github.com/google/go-cmp/cmp" 21 | "github.com/google/go-cmp/cmp/cmpopts" 22 | "google.golang.org/protobuf/proto" 23 | "google.golang.org/protobuf/testing/protocmp" 24 | 25 | "github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/collector/integrationtest/protos" 26 | "github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/collector/integrationtest/testcases" 27 | ) 28 | 29 | var ( 30 | cmpOptions = []cmp.Option{ 31 | protocmp.Transform(), 32 | cmpopts.EquateEmpty(), 33 | } 34 | ) 35 | 36 | // Diff uses cmp.Diff(), protocmp, and some custom options to compare two protobuf messages. 37 | func DiffMetricProtos(t testing.TB, x, y *protos.MetricExpectFixture) string { 38 | x = proto.Clone(x).(*protos.MetricExpectFixture) 39 | y = proto.Clone(y).(*protos.MetricExpectFixture) 40 | testcases.NormalizeMetricFixture(t, x) 41 | testcases.NormalizeMetricFixture(t, y) 42 | 43 | return cmp.Diff(x, y, cmpOptions...) 44 | } 45 | 46 | // Diff uses cmp.Diff(), protocmp, and some custom options to compare two protobuf messages. 47 | func DiffLogProtos(t testing.TB, x, y *protos.LogExpectFixture) string { 48 | x = proto.Clone(x).(*protos.LogExpectFixture) 49 | y = proto.Clone(y).(*protos.LogExpectFixture) 50 | testcases.NormalizeLogFixture(t, x) 51 | testcases.NormalizeLogFixture(t, y) 52 | 53 | return cmp.Diff(x, y, cmpOptions...) 54 | } 55 | 56 | // Diff uses cmp.Diff(), protocmp, and some custom options to compare two protobuf messages. 57 | func DiffTraceProtos(t testing.TB, x, y *protos.TraceExpectFixture) string { 58 | x = proto.Clone(x).(*protos.TraceExpectFixture) 59 | y = proto.Clone(y).(*protos.TraceExpectFixture) 60 | testcases.NormalizeTraceFixture(t, x) 61 | testcases.NormalizeTraceFixture(t, y) 62 | 63 | return cmp.Diff(x, y, cmpOptions...) 64 | } 65 | -------------------------------------------------------------------------------- /exporter/collector/integrationtest/factory_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package integrationtest 16 | 17 | import ( 18 | "testing" 19 | 20 | "github.com/stretchr/testify/assert" 21 | "go.opentelemetry.io/collector/component/componenttest" 22 | 23 | "github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/collector" 24 | ) 25 | 26 | func TestCreateDefaultConfig(t *testing.T) { 27 | cfg := collector.DefaultConfig() 28 | assert.NotNil(t, cfg, "failed to create default config") 29 | assert.NoError(t, componenttest.CheckConfigStruct(cfg)) 30 | } 31 | -------------------------------------------------------------------------------- /exporter/collector/integrationtest/integration_selfobs_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | //go:build integrationtest 16 | // +build integrationtest 17 | 18 | package integrationtest 19 | 20 | import ( 21 | "context" 22 | "log" 23 | "os" 24 | "testing" 25 | 26 | "github.com/google/uuid" 27 | "go.opentelemetry.io/otel" 28 | sdkmetric "go.opentelemetry.io/otel/sdk/metric" 29 | "go.opentelemetry.io/otel/sdk/resource" 30 | semconv "go.opentelemetry.io/otel/semconv/v1.24.0" 31 | 32 | mexporter "github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric" 33 | ) 34 | 35 | func TestMain(m *testing.M) { 36 | ctx := context.Background() 37 | exporter, err := mexporter.New(mexporter.WithProjectID(os.Getenv("PROJECT_ID"))) 38 | if err != nil { 39 | log.Fatalf("Failed to create self-obs exporter: %v", err) 40 | } 41 | version4Uuid, err := uuid.NewRandom() 42 | if err != nil { 43 | log.Fatalf("Failed to create uuid for resource: %v", err) 44 | } 45 | res, err := resource.New( 46 | ctx, 47 | resource.WithTelemetrySDK(), 48 | resource.WithFromEnv(), 49 | resource.WithAttributes( 50 | semconv.ServiceNameKey.String("integrationtest"), 51 | semconv.ServiceInstanceIDKey.String(version4Uuid.String()), 52 | ), 53 | ) 54 | if err != nil { 55 | log.Fatalf("Failed to create self-obs resource: %v", err) 56 | } 57 | mp := sdkmetric.NewMeterProvider( 58 | sdkmetric.WithResource(res), 59 | sdkmetric.WithReader(sdkmetric.NewPeriodicReader(exporter)), 60 | ) 61 | defer mp.Shutdown(ctx) 62 | otel.SetMeterProvider(mp) 63 | m.Run() 64 | } 65 | -------------------------------------------------------------------------------- /exporter/collector/integrationtest/protos/fixtures.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | //go:build generate 16 | // +build generate 17 | 18 | //go:generate protoc -I=. --go_opt=paths=source_relative --go_out=. fixtures.proto 19 | 20 | package protos 21 | -------------------------------------------------------------------------------- /exporter/collector/integrationtest/protos/fixtures.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | syntax = "proto3"; 16 | package fixtures; 17 | option go_package = "github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/collector/integrationtest/protos"; 18 | 19 | import "metric_service.proto"; 20 | import "logging_service.proto"; 21 | import "tracing_service.proto"; 22 | 23 | message MetricExpectFixture { 24 | repeated google.monitoring.v3.CreateTimeSeriesRequest create_time_series_requests = 1; 25 | repeated google.monitoring.v3.CreateMetricDescriptorRequest create_metric_descriptor_requests = 2; 26 | repeated google.monitoring.v3.CreateTimeSeriesRequest create_service_time_series_requests = 3; 27 | SelfObservabilityMetric self_observability_metrics = 4; 28 | string user_agent = 5; 29 | } 30 | 31 | message SelfObservabilityMetric { 32 | repeated google.monitoring.v3.CreateTimeSeriesRequest create_time_series_requests = 1; 33 | repeated google.monitoring.v3.CreateMetricDescriptorRequest create_metric_descriptor_requests = 2; 34 | } 35 | 36 | message LogExpectFixture { 37 | repeated google.logging.v2.WriteLogEntriesRequest write_log_entries_requests = 1; 38 | string user_agent = 2; 39 | SelfObservabilityMetric self_observability_metrics = 3; 40 | } 41 | 42 | message TraceExpectFixture { 43 | repeated google.tracing.v2.BatchWriteSpansRequest batch_write_spans_request = 1; 44 | string user_agent = 2; 45 | SelfObservabilityMetric self_observability_metrics = 3; 46 | } 47 | -------------------------------------------------------------------------------- /exporter/collector/integrationtest/protos/logging_service.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // This is a stub of 16 | // https://github.com/googleapis/googleapis/blob/master/google/logging/v2/logging.proto 17 | // to avoid taking full dependency on googleapis repo 18 | 19 | syntax = "proto3"; 20 | package google.logging.v2; 21 | option go_package = "cloud.google.com/go/logging/apiv2/loggingpb;logging"; 22 | 23 | message WriteLogEntriesRequest{} 24 | -------------------------------------------------------------------------------- /exporter/collector/integrationtest/protos/metric_service.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // This is a stub of 16 | // https://github.com/googleapis/googleapis/blob/master/google/monitoring/v3/metric_service.proto 17 | // to avoid taking full dependency on googleapis repo 18 | 19 | syntax = "proto3"; 20 | package google.monitoring.v3; 21 | option go_package = "cloud.google.com/go/monitoring/apiv3/v2/monitoringpb;monitoring"; 22 | 23 | message CreateTimeSeriesRequest {} 24 | message CreateMetricDescriptorRequest {} 25 | -------------------------------------------------------------------------------- /exporter/collector/integrationtest/protos/tracing_service.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // This is a stub of 16 | // https://github.com/googleapis/googleapis/blob/master/google/devtools/cloudtrace/v2/tracing.proto 17 | // to avoid taking full dependency on googleapis repo 18 | 19 | syntax = "proto3"; 20 | package google.tracing.v2; 21 | option go_package = "cloud.google.com/go/trace/apiv2/tracepb;tracing"; 22 | 23 | message BatchWriteSpansRequest {} -------------------------------------------------------------------------------- /exporter/collector/integrationtest/testcases/exporter_settings.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package testcases 16 | 17 | import ( 18 | "fmt" 19 | "runtime" 20 | "strings" 21 | 22 | "go.opentelemetry.io/collector/component" 23 | "go.opentelemetry.io/collector/exporter" 24 | "go.opentelemetry.io/otel/metric" 25 | "go.uber.org/zap" 26 | 27 | "github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/collector" 28 | ) 29 | 30 | func NewTestExporterSettings(logger *zap.Logger, meterProvider metric.MeterProvider) exporter.Settings { 31 | return exporter.Settings{ 32 | TelemetrySettings: component.TelemetrySettings{ 33 | Logger: logger, 34 | MeterProvider: meterProvider, 35 | }, 36 | BuildInfo: component.BuildInfo{ 37 | Description: "GoogleCloudExporter Integration Test", 38 | Version: collector.Version(), 39 | }, 40 | } 41 | } 42 | 43 | func SetTestUserAgent(cfg *collector.Config, buildInfo component.BuildInfo) { 44 | collector.SetUserAgent(cfg, buildInfo) 45 | cfg.UserAgent = UserAgentRemoveRuntimeInfo(cfg.UserAgent) 46 | } 47 | 48 | func UserAgentRemoveRuntimeInfo(userAgent string) string { 49 | runtimeInfo := fmt.Sprintf(" (%s/%s)", runtime.GOOS, runtime.GOARCH) 50 | return strings.ReplaceAll(userAgent, runtimeInfo, "") 51 | } 52 | -------------------------------------------------------------------------------- /exporter/collector/integrationtest/testcases/testcases_traces.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package testcases 16 | 17 | import "github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/collector" 18 | 19 | var TracesTestCases = []TestCase{ 20 | { 21 | Name: "Basic traces", 22 | OTLPInputFixturePath: "testdata/fixtures/traces/traces_basic.json", 23 | ExpectFixturePath: "testdata/fixtures/traces/traces_basic_expected.json", 24 | }, 25 | { 26 | Name: "Custom User Agent", 27 | OTLPInputFixturePath: "testdata/fixtures/traces/traces_basic.json", 28 | ExpectFixturePath: "testdata/fixtures/traces/traces_user_agent_expected.json", 29 | ConfigureCollector: func(cfg *collector.Config) { 30 | cfg.UserAgent = "custom-user-agent {{version}}" 31 | }, 32 | }, 33 | } 34 | -------------------------------------------------------------------------------- /exporter/collector/integrationtest/testdata/config.yaml: -------------------------------------------------------------------------------- 1 | receivers: 2 | nop: 3 | 4 | processors: 5 | nop: 6 | 7 | exporters: 8 | googlecloud: 9 | googlecloud/customname: 10 | project: my-project 11 | user_agent: opentelemetry-collector-contrib {{version}} 12 | trace: 13 | endpoint: test-trace-endpoint 14 | use_insecure: true 15 | grpc_pool_size: 1 16 | metric: 17 | endpoint: test-metric-endpoint 18 | use_insecure: true 19 | prefix: prefix 20 | skip_create_descriptor: true 21 | grpc_pool_size: 1 22 | log: 23 | default_log_name: foo-log 24 | grpc_pool_size: 1 25 | 26 | service: 27 | pipelines: 28 | traces: 29 | receivers: [nop] 30 | processors: [nop] 31 | exporters: [googlecloud] 32 | metrics: 33 | receivers: [nop] 34 | processors: [nop] 35 | exporters: [googlecloud] 36 | 37 | -------------------------------------------------------------------------------- /exporter/collector/integrationtest/testdata/fixtures/logs/logs_apache_error_scope.json: -------------------------------------------------------------------------------- 1 | { 2 | "resourceLogs": [ 3 | { 4 | "resource": { 5 | "attributes": [ 6 | { 7 | "key": "cloud.platform", 8 | "value": { 9 | "stringValue": "gcp_compute_engine" 10 | } 11 | } 12 | ] 13 | }, 14 | "scopeLogs": [ 15 | { 16 | "scope": { 17 | "name": "scopeNameFoo", 18 | "version": "9000" 19 | }, 20 | "logRecords": [ 21 | { 22 | "timeUnixNano": "1651013315606298000", 23 | "body": { 24 | "kvlistValue": { 25 | "values": [ 26 | { 27 | "key": "time", 28 | "value": { 29 | "stringValue": "Tue Apr 26 22:48:35.606298 2022" 30 | } 31 | }, 32 | { 33 | "key": "severity", 34 | "value": { 35 | "stringValue": "notice" 36 | } 37 | }, 38 | { 39 | "key": "message", 40 | "value": { 41 | "stringValue": "[pid 769:tid 140159306111872] AH00094: Command line: '/usr/local/apache/bin/httpd'" 42 | } 43 | } 44 | ] 45 | } 46 | }, 47 | "attributes": [ 48 | { 49 | "key": "log.file.name", 50 | "value": { 51 | "stringValue": "test.log" 52 | } 53 | }, 54 | { 55 | "key": "gcp.log_name", 56 | "value": { 57 | "stringValue": "apache-error-fixture" 58 | } 59 | } 60 | ], 61 | "traceId": "", 62 | "spanId": "" 63 | } 64 | ] 65 | } 66 | ] 67 | } 68 | ] 69 | } 70 | -------------------------------------------------------------------------------- /exporter/collector/integrationtest/testdata/fixtures/logs/logs_apache_text_error.json: -------------------------------------------------------------------------------- 1 | { 2 | "resourceLogs": [ 3 | { 4 | "resource": { 5 | "attributes": [ 6 | { 7 | "key": "cloud.platform", 8 | "value": { 9 | "stringValue": "gcp_compute_engine" 10 | } 11 | }, 12 | { 13 | "key": "service.name", 14 | "value": { 15 | "stringValue": "apache_service" 16 | } 17 | }, 18 | { 19 | "key": "service.namespace", 20 | "value": { 21 | "stringValue": "" 22 | } 23 | } 24 | ] 25 | }, 26 | "scopeLogs": [ 27 | { 28 | "scope": {}, 29 | "logRecords": [ 30 | { 31 | "observedTimeUnixNano": "1650984816000000000", 32 | "body": { 33 | "stringValue": "127.0.0.1 - - [26/Apr/2022:22:53:36 +0800] \"GET / HTTP/1.1\" 200 1247" 34 | }, 35 | "severity_number": 17, 36 | "attributes": [ 37 | { 38 | "key": "gcp.log_name", 39 | "value": { 40 | "stringValue": "my-log-name-foo" 41 | } 42 | } 43 | ], 44 | "traceId": "", 45 | "spanId": "" 46 | }, 47 | { 48 | "observedTimeUnixNano": "1650984816000000000", 49 | "body": { 50 | "stringValue": "127.0.0.1 - - [26/Apr/2022:22:53:36 +0800] \"GET / HTTP/1.1\" 200 1247" 51 | }, 52 | "severity_text": "ERROR", 53 | "attributes": [ 54 | { 55 | "key": "gcp.log_name", 56 | "value": { 57 | "stringValue": "my-log-name-foo" 58 | } 59 | } 60 | ], 61 | "traceId": "", 62 | "spanId": "" 63 | } 64 | ] 65 | } 66 | ] 67 | } 68 | ] 69 | } 70 | -------------------------------------------------------------------------------- /exporter/collector/integrationtest/testdata/fixtures/metrics/boolean_gauge.json: -------------------------------------------------------------------------------- 1 | { 2 | "resourceMetrics": [ 3 | { 4 | "resource": { 5 | "attributes": [ 6 | { 7 | "key": "cloud.availability_zone", 8 | "value": { 9 | "stringValue": "us-central1-c" 10 | } 11 | }, 12 | { 13 | "key": "service.name", 14 | "value": { 15 | "stringValue": "demo" 16 | } 17 | }, 18 | { 19 | "key": "service.instance.id", 20 | "value": { 21 | "stringValue": "10.92.5.2:15692" 22 | } 23 | } 24 | ] 25 | }, 26 | "scopeMetrics": [ 27 | { 28 | "scope": {}, 29 | "metrics": [ 30 | { 31 | "name": "observer.boolean.collector", 32 | "unit": "{gcp.BOOL}", 33 | "gauge": { 34 | "dataPoints": [ 35 | { 36 | "attributes": [ 37 | { 38 | "key": "key", 39 | "value": { 40 | "stringValue": "value-1" 41 | } 42 | } 43 | ], 44 | "startTimeUnixNano": "11651379494838206464", 45 | "timeUnixNano": "1687377293673694987", 46 | "asInt": "0" 47 | }, 48 | { 49 | "attributes": [ 50 | { 51 | "key": "key", 52 | "value": { 53 | "stringValue": "value-2" 54 | } 55 | } 56 | ], 57 | "startTimeUnixNano": "1688083417576000000", 58 | "timeUnixNano": "1688083820000000000", 59 | "asInt": "393" 60 | }, 61 | { 62 | "attributes": [ 63 | { 64 | "key": "key", 65 | "value": { 66 | "stringValue": "value-3" 67 | } 68 | } 69 | ], 70 | "startTimeUnixNano": "1688083940000000000", 71 | "timeUnixNano": "1688084000000000000", 72 | "asInt": "-272" 73 | } 74 | ] 75 | } 76 | } 77 | ] 78 | } 79 | ] 80 | } 81 | ] 82 | } -------------------------------------------------------------------------------- /exporter/collector/integrationtest/testdata/fixtures/metrics/counter.json: -------------------------------------------------------------------------------- 1 | { 2 | "resourceMetrics": [ 3 | { 4 | "resource": { 5 | "attributes": [ 6 | { 7 | "key": "cloud.availability_zone", 8 | "value": { 9 | "stringValue": "us-central1-c" 10 | } 11 | }, 12 | { 13 | "key": "service.name", 14 | "value": { 15 | "stringValue": "demo" 16 | } 17 | }, 18 | { 19 | "key": "service.instance.id", 20 | "value": { 21 | "stringValue": "10.92.5.2:15692" 22 | } 23 | } 24 | ] 25 | }, 26 | "scopeMetrics": [ 27 | { 28 | "scope": {}, 29 | "metrics": [ 30 | { 31 | "name": "test.counter", 32 | "description": "This is a test counter", 33 | "unit": "s", 34 | "sum": { 35 | "dataPoints": [ 36 | { 37 | "attributes": [ 38 | { 39 | "key": "foo.bar", 40 | "value": { 41 | "stringValue": "baz" 42 | } 43 | } 44 | ], 45 | "startTimeUnixNano": "1634322229906722370", 46 | "timeUnixNano": "1634322234906722370", 47 | "asInt": "253" 48 | } 49 | ], 50 | "aggregationTemporality": "AGGREGATION_TEMPORALITY_CUMULATIVE", 51 | "isMonotonic": true 52 | } 53 | } 54 | ] 55 | } 56 | ] 57 | } 58 | ] 59 | } 60 | -------------------------------------------------------------------------------- /exporter/collector/integrationtest/testdata/fixtures/metrics/create_service_timeseries.json: -------------------------------------------------------------------------------- 1 | { 2 | "resourceMetrics": [ 3 | { 4 | "resource": { 5 | "attributes": [ 6 | { 7 | "key": "cloud.platform", 8 | "value": { 9 | "stringValue": "gcp_kubernetes_engine" 10 | } 11 | }, 12 | { 13 | "key": "k8s.node.name", 14 | "value": { 15 | "stringValue": "gke-rabbitmq-test-dev-default-pool-4ffbde79-k6w0" 16 | } 17 | }, 18 | { 19 | "key": "cloud.availability_zone", 20 | "value": { 21 | "stringValue": "us-central1-c" 22 | } 23 | }, 24 | { 25 | "key": "k8s.cluster.name", 26 | "value": { 27 | "stringValue": "rabbitmq-test-dev" 28 | } 29 | } 30 | ] 31 | }, 32 | "scopeMetrics": [ 33 | { 34 | "scope": { 35 | "name": "foo", 36 | "version": "1.2.3" 37 | }, 38 | "metrics": [ 39 | { 40 | "name":"kubernetes.io/internal/nodes/clustermetrics/node_network_availability_transition_time", 41 | "description":"Node network unavailable condition last transition time (seconds since epoch)", 42 | "gauge":{ 43 | "dataPoints":[ 44 | { 45 | "attributes":[ 46 | { 47 | "key":"network_unavailable", 48 | "value":{ 49 | "stringValue":"False" 50 | } 51 | } 52 | ], 53 | "timeUnixNano":"1639162382976000000", 54 | "asInt":"1639069893" 55 | } 56 | ] 57 | } 58 | } 59 | ] 60 | } 61 | ] 62 | } 63 | ] 64 | } 65 | -------------------------------------------------------------------------------- /exporter/collector/integrationtest/testdata/fixtures/metrics/delta_counter.json: -------------------------------------------------------------------------------- 1 | { 2 | "resourceMetrics": [ 3 | { 4 | "resource": { 5 | "attributes": [ 6 | { 7 | "key": "cloud.availability_zone", 8 | "value": { 9 | "stringValue": "us-central1-c" 10 | } 11 | }, 12 | { 13 | "key": "service.name", 14 | "value": { 15 | "stringValue": "demo" 16 | } 17 | }, 18 | { 19 | "key": "service.instance.id", 20 | "value": { 21 | "stringValue": "10.92.5.2:15692" 22 | } 23 | } 24 | ] 25 | }, 26 | "scopeMetrics": [ 27 | { 28 | "scope": {}, 29 | "metrics": [ 30 | { 31 | "name": "delta.counter", 32 | "description": "This is a test counter with delta temporality", 33 | "unit": "s", 34 | "sum": { 35 | "dataPoints": [ 36 | { 37 | "attributes": [ 38 | { 39 | "key": "foo.bar", 40 | "value": { 41 | "stringValue": "baz" 42 | } 43 | } 44 | ], 45 | "startTimeUnixNano": "1634322229906722370", 46 | "timeUnixNano": "1634322234906722370", 47 | "asInt": "253" 48 | } 49 | ], 50 | "aggregationTemporality": "AGGREGATION_TEMPORALITY_DELTA", 51 | "isMonotonic": true 52 | } 53 | } 54 | ] 55 | } 56 | ] 57 | } 58 | ] 59 | } 60 | -------------------------------------------------------------------------------- /exporter/collector/integrationtest/testdata/fixtures/metrics/gauge.json: -------------------------------------------------------------------------------- 1 | { 2 | "resourceMetrics": [ 3 | { 4 | "resource": { 5 | "attributes": [ 6 | { 7 | "key": "cloud.availability_zone", 8 | "value": { 9 | "stringValue": "us-central1-c" 10 | } 11 | }, 12 | { 13 | "key": "service.name", 14 | "value": { 15 | "stringValue": "demo" 16 | } 17 | }, 18 | { 19 | "key": "service.instance.id", 20 | "value": { 21 | "stringValue": "10.92.5.2:15692" 22 | } 23 | } 24 | ] 25 | }, 26 | "scopeMetrics": [ 27 | { 28 | "scope": {}, 29 | "metrics": [ 30 | { 31 | "name": "simple.gauge", 32 | "unit": "s", 33 | "gauge": { 34 | "dataPoints": [ 35 | { 36 | "attributes": [ 37 | { 38 | "key": "some.lemons", 39 | "value": { 40 | "stringValue": "13" 41 | } 42 | } 43 | ], 44 | "timeUnixNano": "1649443516286000000", 45 | "asDouble": 1 46 | }, 47 | { 48 | "attributes": [ 49 | { 50 | "key": "some.lemons", 51 | "value": { 52 | "stringValue": "1" 53 | } 54 | } 55 | ], 56 | "timeUnixNano": "1649443516286000000", 57 | "asDouble": 13 58 | } 59 | ] 60 | } 61 | } 62 | ] 63 | } 64 | ] 65 | } 66 | ] 67 | } -------------------------------------------------------------------------------- /exporter/collector/integrationtest/testdata/fixtures/metrics/nonmonotonic_counter.json: -------------------------------------------------------------------------------- 1 | { 2 | "resourceMetrics": [ 3 | { 4 | "resource": { 5 | "attributes": [ 6 | { 7 | "key": "cloud.availability_zone", 8 | "value": { 9 | "stringValue": "us-central1-c" 10 | } 11 | }, 12 | { 13 | "key": "service.name", 14 | "value": { 15 | "stringValue": "demo" 16 | } 17 | }, 18 | { 19 | "key": "service.instance.id", 20 | "value": { 21 | "stringValue": "10.92.5.2:15692" 22 | } 23 | } 24 | ] 25 | }, 26 | "scopeMetrics": [ 27 | { 28 | "scope": {}, 29 | "metrics": [ 30 | { 31 | "name": "system.memory.usage", 32 | "description": "Bytes of memory in use.", 33 | "unit": "By", 34 | "sum": { 35 | "dataPoints": [ 36 | { 37 | "attributes": [ 38 | { 39 | "key": "state", 40 | "value": { 41 | "stringValue": "used" 42 | } 43 | } 44 | ], 45 | "timeUnixNano": "1634877479074335121", 46 | "asInt": "6641752448" 47 | } 48 | ], 49 | "aggregationTemporality": "AGGREGATION_TEMPORALITY_CUMULATIVE" 50 | } 51 | } 52 | ] 53 | } 54 | ] 55 | } 56 | ] 57 | } 58 | -------------------------------------------------------------------------------- /exporter/collector/integrationtest/testdata/fixtures/metrics/summary.json: -------------------------------------------------------------------------------- 1 | { 2 | "resourceMetrics": [ 3 | { 4 | "resource": { 5 | "attributes": [ 6 | { 7 | "key": "cloud.availability_zone", 8 | "value": { 9 | "stringValue": "us-central1-c" 10 | } 11 | }, 12 | { 13 | "key": "service.name", 14 | "value": { 15 | "stringValue": "demo" 16 | } 17 | }, 18 | { 19 | "key": "service.instance.id", 20 | "value": { 21 | "stringValue": "10.92.5.2:15692" 22 | } 23 | } 24 | ] 25 | }, 26 | "scopeMetrics": [ 27 | { 28 | "scope": {}, 29 | "metrics": [ 30 | { 31 | "name": "test.summary", 32 | "description": "This is a test summary", 33 | "unit": "s", 34 | "summary": { 35 | "dataPoints": [ 36 | { 37 | "attributes": [ 38 | { 39 | "key": "foo.bar", 40 | "value": { 41 | "stringValue": "baz" 42 | } 43 | } 44 | ], 45 | "startTimeUnixNano": "1634322229906722370", 46 | "timeUnixNano": "1634322234906722370", 47 | "count": "10", 48 | "sum": 123.4, 49 | "quantile_values": [ 50 | { 51 | "quantile": 0.5, 52 | "value": 10.2 53 | }, 54 | { 55 | "quantile": 0.75, 56 | "value": 25.5 57 | }, 58 | { 59 | "quantile": 0.9, 60 | "value": 100.2 61 | } 62 | ] 63 | } 64 | ] 65 | } 66 | } 67 | ] 68 | } 69 | ] 70 | } 71 | ] 72 | } -------------------------------------------------------------------------------- /exporter/collector/integrationtest/testdata/fixtures/metrics/untyped_gauge.json: -------------------------------------------------------------------------------- 1 | { 2 | "resourceMetrics": [ 3 | { 4 | "resource": { 5 | "attributes": [ 6 | { 7 | "key": "cloud.availability_zone", 8 | "value": { 9 | "stringValue": "us-central1-c" 10 | } 11 | }, 12 | { 13 | "key": "service.name", 14 | "value": { 15 | "stringValue": "demo" 16 | } 17 | }, 18 | { 19 | "key": "service.instance.id", 20 | "value": { 21 | "stringValue": "10.92.5.2:15692" 22 | } 23 | } 24 | ] 25 | }, 26 | "scopeMetrics": [ 27 | { 28 | "scope": {}, 29 | "metrics": [ 30 | { 31 | "name": "fake_untyped_metric", 32 | "gauge": { 33 | "dataPoints": [ 34 | { 35 | "attributes": [ 36 | { 37 | "key": "ex_com_lemons_untyped", 38 | "value": { 39 | "stringValue": "13" 40 | } 41 | } 42 | ], 43 | "startTimeUnixNano": "1649443416286000000", 44 | "timeUnixNano": "1649443516286000000", 45 | "asDouble": 3 46 | } 47 | ] 48 | }, 49 | "metadata": [ 50 | { 51 | "key": "prometheus.type", 52 | "value": { 53 | "stringValue": "unknown" 54 | } 55 | } 56 | ] 57 | } 58 | ] 59 | } 60 | ] 61 | } 62 | ] 63 | } -------------------------------------------------------------------------------- /exporter/collector/integrationtest/testdata/fixtures/metrics/with_resource_filter.json: -------------------------------------------------------------------------------- 1 | { 2 | "resourceMetrics": [ 3 | { 4 | "resource": { 5 | "attributes": [ 6 | { 7 | "key": "service.name", 8 | "value": { 9 | "stringValue": "foo-service" 10 | } 11 | }, 12 | { 13 | "key": "service.namespace", 14 | "value": { 15 | "stringValue": "foo" 16 | } 17 | }, 18 | { 19 | "key": "service.instance.id", 20 | "value": { 21 | "stringValue": "abc123" 22 | } 23 | }, 24 | { 25 | "key": "telemetry.sdk.language", 26 | "value": { 27 | "stringValue": "java" 28 | } 29 | }, 30 | { 31 | "key": "telemetry.sdk.version", 32 | "value": { 33 | "stringValue": "1.1.1" 34 | } 35 | }, 36 | { 37 | "key": "something.uninteresting", 38 | "value": { 39 | "stringValue": "baz" 40 | } 41 | } 42 | ] 43 | }, 44 | "scopeMetrics": [ 45 | { 46 | "scope": {}, 47 | "metrics": [ 48 | { 49 | "name": "testresourcefilter", 50 | "description": "This is a test counter", 51 | "unit": "1", 52 | "sum": { 53 | "dataPoints": [ 54 | { 55 | "attributes": [ 56 | { 57 | "key": "foo", 58 | "value": { 59 | "stringValue": "bar" 60 | } 61 | } 62 | ], 63 | "startTimeUnixNano": "1634322229906722370", 64 | "timeUnixNano": "1634322234906722370", 65 | "asInt": "253" 66 | } 67 | ], 68 | "aggregationTemporality": "AGGREGATION_TEMPORALITY_CUMULATIVE", 69 | "isMonotonic": true 70 | } 71 | } 72 | ] 73 | } 74 | ] 75 | } 76 | ] 77 | } 78 | -------------------------------------------------------------------------------- /exporter/collector/integrationtest/testdata/gmp_config.yaml: -------------------------------------------------------------------------------- 1 | receivers: 2 | nop: 3 | 4 | processors: 5 | nop: 6 | 7 | exporters: 8 | googlemanagedprometheus: 9 | googlemanagedprometheus/customname: 10 | project: my-project 11 | user_agent: opentelemetry-collector-contrib {{version}} 12 | endpoint: test-metric-endpoint 13 | use_insecure: true 14 | 15 | service: 16 | pipelines: 17 | metrics: 18 | receivers: [nop] 19 | processors: [nop] 20 | exporters: [googlemanagedprometheus] 21 | -------------------------------------------------------------------------------- /exporter/collector/integrationtest/traces_integration_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | //go:build integrationtest 16 | // +build integrationtest 17 | 18 | package integrationtest 19 | 20 | import ( 21 | "context" 22 | "os" 23 | "testing" 24 | "time" 25 | 26 | "github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/collector" 27 | "github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/collector/integrationtest/testcases" 28 | "github.com/stretchr/testify/require" 29 | "go.opentelemetry.io/collector/component/componenttest" 30 | "go.opentelemetry.io/otel/metric/noop" 31 | "go.uber.org/zap" 32 | ) 33 | 34 | func createTracesExporter( 35 | ctx context.Context, 36 | t *testing.T, 37 | test *testcases.TestCase, 38 | ) *collector.TraceExporter { 39 | cfg := test.CreateTraceConfig() 40 | logger, _ := zap.NewProduction() 41 | cfg.ProjectID = os.Getenv("PROJECT_ID") 42 | 43 | set := testcases.NewTestExporterSettings(logger, noop.NewMeterProvider()) 44 | testcases.SetTestUserAgent(&cfg, set.BuildInfo) 45 | exporter, err := collector.NewGoogleCloudTracesExporter( 46 | ctx, 47 | cfg, 48 | set, 49 | collector.DefaultTimeout, 50 | ) 51 | require.NoError(t, err) 52 | err = exporter.Start(ctx, componenttest.NewNopHost()) 53 | require.NoError(t, err) 54 | t.Log("Collector traces exporter started") 55 | return exporter 56 | } 57 | 58 | func TestIntegrationTraces(t *testing.T) { 59 | ctx := context.Background() 60 | endTime := time.Now() 61 | startTime := endTime.Add(-time.Second) 62 | 63 | for _, test := range testcases.TracesTestCases { 64 | test := test 65 | 66 | t.Run(test.Name, func(t *testing.T) { 67 | test.SkipIfNeeded(t) 68 | traces := test.LoadOTLPTracesInput(t, startTime, endTime) 69 | exporter := createTracesExporter(ctx, t, &test) 70 | defer func() { require.NoError(t, exporter.Shutdown(ctx)) }() 71 | 72 | require.NoError( 73 | t, 74 | exporter.PushTraces(ctx, traces), 75 | "Failed to export metrics", 76 | ) 77 | }) 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /exporter/collector/integrationtest/traces_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package integrationtest 16 | 17 | import ( 18 | "context" 19 | "testing" 20 | "time" 21 | 22 | "github.com/stretchr/testify/require" 23 | 24 | "github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/collector/integrationtest/protos" 25 | "github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/collector/integrationtest/testcases" 26 | "github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock" 27 | ) 28 | 29 | func TestTraces(t *testing.T) { 30 | ctx := context.Background() 31 | endTime := time.Now() 32 | startTime := endTime.Add(-time.Second) 33 | 34 | for _, test := range testcases.TracesTestCases { 35 | t.Run(test.Name, func(t *testing.T) { 36 | test.SkipIfNeeded(t) 37 | 38 | traces := test.LoadOTLPTracesInput(t, startTime, endTime) 39 | testServer, err := cloudmock.NewTracesTestServer() 40 | require.NoError(t, err) 41 | go testServer.Serve() 42 | defer testServer.Shutdown() 43 | 44 | inMemoryOTelExporter, err := NewInMemoryOTelExporter() 45 | require.NoError(t, err) 46 | //nolint:errcheck 47 | defer inMemoryOTelExporter.Shutdown(ctx) 48 | testServerExporter := NewTraceTestExporter(ctx, t, testServer, test.CreateTraceConfig(), inMemoryOTelExporter.MeterProvider) 49 | 50 | err = testServerExporter.PushTraces(ctx, traces) 51 | if !test.ExpectErr { 52 | require.NoError(t, err, "Failed to export traces to local test server") 53 | } else { 54 | require.Error(t, err, "Did not see expected error") 55 | } 56 | require.NoError(t, testServerExporter.Shutdown(ctx)) 57 | 58 | expectFixture := test.LoadTraceExpectFixture( 59 | t, 60 | startTime, 61 | endTime, 62 | ) 63 | 64 | selfObsMetrics, err := inMemoryOTelExporter.Proto(ctx) 65 | require.NoError(t, err) 66 | fixture := &protos.TraceExpectFixture{ 67 | BatchWriteSpansRequest: testServer.CreateBatchWriteSpansRequests(), 68 | UserAgent: testServer.UserAgent(), 69 | SelfObservabilityMetrics: selfObsMetrics, 70 | } 71 | 72 | diff := DiffTraceProtos( 73 | t, 74 | fixture, 75 | expectFixture, 76 | ) 77 | if diff != "" { 78 | require.Fail( 79 | t, 80 | "Expected requests fixture and actual GCM requests differ", 81 | diff, 82 | ) 83 | } 84 | }) 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /exporter/collector/internal/datapointstorage/benchmark_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package datapointstorage 16 | 17 | import ( 18 | "testing" 19 | 20 | "go.opentelemetry.io/collector/pdata/pcommon" 21 | "go.opentelemetry.io/collector/pdata/pmetric" 22 | monitoredrespb "google.golang.org/genproto/googleapis/api/monitoredres" 23 | ) 24 | 25 | func BenchmarkIdentifier(b *testing.B) { 26 | metric := pmetric.NewMetric() 27 | metric.SetName("custom.googleapis.com/test.metric") 28 | attrs := pcommon.NewMap() 29 | attrs.PutStr("string", "strval") 30 | attrs.PutBool("bool", true) 31 | attrs.PutInt("int", 123) 32 | attrs.PutInt("int1", 123) 33 | attrs.PutInt("int2", 123) 34 | attrs.PutInt("int3", 123) 35 | attrs.PutInt("int4", 123) 36 | attrs.PutInt("int5", 123) 37 | monitoredResource := &monitoredrespb.MonitoredResource{ 38 | Type: "k8s_container", 39 | Labels: map[string]string{ 40 | "location": "us-central1-b", 41 | "project": "project-foo", 42 | "cluster": "cluster-foo", 43 | "pod": "pod-foo", 44 | "namespace": "namespace-foo", 45 | "container": "container-foo", 46 | }, 47 | } 48 | extraLabels := map[string]string{ 49 | "foo": "bar", 50 | "hello": "world", 51 | "ding": "dong", 52 | } 53 | 54 | b.ResetTimer() 55 | for i := 0; i < b.N; i++ { 56 | Identifier(monitoredResource, extraLabels, metric, attrs) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /exporter/collector/internal/logsutil/logsutil.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package logsutil 16 | 17 | // ExporterConfig configures the Logs exporter with various settings post-initializition. 18 | // It is meant to be used by integration tests. 19 | type ExporterConfig struct { 20 | // MaxEntrySize is the maximum size of an individual LogEntry in bytes. Entries 21 | // larger than this size will be split into multiple entries. 22 | MaxEntrySize int 23 | // MaxRequestSize is the maximum size of a batch WriteLogEntries request in bytes. 24 | // Request larger than this size will be split into multiple requests. 25 | MaxRequestSize int 26 | } 27 | -------------------------------------------------------------------------------- /exporter/collector/internal/normalization/types.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package normalization 16 | 17 | import ( 18 | "go.opentelemetry.io/collector/pdata/pmetric" 19 | ) 20 | 21 | // Normalizer can normalize data points to handle cases in which the start time is unknown. 22 | type Normalizer interface { 23 | // NormalizeExponentialHistogramDataPoint normalizes an exponential histogram. 24 | // It returns the normalized point, and true if the point should be kept. 25 | NormalizeExponentialHistogramDataPoint(point pmetric.ExponentialHistogramDataPoint, identifier uint64) bool 26 | // NormalizeHistogramDataPoint normalizes a cumulative histogram. 27 | // It returns the normalized point, and true if the point should be kept. 28 | NormalizeHistogramDataPoint(point pmetric.HistogramDataPoint, identifier uint64) bool 29 | // NormalizeNumberDataPoint normalizes a cumulative, monotonic sum. 30 | // It returns the normalized point, and true if the point should be kept. 31 | NormalizeNumberDataPoint(point pmetric.NumberDataPoint, identifier uint64) bool 32 | // NormalizeSummaryDataPoint normalizes a summary. 33 | // It returns the normalized point, and true if the point should be kept. 34 | NormalizeSummaryDataPoint(point pmetric.SummaryDataPoint, identifier uint64) bool 35 | } 36 | -------------------------------------------------------------------------------- /exporter/collector/monitoredresource.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package collector 16 | 17 | import ( 18 | "regexp" 19 | "strings" 20 | 21 | "go.opentelemetry.io/collector/pdata/pcommon" 22 | semconv "go.opentelemetry.io/collector/semconv/v1.22.0" 23 | monitoredrespb "google.golang.org/genproto/googleapis/api/monitoredres" 24 | 25 | "github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping" 26 | ) 27 | 28 | type attributes struct { 29 | Attrs pcommon.Map 30 | } 31 | 32 | func (attrs *attributes) GetString(key string) (string, bool) { 33 | value, ok := attrs.Attrs.Get(key) 34 | if ok { 35 | return value.AsString(), ok 36 | } 37 | return "", false 38 | } 39 | 40 | // defaultResourceToMonitoredResource pdata Resource to a GCM Monitored Resource. 41 | func defaultResourceToMonitoringMonitoredResource(resource pcommon.Resource) *monitoredrespb.MonitoredResource { 42 | return resourcemapping.ResourceAttributesToMonitoringMonitoredResource(&attributes{ 43 | Attrs: resource.Attributes(), 44 | }) 45 | } 46 | 47 | // defaultResourceToMonitoredResource pdata Resource to a GCM Monitored Resource. 48 | func defaultResourceToLoggingMonitoredResource(resource pcommon.Resource) *monitoredrespb.MonitoredResource { 49 | return resourcemapping.ResourceAttributesToLoggingMonitoredResource(&attributes{ 50 | Attrs: resource.Attributes(), 51 | }) 52 | } 53 | 54 | // resourceToLabels converts the Resource attributes into labels. 55 | // TODO(@damemi): Refactor to pass control-coupling lint check. 56 | // 57 | //nolint:revive 58 | func filterAttributes( 59 | attributes pcommon.Map, 60 | serviceResourceLabels bool, 61 | resourceFilters []ResourceFilter, 62 | ) pcommon.Map { 63 | attrs := pcommon.NewMap() 64 | attributes.Range(func(k string, v pcommon.Value) bool { 65 | // Is a service attribute and should be included 66 | if serviceResourceLabels && 67 | (k == semconv.AttributeServiceName || 68 | k == semconv.AttributeServiceNamespace || 69 | k == semconv.AttributeServiceInstanceID) { 70 | if len(v.AsString()) > 0 { 71 | v.CopyTo(attrs.PutEmpty(k)) 72 | } 73 | return true 74 | } 75 | // Matches one of the resource filters 76 | for _, resourceFilter := range resourceFilters { 77 | if match, _ := regexp.Match(resourceFilter.Regex, []byte(k)); strings.HasPrefix(k, resourceFilter.Prefix) && match { 78 | v.CopyTo(attrs.PutEmpty(k)) 79 | return true 80 | } 81 | } 82 | return true 83 | }) 84 | return attrs 85 | } 86 | -------------------------------------------------------------------------------- /exporter/collector/spansnapshot.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 OpenTelemetry Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package collector 16 | 17 | import ( 18 | "time" 19 | 20 | "go.opentelemetry.io/otel/attribute" 21 | "go.opentelemetry.io/otel/sdk/instrumentation" 22 | sdkresource "go.opentelemetry.io/otel/sdk/resource" 23 | sdktrace "go.opentelemetry.io/otel/sdk/trace" 24 | apitrace "go.opentelemetry.io/otel/trace" 25 | ) 26 | 27 | // spanSnapshot serves the same purpose as 28 | // https://github.com/open-telemetry/opentelemetry-go/blob/main/sdk/trace/snapshot.go#L28 29 | // It allows instantiating ReadOnlySpans. 30 | type spanSnapshot struct { 31 | endTime time.Time 32 | startTime time.Time 33 | // ReadOnlySpan is needed so we can inherit the "private" func 34 | sdktrace.ReadOnlySpan 35 | resource *sdkresource.Resource 36 | instrumentationScope instrumentation.Scope 37 | status sdktrace.Status 38 | name string 39 | attributes []attribute.KeyValue 40 | events []sdktrace.Event 41 | links []sdktrace.Link 42 | parent apitrace.SpanContext 43 | spanContext apitrace.SpanContext 44 | droppedMessageEvents int 45 | droppedLinks int 46 | childSpanCount int 47 | spanKind apitrace.SpanKind 48 | droppedAttributes int 49 | } 50 | 51 | func (s spanSnapshot) Name() string { return s.name } 52 | func (s spanSnapshot) SpanContext() apitrace.SpanContext { return s.spanContext } 53 | func (s spanSnapshot) Parent() apitrace.SpanContext { return s.parent } 54 | func (s spanSnapshot) SpanKind() apitrace.SpanKind { return s.spanKind } 55 | func (s spanSnapshot) StartTime() time.Time { return s.startTime } 56 | func (s spanSnapshot) EndTime() time.Time { return s.endTime } 57 | func (s spanSnapshot) Attributes() []attribute.KeyValue { return s.attributes } 58 | func (s spanSnapshot) Links() []sdktrace.Link { return s.links } 59 | func (s spanSnapshot) Events() []sdktrace.Event { return s.events } 60 | func (s spanSnapshot) Status() sdktrace.Status { return s.status } 61 | func (s spanSnapshot) Resource() *sdkresource.Resource { return s.resource } 62 | func (s spanSnapshot) DroppedAttributes() int { return s.droppedAttributes } 63 | func (s spanSnapshot) DroppedLinks() int { return s.droppedLinks } 64 | func (s spanSnapshot) DroppedEvents() int { return s.droppedLinks } 65 | func (s spanSnapshot) ChildSpanCount() int { return s.childSpanCount } 66 | func (s spanSnapshot) InstrumentationScope() instrumentation.Scope { 67 | return s.instrumentationScope 68 | } 69 | -------------------------------------------------------------------------------- /exporter/collector/version.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package collector 16 | 17 | // Version is the current release version of the OpenTelemetry 18 | // Operations Collector Exporter in use. 19 | func Version() string { 20 | return "0.52.0" 21 | } 22 | -------------------------------------------------------------------------------- /exporter/metric/README.md: -------------------------------------------------------------------------------- 1 | # OpenTelemetry Google Cloud Monitoring Exporter 2 | 3 | [![Docs](https://godoc.org/github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric?status.svg)](https://pkg.go.dev/github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric) 4 | [![Apache License][license-image]][license-url] 5 | 6 | OpenTelemetry Google Cloud Monitoring Exporter allows the user to send collected metrics to Google Cloud. 7 | 8 | To get started with instrumentation in Google Cloud, see [Generate traces and metrics with 9 | Go](https://cloud.google.com/stackdriver/docs/instrumentation/setup/go). 10 | 11 | To learn more about instrumentation and observability, including opinionated recommendations 12 | for Google Cloud Observability, visit [Instrumentation and 13 | observability](https://cloud.google.com/stackdriver/docs/instrumentation/overview). 14 | 15 | [Google Cloud Monitoring](https://cloud.google.com/monitoring) provides visibility into the performance, uptime, and overall health of cloud-powered applications. It collects metrics, events, and metadata from Google Cloud, Amazon Web Services, hosted uptime probes, application instrumentation, and a variety of common application components including Cassandra, Nginx, Apache Web Server, Elasticsearch, and many others. Operations ingests that data and generates insights via dashboards, charts, and alerts. Cloud Monitoring alerting helps you collaborate by integrating with Slack, PagerDuty, and more. 16 | 17 | ## Setup 18 | 19 | Google Cloud Monitoring is a managed service provided by Google Cloud Platform. Google Cloud Monitoring requires to set up "Workspace" in advance. The guide to create a new Workspace is available on [the official document](https://cloud.google.com/monitoring/workspaces/create). 20 | 21 | ## Authentication 22 | 23 | The Google Cloud Monitoring exporter depends upon [`google.FindDefaultCredentials`](https://pkg.go.dev/golang.org/x/oauth2/google?tab=doc#FindDefaultCredentials), so the service account is automatically detected by default, but also the custom credential file (so called `service_account_key.json`) can be detected with specific conditions. Quoting from the document of `google.FindDefaultCredentials`: 24 | 25 | * A JSON file whose path is specified by the `GOOGLE_APPLICATION_CREDENTIALS` environment variable. 26 | * A JSON file in a location known to the gcloud command-line tool. On Windows, this is `%APPDATA%/gcloud/application_default_credentials.json`. On other systems, `$HOME/.config/gcloud/application_default_credentials.json`. 27 | 28 | When running code locally, you may need to specify a Google Project ID in addition to `GOOGLE_APPLICATION_CREDENTIALS`. This is best done using an environment variable (e.g. `GOOGLE_CLOUD_PROJECT`) and the `metric.WithProjectID` method, e.g.: 29 | 30 | ```golang 31 | projectID := os.Getenv("GOOGLE_CLOUD_PROJECT") 32 | opts := []mexporter.Option{ 33 | mexporter.WithProjectID(projectID), 34 | } 35 | ``` 36 | 37 | ## Useful links 38 | 39 | * For more information on OpenTelemetry, visit: https://opentelemetry.io/ 40 | * For more about OpenTelemetry Go, visit: https://github.com/open-telemetry/opentelemetry-go 41 | * Learn more about Google Cloud Monitoring at https://cloud.google.com/monitoring 42 | 43 | [license-url]: https://github.com/GoogleCloudPlatform/opentelemetry-operations-go/blob/main/LICENSE 44 | [license-image]: https://img.shields.io/badge/license-Apache_2.0-green.svg?style=flat 45 | -------------------------------------------------------------------------------- /exporter/metric/cloudmonitoring.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package metric 16 | 17 | import ( 18 | "context" 19 | "errors" 20 | "fmt" 21 | 22 | sdkmetric "go.opentelemetry.io/otel/sdk/metric" 23 | 24 | monitoring "cloud.google.com/go/monitoring/apiv3/v2" 25 | "golang.org/x/oauth2/google" 26 | ) 27 | 28 | // New creates a new Exporter thats implements metric.Exporter. 29 | func New(opts ...Option) (sdkmetric.Exporter, error) { 30 | o := options{ 31 | context: context.Background(), 32 | resourceAttributeFilter: DefaultResourceAttributesFilter, 33 | } 34 | for _, opt := range opts { 35 | opt(&o) 36 | } 37 | 38 | if o.projectID == "" { 39 | creds, err := google.FindDefaultCredentials(o.context, monitoring.DefaultAuthScopes()...) 40 | if err != nil { 41 | return nil, fmt.Errorf("failed to find Google Cloud credentials: %v", err) 42 | } 43 | if creds.ProjectID == "" { 44 | return nil, errors.New("google cloud monitoring: no project found with application default credentials") 45 | } 46 | o.projectID = creds.ProjectID 47 | } 48 | return newMetricExporter(&o) 49 | } 50 | -------------------------------------------------------------------------------- /exporter/metric/cloudmonitoring_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package metric 16 | 17 | import ( 18 | "fmt" 19 | "testing" 20 | 21 | monitoring "cloud.google.com/go/monitoring/apiv3/v2" 22 | ) 23 | 24 | func TestNew(t *testing.T) { 25 | cl := &monitoring.MetricClient{} 26 | tcs := []struct { 27 | desc string 28 | opts []Option 29 | verifyExporterFunc func(*metricExporter) error 30 | }{ 31 | { 32 | desc: "WithMetricClient sets the client", 33 | opts: []Option{WithMonitoringClient(cl)}, 34 | verifyExporterFunc: func(e *metricExporter) error { 35 | if e.client != cl { 36 | return fmt.Errorf("client mismatch, got = %p, want = %p", e.client, cl) 37 | } 38 | return nil 39 | }, 40 | }, 41 | { 42 | desc: "WithMetricClient overrides WithMetricClientOptions", 43 | opts: []Option{WithMonitoringClient(cl), WithMonitoringClientOptions()}, 44 | verifyExporterFunc: func(e *metricExporter) error { 45 | if e.client != cl { 46 | return fmt.Errorf("client mismatch, got = %p, want = %p", e.client, cl) 47 | } 48 | return nil 49 | }, 50 | }, 51 | } 52 | 53 | for _, tc := range tcs { 54 | t.Run(tc.desc, func(t *testing.T) { 55 | opts := append(tc.opts, WithProjectID("some-project-id")) 56 | e, err := New(opts...) 57 | if err != nil { 58 | t.Fatalf("New(): %v", err) 59 | } 60 | exp, ok := e.(*metricExporter) 61 | if !ok { 62 | t.Fatal("unexpected type mismatch") 63 | } 64 | if err := tc.verifyExporterFunc(exp); err != nil { 65 | t.Fatalf("failed to verify exporter: %v", err) 66 | } 67 | }) 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /exporter/metric/error.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package metric 16 | 17 | import ( 18 | "errors" 19 | "fmt" 20 | ) 21 | 22 | var ( 23 | errBlankProjectID = errors.New("expecting a non-blank ProjectID") 24 | ) 25 | 26 | type errUnexpectedAggregationKind struct { 27 | kind string 28 | } 29 | 30 | func (e errUnexpectedAggregationKind) Error() string { 31 | return fmt.Sprintf("the metric kind is unexpected: %v", e.kind) 32 | } 33 | -------------------------------------------------------------------------------- /exporter/metric/example_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package metric_test 16 | 17 | import ( 18 | "context" 19 | "log" 20 | 21 | "go.opentelemetry.io/otel/attribute" 22 | "go.opentelemetry.io/otel/metric" 23 | sdkmetric "go.opentelemetry.io/otel/sdk/metric" 24 | 25 | mexporter "github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric" 26 | ) 27 | 28 | func ExampleNew() { 29 | exporter, err := mexporter.New() 30 | if err != nil { 31 | log.Printf("Failed to create exporter: %v", err) 32 | return 33 | } 34 | // initialize a MeterProvider with that periodically exports to the GCP exporter. 35 | provider := sdkmetric.NewMeterProvider( 36 | sdkmetric.WithReader(sdkmetric.NewPeriodicReader(exporter)), 37 | ) 38 | ctx := context.Background() 39 | defer func() { 40 | if err = provider.Shutdown(ctx); err != nil { 41 | log.Printf("Failed to shut down meter provider: %v", err) 42 | } 43 | }() 44 | 45 | // Start meter 46 | meter := provider.Meter("github.com/GoogleCloudPlatform/opentelemetry-operations-go/example/metric") 47 | 48 | counter, err := meter.Int64Counter("counter-foo") 49 | if err != nil { 50 | log.Printf("Failed to create counter: %v", err) 51 | return 52 | } 53 | attrs := []attribute.KeyValue{ 54 | attribute.Key("key").String("value"), 55 | } 56 | counter.Add(ctx, 123, metric.WithAttributes(attrs...)) 57 | } 58 | -------------------------------------------------------------------------------- /exporter/metric/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric 2 | 3 | go 1.23.0 4 | 5 | require ( 6 | cloud.google.com/go/monitoring v1.24.2 7 | github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.52.0 8 | github.com/googleapis/gax-go/v2 v2.14.2 9 | github.com/stretchr/testify v1.10.0 10 | go.opentelemetry.io/otel v1.36.0 11 | go.opentelemetry.io/otel/metric v1.36.0 12 | go.opentelemetry.io/otel/sdk v1.36.0 13 | go.opentelemetry.io/otel/sdk/metric v1.36.0 14 | golang.org/x/net v0.40.0 // indirect 15 | golang.org/x/oauth2 v0.30.0 16 | golang.org/x/sys v0.33.0 // indirect 17 | google.golang.org/api v0.234.0 18 | google.golang.org/genproto v0.0.0-20250505200425-f936aa4a68b2 // indirect 19 | google.golang.org/grpc v1.72.2 20 | google.golang.org/protobuf v1.36.6 21 | ) 22 | 23 | require ( 24 | github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.52.0 25 | go.opentelemetry.io/otel/trace v1.36.0 26 | google.golang.org/genproto/googleapis/api v0.0.0-20250505200425-f936aa4a68b2 27 | ) 28 | 29 | require ( 30 | cloud.google.com/go/auth v0.16.1 // indirect 31 | cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect 32 | cloud.google.com/go/compute/metadata v0.7.0 // indirect 33 | cloud.google.com/go/logging v1.13.0 // indirect 34 | cloud.google.com/go/longrunning v0.6.7 // indirect 35 | cloud.google.com/go/trace v1.11.6 // indirect 36 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect 37 | github.com/go-logr/logr v1.4.3 // indirect 38 | github.com/go-logr/stdr v1.2.2 // indirect 39 | github.com/google/s2a-go v0.1.9 // indirect 40 | github.com/google/uuid v1.6.0 // indirect 41 | github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect 42 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect 43 | go.opentelemetry.io/auto/sdk v1.1.0 // indirect 44 | go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 // indirect 45 | go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect 46 | golang.org/x/crypto v0.38.0 // indirect 47 | golang.org/x/sync v0.14.0 // indirect 48 | golang.org/x/text v0.25.0 // indirect 49 | golang.org/x/time v0.11.0 // indirect 50 | google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect 51 | gopkg.in/yaml.v3 v3.0.1 // indirect 52 | ) 53 | 54 | replace github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock => ../../internal/cloudmock 55 | 56 | replace github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping => ../../internal/resourcemapping 57 | 58 | retract v1.0.0-RC1 59 | -------------------------------------------------------------------------------- /exporter/metric/version.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package metric 16 | 17 | // Version is the current release version of the OpenTelemetry 18 | // Operations Metric Exporter in use. 19 | func Version() string { 20 | return "0.52.0" 21 | } 22 | -------------------------------------------------------------------------------- /exporter/trace/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace 2 | 3 | go 1.23.0 4 | 5 | require ( 6 | cloud.google.com/go/trace v1.11.6 7 | github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.52.0 8 | github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.52.0 9 | github.com/stretchr/testify v1.10.0 10 | go.opentelemetry.io/otel v1.36.0 11 | go.opentelemetry.io/otel/sdk v1.36.0 12 | go.opentelemetry.io/otel/trace v1.36.0 13 | golang.org/x/oauth2 v0.30.0 14 | google.golang.org/api v0.234.0 15 | google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 16 | google.golang.org/grpc v1.72.2 17 | google.golang.org/protobuf v1.36.6 18 | ) 19 | 20 | require ( 21 | cloud.google.com/go/auth v0.16.1 // indirect 22 | cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect 23 | cloud.google.com/go/compute/metadata v0.7.0 // indirect 24 | cloud.google.com/go/logging v1.13.0 // indirect 25 | cloud.google.com/go/longrunning v0.6.7 // indirect 26 | cloud.google.com/go/monitoring v1.24.2 // indirect 27 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect 28 | github.com/felixge/httpsnoop v1.0.4 // indirect 29 | github.com/go-logr/logr v1.4.3 // indirect 30 | github.com/go-logr/stdr v1.2.2 // indirect 31 | github.com/google/s2a-go v0.1.9 // indirect 32 | github.com/google/uuid v1.6.0 // indirect 33 | github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect 34 | github.com/googleapis/gax-go/v2 v2.14.2 // indirect 35 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect 36 | go.opentelemetry.io/auto/sdk v1.1.0 // indirect 37 | go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 // indirect 38 | go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect 39 | go.opentelemetry.io/otel/metric v1.36.0 // indirect 40 | golang.org/x/crypto v0.38.0 // indirect 41 | golang.org/x/net v0.40.0 // indirect 42 | golang.org/x/sync v0.14.0 // indirect 43 | golang.org/x/sys v0.33.0 // indirect 44 | golang.org/x/text v0.25.0 // indirect 45 | golang.org/x/time v0.11.0 // indirect 46 | google.golang.org/genproto v0.0.0-20250505200425-f936aa4a68b2 // indirect 47 | google.golang.org/genproto/googleapis/api v0.0.0-20250505200425-f936aa4a68b2 // indirect 48 | gopkg.in/yaml.v3 v3.0.1 // indirect 49 | ) 50 | 51 | replace github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping => ../../internal/resourcemapping 52 | 53 | replace github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock => ../../internal/cloudmock 54 | -------------------------------------------------------------------------------- /exporter/trace/version.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package trace 16 | 17 | // Version is the current release version of the OpenTelemetry 18 | // Operations Trace Exporter in use. 19 | func Version() string { 20 | return "1.28.0" 21 | } 22 | -------------------------------------------------------------------------------- /extension/googleclientauthextension/README.md: -------------------------------------------------------------------------------- 1 | # Authenticator - Google Client Credentials 2 | 3 | | Status | | 4 | | ------------- |-----------| 5 | | Stability | [alpha] | 6 | 7 | [alpha]: https://github.com/open-telemetry/opentelemetry-collector#alpha 8 | 9 | This extension provides Google OAuth2 Client Credentials and Metadata for gRPC and http based exporters. 10 | 11 | The authenticator type has to be set to `googleclientauth`. 12 | 13 | ## Configuration 14 | 15 | ```yaml 16 | extensions: 17 | googleclientauth: 18 | 19 | receivers: 20 | otlp: 21 | protocols: 22 | grpc: 23 | 24 | exporters: 25 | otlp/withauth: 26 | endpoint: 0.0.0.0:5000 27 | ca_file: /tmp/certs/ca.pem 28 | auth: 29 | authenticator: googleclientauth 30 | 31 | service: 32 | extensions: [googleclientauth] 33 | pipelines: 34 | metrics: 35 | receivers: [otlp] 36 | processors: [] 37 | exporters: [otlp/withauth] 38 | ``` 39 | 40 | Following are the configuration fields: 41 | - **project** - The Google Cloud Project telemetry is sent to if the gcp.project.id resource attribute is not set. If unspecified, this is determined using application default credentials. 42 | - [**scopes**](https://datatracker.ietf.org/doc/html/rfc6749#section-3.3) - The oauth 2.0 scopes requested by the extension. 43 | - [**quota_project**](https://cloud.google.com/apis/docs/system-parameters) - The project for quota and billing purposes. The caller must have serviceusage.services.use permission on the project. 44 | - **token_type** - The type of generated token. Default: `access_token` 45 | - `access_token`: [OAuth 2.0 access token](https://cloud.google.com/docs/authentication/token-types#access) will be generated. 46 | - `id_token`: Google-signed [ID token](https://cloud.google.com/docs/authentication/token-types#id) will be generated. 47 | - **audience** - The audience claim used for generating ID token 48 | -------------------------------------------------------------------------------- /extension/googleclientauthextension/config.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package googleclientauthextension // import "github.com/GoogleCloudPlatform/opentelemetry-operations-go/extension/googleclientauthextension" 16 | 17 | import ( 18 | "errors" 19 | 20 | "go.opentelemetry.io/collector/component" 21 | ) 22 | 23 | const ( 24 | // accessToken indicates OAuth 2.0 access token (https://cloud.google.com/docs/authentication/token-types#access) 25 | accessToken = "access_token" 26 | 27 | // idToken indicates Google-signed ID-token (https://cloud.google.com/docs/authentication/token-types#id) 28 | idToken = "id_token" 29 | ) 30 | 31 | var tokenTypes = map[string]struct{}{ 32 | accessToken: {}, 33 | idToken: {}, 34 | } 35 | 36 | // Config stores the configuration for GCP Client Credentials. 37 | type Config struct { 38 | // Project is the project telemetry is sent to if the gcp.project.id 39 | // resource attribute is not set. If unspecified, this is determined using 40 | // application default credentials. 41 | Project string `mapstructure:"project"` 42 | 43 | // QuotaProject specifies a project for quota and billing purposes. The 44 | // caller must have serviceusage.services.use permission on the project. 45 | // 46 | // For more information please read: 47 | // https://cloud.google.com/apis/docs/system-parameters 48 | QuotaProject string `mapstructure:"quota_project"` 49 | 50 | // TokenType specifies which type of token will be generated. 51 | // default: access_token 52 | TokenType string `mapstructure:"token_type,omitempty"` 53 | 54 | // Audience specifies the audience claim used for generating ID token. 55 | Audience string `mapstructure:"audience,omitempty"` 56 | 57 | // Scope specifies optional requested permissions. 58 | // See https://datatracker.ietf.org/doc/html/rfc6749#section-3.3 59 | Scopes []string `mapstructure:"scopes,omitempty"` 60 | 61 | // TODO: Support impersonation, similar to what exists in the googlecloud collector exporter. 62 | } 63 | 64 | var _ component.Config = (*Config)(nil) 65 | 66 | // Validate checks if the extension configuration is valid. 67 | func (cfg *Config) Validate() error { 68 | if _, ok := tokenTypes[cfg.TokenType]; !ok { 69 | return errors.New("invalid token_type") 70 | } 71 | 72 | if cfg.TokenType == idToken && cfg.Audience == "" { 73 | return errors.New("audience must be specified when using the id_token token_type") 74 | } 75 | 76 | return nil 77 | } 78 | 79 | // defaultScopes are the scopes required for writing logs, metrics, and traces. 80 | var defaultScopes = []string{ 81 | "https://www.googleapis.com/auth/cloud-platform", 82 | "https://www.googleapis.com/auth/logging.write", 83 | "https://www.googleapis.com/auth/monitoring.write", 84 | "https://www.googleapis.com/auth/trace.append", 85 | } 86 | 87 | func CreateDefaultConfig() component.Config { 88 | return &Config{ 89 | Scopes: defaultScopes, 90 | TokenType: accessToken, 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /extension/googleclientauthextension/config_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package googleclientauthextension // import "github.com/GoogleCloudPlatform/opentelemetry-operations-go/extension/googleclientauthextension" 16 | 17 | import ( 18 | "testing" 19 | 20 | "github.com/stretchr/testify/assert" 21 | ) 22 | 23 | func TestConfig_Validate_ValidAccessToken(t *testing.T) { 24 | cfg := &Config{ 25 | TokenType: accessToken, 26 | } 27 | 28 | err := cfg.Validate() 29 | assert.NoError(t, err) 30 | } 31 | 32 | func TestConfig_Validate_ValidIDToken(t *testing.T) { 33 | cfg := &Config{ 34 | TokenType: idToken, 35 | Audience: "audience", 36 | } 37 | 38 | err := cfg.Validate() 39 | assert.NoError(t, err) 40 | } 41 | 42 | func TestConfig_Validate_MissingAudience(t *testing.T) { 43 | cfg := &Config{ 44 | TokenType: idToken, 45 | } 46 | 47 | err := cfg.Validate() 48 | assert.Error(t, err) 49 | } 50 | 51 | func TestConfig_Validate_Invalid(t *testing.T) { 52 | cfg := &Config{ 53 | TokenType: "invalid", 54 | } 55 | 56 | err := cfg.Validate() 57 | assert.Error(t, err) 58 | } 59 | -------------------------------------------------------------------------------- /extension/googleclientauthextension/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package googleclientauthextension provides gRPC and HTTP credentials and metadata 16 | // using Application Default Credentials: https://cloud.google.com/docs/authentication#adc 17 | package googleclientauthextension // import "github.com/GoogleCloudPlatform/opentelemetry-operations-go/extension/googleclientauthextension" 18 | -------------------------------------------------------------------------------- /extension/googleclientauthextension/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/GoogleCloudPlatform/opentelemetry-operations-go/extension/googleclientauthextension 2 | 3 | go 1.23.0 4 | 5 | require ( 6 | github.com/stretchr/testify v1.10.0 7 | go.opentelemetry.io/collector/component v0.120.0 8 | go.opentelemetry.io/collector/component/componenttest v0.120.0 9 | go.opentelemetry.io/collector/extension v0.120.0 10 | golang.org/x/oauth2 v0.30.0 11 | google.golang.org/api v0.234.0 12 | google.golang.org/grpc v1.72.2 13 | ) 14 | 15 | require ( 16 | cloud.google.com/go/auth v0.16.1 // indirect 17 | cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect 18 | cloud.google.com/go/compute/metadata v0.7.0 // indirect 19 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect 20 | github.com/felixge/httpsnoop v1.0.4 // indirect 21 | github.com/go-logr/logr v1.4.3 // indirect 22 | github.com/go-logr/stdr v1.2.2 // indirect 23 | github.com/gogo/protobuf v1.3.2 // indirect 24 | github.com/google/s2a-go v0.1.9 // indirect 25 | github.com/google/uuid v1.6.0 // indirect 26 | github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect 27 | github.com/googleapis/gax-go/v2 v2.14.2 // indirect 28 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect 29 | go.opentelemetry.io/auto/sdk v1.1.0 // indirect 30 | go.opentelemetry.io/collector/pdata v1.33.0 // indirect 31 | go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect 32 | go.opentelemetry.io/otel v1.36.0 // indirect 33 | go.opentelemetry.io/otel/metric v1.36.0 // indirect 34 | go.opentelemetry.io/otel/sdk v1.36.0 // indirect 35 | go.opentelemetry.io/otel/sdk/metric v1.36.0 // indirect 36 | go.opentelemetry.io/otel/trace v1.36.0 // indirect 37 | go.uber.org/multierr v1.11.0 // indirect 38 | go.uber.org/zap v1.27.0 // indirect 39 | golang.org/x/crypto v0.38.0 // indirect 40 | golang.org/x/net v0.40.0 // indirect 41 | golang.org/x/sys v0.33.0 // indirect 42 | golang.org/x/text v0.25.0 // indirect 43 | google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect 44 | google.golang.org/protobuf v1.36.6 // indirect 45 | gopkg.in/yaml.v3 v3.0.1 // indirect 46 | ) 47 | 48 | retract ( 49 | v0.76.2 50 | v0.76.1 51 | v0.65.0 52 | ) 53 | -------------------------------------------------------------------------------- /extension/googleclientauthextension/grpc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package googleclientauthextension // import "github.com/GoogleCloudPlatform/opentelemetry-operations-go/extension/googleclientauthextension" 16 | 17 | import ( 18 | "context" 19 | "errors" 20 | 21 | "google.golang.org/grpc/credentials" 22 | ) 23 | 24 | // perRPCCredentials returns gRPC credentials using the OAuth TokenSource, and adds 25 | // google metadata. 26 | func (ca clientAuthenticator) PerRPCCredentials() (credentials.PerRPCCredentials, error) { 27 | if ca.TokenSource == nil { 28 | return nil, errors.New("not started") 29 | } 30 | return ca, nil 31 | } 32 | 33 | // GetRequestMetadata gets the request metadata as a map from a clientAuthenticator. 34 | // Based on metadata added by the google go client: 35 | // https://github.com/googleapis/google-api-go-client/blob/113082d14d54f188d1b6c34c652e416592fc51b5/transport/grpc/dial.go#L224 36 | func (ca clientAuthenticator) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) { 37 | if ca.TokenSource == nil { 38 | return nil, errors.New("not started") 39 | } 40 | 41 | metadata, err := ca.TokenSource.GetRequestMetadata(ctx, uri...) 42 | if err != nil { 43 | return nil, err 44 | } 45 | 46 | // Attach system parameters 47 | if ca.config.QuotaProject != "" { 48 | metadata["X-goog-user-project"] = ca.config.QuotaProject 49 | } 50 | if ca.config.Project != "" { 51 | metadata["X-goog-project-id"] = ca.config.Project 52 | } 53 | return metadata, nil 54 | } 55 | -------------------------------------------------------------------------------- /extension/googleclientauthextension/grpc_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package googleclientauthextension // import "github.com/GoogleCloudPlatform/opentelemetry-operations-go/extension/googleclientauthextension" 16 | 17 | import ( 18 | "context" 19 | "testing" 20 | 21 | "github.com/stretchr/testify/assert" 22 | "google.golang.org/api/idtoken" 23 | ) 24 | 25 | func TestPerRPCCredentials(t *testing.T) { 26 | t.Setenv("GOOGLE_APPLICATION_CREDENTIALS", "testdata/fake_creds.json") 27 | ca := clientAuthenticator{config: &Config{ 28 | Project: "my-project", 29 | QuotaProject: "other-project", 30 | TokenType: accessToken, 31 | }} 32 | err := ca.Start(context.Background(), nil) 33 | assert.NoError(t, err) 34 | 35 | perrpc, err := ca.PerRPCCredentials() 36 | assert.NotNil(t, perrpc) 37 | assert.NoError(t, err) 38 | } 39 | 40 | func TestPerRPCCredentialsWithIDToken(t *testing.T) { 41 | t.Setenv("GOOGLE_APPLICATION_CREDENTIALS", "testdata/fake_isa_creds.json") 42 | ca := clientAuthenticator{ 43 | config: &Config{ 44 | Project: "my-project", 45 | TokenType: idToken, 46 | Audience: "http://example.com", 47 | }, 48 | newIDTokenSource: idtoken.NewTokenSource, 49 | } 50 | err := ca.Start(context.Background(), nil) 51 | assert.NoError(t, err) 52 | 53 | perrpc, err := ca.PerRPCCredentials() 54 | assert.NotNil(t, perrpc) 55 | assert.NoError(t, err) 56 | } 57 | 58 | func TestPerRPCCredentialsNotStarted(t *testing.T) { 59 | ca := clientAuthenticator{config: &Config{ 60 | Project: "my-project", 61 | QuotaProject: "other-project", 62 | TokenType: accessToken, 63 | }} 64 | perrpc, err := ca.PerRPCCredentials() 65 | assert.Nil(t, perrpc) 66 | assert.Error(t, err) 67 | } 68 | -------------------------------------------------------------------------------- /extension/googleclientauthextension/http.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package googleclientauthextension // import "github.com/GoogleCloudPlatform/opentelemetry-operations-go/extension/googleclientauthextension" 16 | 17 | import ( 18 | "errors" 19 | "net/http" 20 | 21 | "golang.org/x/oauth2" 22 | ) 23 | 24 | // roundTripper provides an HTTP RoundTripper which adds gcp credentials and 25 | // headers. 26 | func (ca *clientAuthenticator) RoundTripper(base http.RoundTripper) (http.RoundTripper, error) { 27 | if ca.TokenSource == nil { 28 | return nil, errors.New("not started") 29 | } 30 | return &oauth2.Transport{ 31 | Source: ca, 32 | Base: ¶meterTransport{ 33 | base: base, 34 | config: ca.config, 35 | }, 36 | }, nil 37 | } 38 | 39 | type parameterTransport struct { 40 | base http.RoundTripper 41 | config *Config 42 | } 43 | 44 | // RoundTrip adds headers related to 45 | // Based on headers added by the google go client: 46 | // https://github.com/googleapis/google-api-go-client/blob/113082d14d54f188d1b6c34c652e416592fc51b5/transport/http/dial.go#L122 47 | func (t *parameterTransport) RoundTrip(req *http.Request) (*http.Response, error) { 48 | if t.base == nil { 49 | return nil, errors.New("transport: no Transport specified") 50 | } 51 | newReq := *req 52 | newReq.Header = make(http.Header) 53 | for k, vv := range req.Header { 54 | newReq.Header[k] = vv 55 | } 56 | 57 | // Attach system parameters into the header 58 | if t.config.QuotaProject != "" { 59 | newReq.Header.Set("X-Goog-User-Project", t.config.QuotaProject) 60 | } 61 | if t.config.Project != "" { 62 | newReq.Header.Set("X-Goog-Project-ID", t.config.Project) 63 | } 64 | 65 | return t.base.RoundTrip(&newReq) 66 | } 67 | -------------------------------------------------------------------------------- /extension/googleclientauthextension/testdata/fake_creds.json: -------------------------------------------------------------------------------- 1 | { 2 | "client_id": "notreal-notreal.apps.googleusercontent.com", 3 | "client_secret": "d-notreal", 4 | "project_id": "my-project", 5 | "refresh_token": "notreal-notreal-notreal-notreal-notreal", 6 | "type": "authorized_user" 7 | } -------------------------------------------------------------------------------- /extension/googleclientauthextension/testdata/fake_creds_no_project.json: -------------------------------------------------------------------------------- 1 | { 2 | "client_id": "notreal-notreal.apps.googleusercontent.com", 3 | "client_secret": "d-notreal", 4 | "project_id": "", 5 | "refresh_token": "notreal-notreal-notreal-notreal-notreal", 6 | "type": "authorized_user" 7 | } 8 | -------------------------------------------------------------------------------- /extension/googleclientauthextension/testdata/fake_isa_creds.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "impersonated_service_account", 3 | "service_account_impersonation_url": "http://example.com", 4 | "source_credentials": { 5 | "client_id": "notreal-notreal.apps.googleusercontent.com", 6 | "client_secret": "d-notreal", 7 | "refresh_token": "notreal-notreal-notreal-notreal-notreal", 8 | "type": "authorized_user" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /get_main_pkgs.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2020 Google LLC 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -euo pipefail 18 | 19 | top_dir='.' 20 | if [[ $# -gt 0 ]]; then 21 | top_dir="${1}" 22 | fi 23 | 24 | p=$(pwd) 25 | mod_dirs=() 26 | mapfile -t mod_dirs < <(find "${top_dir}" -type f -name 'go.mod' -exec dirname {} \; | sort) 27 | 28 | for mod_dir in "${mod_dirs[@]}"; do 29 | cd "${mod_dir}" 30 | main_dirs=() 31 | mapfile -t main_dirs < <(go list --find -f '{{.Name}}|{{.Dir}}' ./... | grep '^main|' | cut -f 2- -d '|') 32 | for main_dir in "${main_dirs[@]}"; do 33 | echo ".${main_dir#${p}}" 34 | done 35 | cd "${p}" 36 | done 37 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/GoogleCloudPlatform/opentelemetry-operations-go 2 | 3 | go 1.23 4 | 5 | retract ( 6 | v1.8.0 7 | v1.5.2 8 | v1.5.1 9 | v1.5.0 10 | v1.4.0 11 | v1.3.0 12 | v1.0.0 13 | v1.0.0-RC2 14 | v1.0.0-RC1 15 | ) 16 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/opentelemetry-operations-go/6658b3aae40518709f8f7763b3e5f0881507ffc1/go.sum -------------------------------------------------------------------------------- /internal/buildscripts/update-dep: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Updates MODULE inside go.mod if it is already present to version VERSION. 4 | 5 | set -e 6 | 7 | if grep -q "$MODULE " go.mod; then 8 | go get $MODULE@$VERSION 9 | fi 10 | 11 | -------------------------------------------------------------------------------- /internal/cloudmock/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock 2 | 3 | go 1.23.0 4 | 5 | require ( 6 | cloud.google.com/go/logging v1.13.0 7 | cloud.google.com/go/monitoring v1.24.2 8 | cloud.google.com/go/trace v1.11.6 9 | google.golang.org/genproto/googleapis/api v0.0.0-20250505200425-f936aa4a68b2 10 | google.golang.org/grpc v1.72.2 11 | google.golang.org/protobuf v1.36.6 12 | ) 13 | 14 | require ( 15 | cloud.google.com/go/longrunning v0.6.7 // indirect 16 | github.com/go-logr/logr v1.4.3 // indirect 17 | github.com/google/go-cmp v0.7.0 // indirect 18 | go.opentelemetry.io/otel v1.36.0 // indirect 19 | go.opentelemetry.io/otel/sdk/metric v1.36.0 // indirect 20 | golang.org/x/net v0.40.0 // indirect 21 | golang.org/x/sys v0.33.0 // indirect 22 | golang.org/x/text v0.25.0 // indirect 23 | google.golang.org/genproto v0.0.0-20250505200425-f936aa4a68b2 // indirect 24 | google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect 25 | ) 26 | -------------------------------------------------------------------------------- /internal/cloudmock/logs.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cloudmock 16 | 17 | import ( 18 | "context" 19 | "net" 20 | "strings" 21 | "sync" 22 | 23 | logpb "cloud.google.com/go/logging/apiv2/loggingpb" 24 | "google.golang.org/grpc" 25 | "google.golang.org/grpc/metadata" 26 | ) 27 | 28 | type LogsTestServer struct { 29 | lis net.Listener 30 | srv *grpc.Server 31 | // Endpoint where the gRPC server is listening 32 | Endpoint string 33 | userAgent string 34 | writeLogEntriesRequests []*logpb.WriteLogEntriesRequest 35 | mu sync.Mutex 36 | } 37 | 38 | func (l *LogsTestServer) Shutdown() { 39 | l.srv.GracefulStop() 40 | } 41 | 42 | func (l *LogsTestServer) Serve() { 43 | //nolint:errcheck 44 | l.srv.Serve(l.lis) 45 | } 46 | 47 | func (l *LogsTestServer) CreateWriteLogEntriesRequests() []*logpb.WriteLogEntriesRequest { 48 | l.mu.Lock() 49 | defer l.mu.Unlock() 50 | reqs := l.writeLogEntriesRequests 51 | l.writeLogEntriesRequests = nil 52 | return reqs 53 | } 54 | 55 | // Pops out the UserAgent from the most recent CreateWriteLogEntries. 56 | func (l *LogsTestServer) UserAgent() string { 57 | l.mu.Lock() 58 | defer l.mu.Unlock() 59 | ua := l.userAgent 60 | l.userAgent = "" 61 | return ua 62 | } 63 | 64 | func (l *LogsTestServer) appendWriteLogEntriesRequest(ctx context.Context, req *logpb.WriteLogEntriesRequest) { 65 | l.mu.Lock() 66 | defer l.mu.Unlock() 67 | l.writeLogEntriesRequests = append(l.writeLogEntriesRequests, req) 68 | if md, ok := metadata.FromIncomingContext(ctx); ok { 69 | l.userAgent = strings.Join(md.Get("User-Agent"), ";") 70 | } 71 | } 72 | 73 | type fakeLoggingServiceServer struct { 74 | logpb.UnimplementedLoggingServiceV2Server 75 | logsTestServer *LogsTestServer 76 | } 77 | 78 | func (f *fakeLoggingServiceServer) WriteLogEntries( 79 | ctx context.Context, 80 | request *logpb.WriteLogEntriesRequest, 81 | ) (*logpb.WriteLogEntriesResponse, error) { 82 | f.logsTestServer.appendWriteLogEntriesRequest(ctx, request) 83 | return &logpb.WriteLogEntriesResponse{}, nil 84 | } 85 | 86 | func NewLoggingTestServer() (*LogsTestServer, error) { 87 | srv := grpc.NewServer() 88 | lis, err := net.Listen("tcp", "localhost:0") 89 | if err != nil { 90 | return nil, err 91 | } 92 | testServer := &LogsTestServer{ 93 | Endpoint: lis.Addr().String(), 94 | lis: lis, 95 | srv: srv, 96 | } 97 | logpb.RegisterLoggingServiceV2Server( 98 | srv, 99 | &fakeLoggingServiceServer{logsTestServer: testServer}, 100 | ) 101 | 102 | return testServer, nil 103 | } 104 | -------------------------------------------------------------------------------- /internal/resourcemapping/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping 2 | 3 | go 1.23.0 4 | 5 | require ( 6 | go.opentelemetry.io/otel v1.36.0 7 | google.golang.org/genproto/googleapis/api v0.0.0-20250505200425-f936aa4a68b2 8 | ) 9 | 10 | require ( 11 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect 12 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect 13 | google.golang.org/protobuf v1.36.6 // indirect 14 | ) 15 | -------------------------------------------------------------------------------- /internal/resourcemapping/go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= 2 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 3 | github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= 4 | github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= 5 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= 6 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 7 | github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= 8 | github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 9 | go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg= 10 | go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E= 11 | google.golang.org/genproto/googleapis/api v0.0.0-20250505200425-f936aa4a68b2 h1:vPV0tzlsK6EzEDHNNH5sa7Hs9bd7iXR7B1tSiPepkV0= 12 | google.golang.org/genproto/googleapis/api v0.0.0-20250505200425-f936aa4a68b2/go.mod h1:pKLAc5OolXC3ViWGI62vvC0n10CpwAtRcTNCFwTKBEw= 13 | google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= 14 | google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= 15 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 16 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 17 | -------------------------------------------------------------------------------- /propagator/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/GoogleCloudPlatform/opentelemetry-operations-go/propagator 2 | 3 | go 1.23.0 4 | 5 | require ( 6 | github.com/google/go-cmp v0.7.0 7 | go.opentelemetry.io/otel v1.36.0 8 | go.opentelemetry.io/otel/trace v1.36.0 9 | ) 10 | 11 | require ( 12 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect 13 | github.com/go-logr/logr v1.4.3 // indirect 14 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect 15 | ) 16 | -------------------------------------------------------------------------------- /propagator/go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= 2 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 3 | github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= 4 | github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 5 | github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= 6 | github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= 7 | github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= 8 | github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= 9 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= 10 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 11 | github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= 12 | github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 13 | go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= 14 | go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= 15 | go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg= 16 | go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E= 17 | go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE= 18 | go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs= 19 | go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w= 20 | go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= 21 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 22 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 23 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:recommended" 5 | ], 6 | "ignorePaths": [], 7 | "labels": ["Skip Changelog", "dependencies"], 8 | "postUpdateOptions" : [ 9 | "gomodTidy" 10 | ], 11 | "packageRules": [ 12 | { 13 | "matchManagers": ["gomod"], 14 | "matchDepTypes": ["indirect"], 15 | "enabled": true 16 | }, 17 | { 18 | "matchFileNames": ["tools/**"], 19 | "matchManagers": ["gomod"], 20 | "matchDepTypes": ["indirect"], 21 | "enabled": false 22 | }, 23 | { 24 | "matchPackageNames": ["google.golang.org/**"], 25 | "groupName": "google.golang.org" 26 | }, 27 | { 28 | "matchPackageNames": ["golang.org/x/**"], 29 | "groupName": "golang.org/x" 30 | }, 31 | { 32 | "matchPackageNames": ["cloud.google.com/**"], 33 | "groupName": "cloud.google.com" 34 | }, 35 | { 36 | "matchManagers": ["gomod"], 37 | "matchPackageNames": ["go.opentelemetry.io/collector/**", "github.com/open-telemetry/opentelemetry-collector-contrib/**"], 38 | "groupName": "go.opentelemetry.io/collector" 39 | }, 40 | { 41 | "matchManagers": ["gomod"], 42 | "matchPackageNames": ["go.opentelemetry.io/otel", "go.opentelemetry.io/otel/**", "go.opentelemetry.io/contrib/**"], 43 | "groupName": "go.opentelemetry.io/otel" 44 | } 45 | ] 46 | } 47 | -------------------------------------------------------------------------------- /tools/tools.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | //go:build tools 16 | 17 | package tools 18 | 19 | import ( 20 | _ "github.com/client9/misspell/cmd/misspell" 21 | _ "github.com/golangci/golangci-lint/cmd/golangci-lint" 22 | _ "github.com/itchyny/gojq/cmd/gojq" 23 | _ "github.com/wadey/gocovmerge" 24 | _ "golang.org/x/tools/cmd/stringer" 25 | _ "golang.org/x/tools/go/analysis/passes/fieldalignment/cmd/fieldalignment" 26 | _ "golang.org/x/vuln/cmd/govulncheck" 27 | _ "google.golang.org/protobuf/cmd/protoc-gen-go" 28 | ) 29 | -------------------------------------------------------------------------------- /verify_examples.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2020 Google LLC 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -euo pipefail 18 | 19 | cd $(dirname $0) 20 | TOOLS_DIR=$(pwd)/.tools 21 | 22 | # Pre-requisites 23 | if ! git diff --quiet; then \ 24 | git status 25 | printf "\n\nError: working tree is not clean\n" 26 | exit -1 27 | fi 28 | 29 | if [ "$(git tag --contains $(git log -1 --pretty=format:"%H"))" = "" ] ; then 30 | printf "$(git log -1)" 31 | printf "\n\nError: HEAD is not pointing to a tagged version" 32 | fi 33 | 34 | make ${TOOLS_DIR}/gojq 35 | 36 | DIR_TMP="$(mktemp -d -t otelops-XXXX)" 37 | 38 | printf "Copy examples to ${DIR_TMP}\n" 39 | cp -a ./example ${DIR_TMP} 40 | 41 | # Update go.mod files 42 | printf "Update go.mod: rename module and remove replace\n" 43 | 44 | PACKAGE_DIRS=$(find . -mindepth 2 -type f -name 'go.mod' -exec dirname {} \; | grep -E 'example' | sed 's/^\.\///' | sort) 45 | 46 | for dir in $PACKAGE_DIRS; do 47 | printf " Update go.mod for $dir\n" 48 | (cd "${DIR_TMP}/${dir}" && \ 49 | # replaces is ("mod1" "mod2" …) 50 | replaces=($(go mod edit -json | ${TOOLS_DIR}/gojq '.Replace[].Old.Path')) && \ 51 | # strip double quotes 52 | replaces=("${replaces[@]%\"}") && \ 53 | replaces=("${replaces[@]#\"}") && \ 54 | # make an array (-dropreplace=mod1 -dropreplace=mod2 …) 55 | dropreplaces=("${replaces[@]/#/-dropreplace=}") && \ 56 | go mod edit -module "oteltmp/${dir}" "${dropreplaces[@]}" && \ 57 | go mod tidy) 58 | done 59 | printf "Update done:\n\n" 60 | 61 | # Build directories that contain main package. These directories are different than 62 | # directories that contain go.mod files. 63 | printf "Build examples:\n" 64 | EXAMPLES=$(./get_main_pkgs.sh ./example) 65 | for ex in $EXAMPLES; do 66 | printf " Build $ex in ${DIR_TMP}/${ex}\n" 67 | (cd "${DIR_TMP}/${ex}" && \ 68 | go build .) 69 | done 70 | 71 | # Cleanup 72 | printf "Remove copied files.\n" 73 | rm -rf $DIR_TMP 74 | --------------------------------------------------------------------------------