├── .dockerignore
├── .flake8
├── .github
├── CODEOWNERS
├── header-checker-lint.yml
├── snippet-bot.yml
└── workflows
│ ├── ci.yaml
│ └── codeql-analysis.yml
├── .gitignore
├── .isort.cfg
├── .pylintrc
├── .readthedocs.yml
├── LICENSE
├── README.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
├── dev-constraints.txt
├── docs-requirements.txt
├── docs
├── Makefile
├── _static
│ └── .gitkeep
├── _templates
│ ├── custom-class-template.rst
│ └── custom-module-template.rst
├── apireference.rst
├── cloud_monitoring
│ └── cloud_monitoring.rst
├── cloud_trace
│ ├── cloud_trace.rst
│ └── cloud_trace_propagator.rst
├── code-of-conduct.md
├── conf.py
├── contributing.md
├── examples
│ ├── cloud_monitoring
│ │ ├── README.rst
│ │ ├── basic_metrics.py
│ │ ├── requirements.in
│ │ └── requirements.txt
│ ├── cloud_resource_detector
│ │ ├── README.rst
│ │ ├── requirements.in
│ │ ├── requirements.txt
│ │ ├── resource_detector_metrics.py
│ │ └── resource_detector_trace.py
│ ├── cloud_trace_exporter
│ │ ├── README.rst
│ │ ├── advanced_trace.py
│ │ ├── basic_trace.py
│ │ ├── requirements.in
│ │ └── requirements.txt
│ ├── cloud_trace_propagator
│ │ ├── README.rst
│ │ ├── client.py
│ │ ├── requirements.in
│ │ ├── requirements.txt
│ │ └── server.py
│ ├── flask_e2e
│ │ ├── README.rst
│ │ ├── client.py
│ │ ├── gcm_latency.png
│ │ ├── gct_result.png
│ │ ├── metrics_explorer.png
│ │ ├── requirements.in
│ │ ├── requirements.txt
│ │ └── server.py
│ └── prometheus_exemplars
│ │ ├── README.rst
│ │ ├── docker-compose.yaml
│ │ ├── heatmap.png
│ │ ├── hey.dockerfile
│ │ ├── otel-collector-config.yaml
│ │ ├── requirements.in
│ │ ├── requirements.txt
│ │ ├── select_metric.png
│ │ ├── server.dockerfile
│ │ ├── server.py
│ │ └── trace_details.png
├── index.rst
├── make.bat
└── releasing.md
├── e2e-test-server
├── Dockerfile
├── constraints.txt
├── e2e_test_server
│ ├── constants.py
│ ├── scenarios.py
│ ├── server.py
│ └── types.py
├── main.py
├── requirements-dockerfile.txt
├── requirements-shared.txt
├── requirements.txt
└── wait-for-image.sh
├── get_mock_server.sh
├── opentelemetry-exporter-gcp-logging
├── CHANGELOG.md
├── LICENSE
├── MANIFEST.in
├── README.rst
├── mypy.ini
├── setup.cfg
├── setup.py
├── src
│ └── opentelemetry
│ │ └── exporter
│ │ └── cloud_logging
│ │ ├── __init__.py
│ │ ├── environment_variables.py
│ │ └── version.py
└── tests
│ ├── __snapshots__
│ └── test_cloud_logging
│ │ ├── test_convert_non_json_dict_bytes.json
│ │ ├── test_convert_otlp_dict_body.json
│ │ ├── test_convert_otlp_various_different_types_in_attrs_and_bytes_body.json
│ │ ├── test_convert_various_types_of_bodies[bool].json
│ │ └── test_convert_various_types_of_bodies[str].json
│ ├── conftest.py
│ ├── fixtures
│ ├── cloud_logging_fake.py
│ └── snapshot_logging_calls.py
│ └── test_cloud_logging.py
├── opentelemetry-exporter-gcp-monitoring
├── CHANGELOG.md
├── LICENSE
├── MANIFEST.in
├── README.rst
├── mypy.ini
├── setup.cfg
├── setup.py
├── src
│ └── opentelemetry
│ │ ├── exporter
│ │ └── cloud_monitoring
│ │ │ ├── __init__.py
│ │ │ ├── environment_variables.py
│ │ │ └── version.py
│ │ └── py.typed
└── tests
│ ├── __snapshots__
│ └── test_cloud_monitoring
│ │ ├── test_counter[float].json
│ │ ├── test_counter[int].json
│ │ ├── test_histogram_default_buckets.json
│ │ ├── test_histogram_single_bucket.json
│ │ ├── test_invalid_label_keys.json
│ │ ├── test_observable_counter[float].json
│ │ ├── test_observable_counter[int].json
│ │ ├── test_observable_gauge[float].json
│ │ ├── test_observable_gauge[int].json
│ │ ├── test_observable_updowncounter[float].json
│ │ ├── test_observable_updowncounter[int].json
│ │ ├── test_up_down_counter[float].json
│ │ ├── test_up_down_counter[int].json
│ │ └── test_with_resource.json
│ ├── conftest.py
│ ├── fixtures
│ ├── gcmfake.py
│ └── snapshot_gcmcalls.py
│ ├── test_cloud_monitoring.py
│ ├── test_cloud_monitoring_auto_instrument.py
│ ├── test_normalize_label_key.py
│ └── test_user_agent.py
├── opentelemetry-exporter-gcp-trace
├── CHANGELOG.md
├── LICENSE
├── MANIFEST.in
├── README.rst
├── mypy.ini
├── setup.cfg
├── setup.py
├── src
│ └── opentelemetry
│ │ ├── exporter
│ │ └── cloud_trace
│ │ │ ├── __init__.py
│ │ │ ├── environment_variables.py
│ │ │ └── version.py
│ │ └── py.typed
└── tests
│ ├── test_cloud_trace_auto_instrument.py
│ ├── test_cloud_trace_exporter.py
│ └── test_integration_cloud_trace_exporter.py
├── opentelemetry-propagator-gcp
├── CHANGELOG.md
├── LICENSE
├── MANIFEST.in
├── README.rst
├── mypy.ini
├── setup.cfg
├── setup.py
├── src
│ └── opentelemetry
│ │ ├── propagators
│ │ └── cloud_trace_propagator
│ │ │ ├── __init__.py
│ │ │ └── version.py
│ │ └── py.typed
└── tests
│ ├── test_cloud_trace_propagator.py
│ └── test_cloud_trace_propagator_auto_instrument.py
├── opentelemetry-resourcedetector-gcp
├── CHANGELOG.md
├── LICENSE
├── MANIFEST.in
├── README.rst
├── mypy.ini
├── setup.cfg
├── setup.py
├── src
│ └── opentelemetry
│ │ ├── py.typed
│ │ └── resourcedetector
│ │ └── gcp_resource_detector
│ │ ├── __init__.py
│ │ ├── _constants.py
│ │ ├── _detector.py
│ │ ├── _faas.py
│ │ ├── _gae.py
│ │ ├── _gce.py
│ │ ├── _gke.py
│ │ ├── _mapping.py
│ │ ├── _metadata.py
│ │ └── version.py
└── tests
│ ├── __snapshots__
│ ├── test_detector.ambr
│ └── test_mapping.ambr
│ ├── conftest.py
│ ├── test_detector.py
│ ├── test_faas.py
│ ├── test_gae.py
│ ├── test_gce.py
│ ├── test_gcp_resource_detector.py
│ ├── test_gke.py
│ └── test_mapping.py
├── pyproject.toml
├── release.py
├── samples
├── instrumentation-quickstart
│ ├── .dockerignore
│ ├── Dockerfile
│ ├── README.md
│ ├── app.py
│ ├── cloudbuild-integration.yaml
│ ├── docker-compose.cloudbuild.yaml
│ ├── docker-compose.creds.yaml
│ ├── docker-compose.yaml
│ ├── gcp_logging.py
│ ├── integrationtest
│ │ ├── go.mod
│ │ ├── go.sum
│ │ └── quickstart_test.go
│ ├── otel-collector-config.yaml
│ ├── pyproject.toml
│ ├── setup_opentelemetry.py
│ └── uv.lock
├── langgraph-sql-agent
│ ├── .python-version
│ ├── README.md
│ ├── agent.py
│ ├── main.py
│ ├── patched_vertexai.py
│ ├── pyproject.toml
│ ├── requirements.txt
│ ├── utils.py
│ └── uv.lock
├── otlpmetric
│ ├── README.md
│ ├── example.py
│ └── requirements.txt
└── otlptrace
│ ├── README.md
│ ├── example_grpc.py
│ ├── example_http.py
│ └── requirements.txt
├── test-common
├── MANIFEST.in
├── setup.cfg
├── setup.py
└── src
│ └── test_common
│ ├── __init__.py
│ └── base_exporter_integration_test.py
└── tox.ini
/.dockerignore:
--------------------------------------------------------------------------------
1 | .git
2 | docs/
3 | .tox
4 | **/venv/
5 | .mypy_cache/
6 | **/__pycache__/
7 | e2e-test-server/wheels/
8 |
--------------------------------------------------------------------------------
/.flake8:
--------------------------------------------------------------------------------
1 | [flake8]
2 | ignore =
3 | E501 # line too long, defer to black
4 | F401 # unused import, defer to pylint
5 | W503 # allow line breaks before binary ops
6 | W504 # allow line breaks after binary ops
7 | E203 # allow whitespace before ':' (https://github.com/psf/black#slices)
8 | exclude =
9 | .git
10 | .tox
11 | CVS
12 | .venv*/
13 | *venv*/
14 | target
15 | __pycache__
16 |
--------------------------------------------------------------------------------
/.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 | allowedLicenses:
2 | - Apache-2.0
3 | allowedCopyrightHolders:
4 | - Google LLC
5 | - The OpenTelemetry Authors
6 | sourceFileExtensions:
7 | - py
8 | - sh
9 |
--------------------------------------------------------------------------------
/.github/snippet-bot.yml:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GoogleCloudPlatform/opentelemetry-operations-python/54cb8a6db1f707ecc639e11c0a0d808deca6ac9e/.github/snippet-bot.yml
--------------------------------------------------------------------------------
/.github/workflows/ci.yaml:
--------------------------------------------------------------------------------
1 | on:
2 | push:
3 | branches: [main]
4 | pull_request:
5 | name: ci
6 | env:
7 | # Bump this to invalidate all caches
8 | cache-version: 1
9 |
10 | jobs:
11 | test:
12 | runs-on: ubuntu-22.04
13 | strategy:
14 | matrix:
15 | py:
16 | - { version: "3.8", tox: "38" }
17 | - { version: "3.9", tox: "39" }
18 | - { version: "3.10", tox: "310" }
19 | - { version: "3.11", tox: "311" }
20 | - { version: "3.12", tox: "312" }
21 | - { version: "3.13", tox: "313" }
22 | env:
23 | run-matrix-combo: ${{ matrix.py.version }}
24 |
25 | name: Test ${{ matrix.py.version }}
26 | steps:
27 | - uses: actions/checkout@v3
28 | - name: Set up Python ${{ matrix.py.version }}
29 | uses: actions/setup-python@v4
30 | with:
31 | python-version: ${{ matrix.py.version }}
32 | - uses: actions/cache@v3
33 | with:
34 | path: ~/.cache/pip
35 | key: ${{ env.cache-version }}-${{ env.run-matrix-combo }}-pip-${{ hashFiles('tox.ini', 'dev-constraints.txt') }}
36 | restore-keys: |
37 | ${{ env.cache-version }}-${{ env.run-matrix-combo }}-pip
38 | - name: Install tox
39 | run: pip install -U tox
40 | - name: Run tox test factors for python ${{ matrix.py.version }}
41 | run: >
42 | tox
43 | --skip-missing-interpreters=true
44 | -f py${{ matrix.py.tox }}-ci
45 |
46 | lint:
47 | runs-on: ubuntu-22.04
48 | strategy:
49 | matrix:
50 | target: [lint-ci, docs-ci, mypy-ci]
51 | py:
52 | - { version: "3.10" }
53 |
54 | env:
55 | run-matrix-combo: ${{ matrix.py.version }}-${{ matrix.target }}
56 |
57 | name: ${{ matrix.target }}
58 | steps:
59 | - uses: actions/checkout@v3
60 | - name: Set up Python ${{ matrix.py.version }}
61 | uses: actions/setup-python@v4
62 | with:
63 | python-version: ${{ matrix.py.version }}
64 | - uses: actions/cache@v3
65 | with:
66 | path: ~/.cache/pip
67 | key: ${{ env.cache-version }}-${{ env.run-matrix-combo }}-pip-${{ hashFiles('tox.ini', 'dev-constraints.txt') }}
68 | restore-keys: |
69 | ${{ env.cache-version }}-${{ env.run-matrix-combo }}-pip
70 | - name: Install tox
71 | run: pip install -U tox
72 | - name: Run tox factors ${{ matrix.target }}
73 | run: tox -f ${{ matrix.target }}
74 |
--------------------------------------------------------------------------------
/.github/workflows/codeql-analysis.yml:
--------------------------------------------------------------------------------
1 | name: "CodeQL Analysis"
2 |
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@v2
31 | with:
32 | languages: python
33 |
34 | - name: Autobuild
35 | uses: github/codeql-action/autobuild@v2
36 |
37 | - name: Perform CodeQL Analysis
38 | uses: github/codeql-action/analyze@v2
39 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | share/python-wheels/
24 | *.egg-info/
25 | .installed.cfg
26 | *.egg
27 | MANIFEST
28 |
29 | # PyInstaller
30 | # Usually these files are written by a python script from a template
31 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
32 | *.manifest
33 | *.spec
34 |
35 | # Installer logs
36 | pip-log.txt
37 | pip-delete-this-directory.txt
38 |
39 | # Unit test / coverage reports
40 | htmlcov/
41 | .tox/
42 | .nox/
43 | .coverage
44 | .coverage.*
45 | .cache
46 | nosetests.xml
47 | coverage.xml
48 | *.cover
49 | *.py,cover
50 | .hypothesis/
51 | .pytest_cache/
52 | cover/
53 |
54 | # Outputting junit xmls to here
55 | .test-results/
56 |
57 | # Translations
58 | *.mo
59 | *.pot
60 |
61 | # Django stuff:
62 | *.log
63 | local_settings.py
64 | db.sqlite3
65 | db.sqlite3-journal
66 |
67 | # Flask stuff:
68 | instance/
69 | .webassets-cache
70 |
71 | # Scrapy stuff:
72 | .scrapy
73 |
74 | # Sphinx documentation
75 | docs/_build/
76 |
77 | # PyBuilder
78 | .pybuilder/
79 | target/
80 |
81 | # Jupyter Notebook
82 | .ipynb_checkpoints
83 |
84 | # IPython
85 | profile_default/
86 | ipython_config.py
87 |
88 | # pyenv
89 | # For a library or package, you might want to ignore these files since the code is
90 | # intended to run in multiple environments; otherwise, check them in:
91 | # .python-version
92 |
93 | # pipenv
94 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
95 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
96 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
97 | # install all needed dependencies.
98 | #Pipfile.lock
99 |
100 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow
101 | __pypackages__/
102 |
103 | # Celery stuff
104 | celerybeat-schedule
105 | celerybeat.pid
106 |
107 | # SageMath parsed files
108 | *.sage.py
109 |
110 | # Environments
111 | .env
112 | .venv
113 | env/
114 | venv/
115 | ENV/
116 | env.bak/
117 | venv.bak/
118 | myproject/
119 |
120 | # Spyder project settings
121 | .spyderproject
122 | .spyproject
123 |
124 | # Rope project settings
125 | .ropeproject
126 |
127 | # mkdocs documentation
128 | /site
129 |
130 | # mypy
131 | .mypy_cache/
132 | .dmypy.json
133 | dmypy.json
134 |
135 | # Pyre type checker
136 | .pyre/
137 |
138 | # pytype static type analyzer
139 | .pytype/
140 |
141 | # Cython debug symbols
142 | cython_debug/
143 |
144 | .vscode/
145 |
146 | # Sphinx
147 | _build/
148 | _autosummary/
149 |
--------------------------------------------------------------------------------
/.isort.cfg:
--------------------------------------------------------------------------------
1 | [settings]
2 | profile=black
3 | line_length=79
4 | multi_line_output=3
5 | skip=target
6 | skip_glob=**/gen/*,**/venv/*,**/proto/*,.tox
7 |
--------------------------------------------------------------------------------
/.readthedocs.yml:
--------------------------------------------------------------------------------
1 | # Read the Docs configuration file
2 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
3 | version: 2
4 |
5 | sphinx:
6 | configuration: docs/conf.py
7 |
8 | build:
9 | os: ubuntu-22.04
10 | tools:
11 | python: "3.10"
12 |
13 | python:
14 | install:
15 | - requirements: docs-requirements.txt
16 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Open-Telemetry Operations Exporters for Python
2 |
3 | [](https://google-cloud-opentelemetry.readthedocs.io/en/latest/?badge=latest)
4 |
5 |
6 | This repo provides OpenTelemetry Python exporters, propagators, and resource detectors
7 | for Google Cloud Platform.
8 |
9 | To get started with instrumentation in Google Cloud, see [Generate traces and metrics with
10 | Python](https://cloud.google.com/stackdriver/docs/instrumentation/setup/python).
11 |
12 | ## Documentation
13 |
14 | To learn more about instrumentation and observability, including opinionated recommendations
15 | for Google Cloud Observability, visit [Instrumentation and
16 | observability](https://cloud.google.com/stackdriver/docs/instrumentation/overview).
17 |
18 | API docs and additional examples are available at
19 |
20 | ## Installation
21 |
22 | All packages are [available on PyPI](https://pypi.org/user/google_opentelemetry/) for installation with `pip`.
23 |
24 | ## Contributing
25 |
26 | See the [contributing guide](docs/contributing.md).
27 |
--------------------------------------------------------------------------------
/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 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 | steps:
16 | # Build function source zip with vendored wheels of packages in this monorepo
17 | - name: python:3.11-slim
18 | id: build
19 | script: |
20 | set -xe
21 | apt-get update
22 | apt-get install -y zip
23 |
24 | cd e2e-test-server/
25 | # package monorepo libraries into wheels in local wheels/ directory
26 | pip wheel \
27 | --no-deps \
28 | --wheel-dir wheels \
29 | ../opentelemetry-exporter-gcp-trace/ \
30 | ../opentelemetry-resourcedetector-gcp/ \
31 | ../opentelemetry-propagator-gcp
32 |
33 | zip -qr function-source.zip .
34 |
35 | # Run the test
36 | - name: $_TEST_RUNNER_IMAGE
37 | id: run-tests-cloud-run
38 | dir: /
39 | env: ["PROJECT_ID=$PROJECT_ID"]
40 | args:
41 | - cloud-functions-gen2
42 | - --functionsource=/workspace/e2e-test-server/function-source.zip
43 | - --runtime=python311
44 | - --entrypoint=cloud_functions_handler
45 |
46 | logsBucket: gs://opentelemetry-ops-e2e-cloud-build-logs
47 | substitutions:
48 | _TEST_RUNNER_IMAGE: us-central1-docker.pkg.dev/${PROJECT_ID}/e2e-testing/opentelemetry-operations-e2e-testing:0.20.1
49 |
--------------------------------------------------------------------------------
/cloudbuild-e2e-cloud-run.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-cloud-run
27 | dir: /
28 | env: ["PROJECT_ID=$PROJECT_ID"]
29 | args:
30 | - cloud-run
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-python-e2e-test-server:${SHORT_SHA}
37 |
--------------------------------------------------------------------------------
/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 | # 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 | steps:
16 | # Build function source zip with vendored wheels of packages in this monorepo
17 | - name: python:3.11-slim
18 | id: build
19 | script: |
20 | set -xe
21 | apt-get update
22 | apt-get install -y zip
23 |
24 | cd e2e-test-server/
25 | # package monorepo libraries into wheels in local wheels/ directory
26 | pip wheel \
27 | --no-deps \
28 | --wheel-dir wheels \
29 | ../opentelemetry-exporter-gcp-trace/ \
30 | ../opentelemetry-resourcedetector-gcp/ \
31 | ../opentelemetry-propagator-gcp
32 |
33 | zip -qr appsource.zip .
34 |
35 | # Run the test
36 | - name: $_TEST_RUNNER_IMAGE
37 | id: run-tests-gae-standard
38 | dir: /
39 | env: ["PROJECT_ID=$PROJECT_ID"]
40 | args:
41 | - gae-standard
42 | - --runtime=python311
43 | - --entrypoint=python main.py
44 | - --appsource=/workspace/e2e-test-server/appsource.zip
45 |
46 | logsBucket: gs://opentelemetry-ops-e2e-cloud-build-logs
47 | substitutions:
48 | _TEST_RUNNER_IMAGE: us-central1-docker.pkg.dev/${PROJECT_ID}/e2e-testing/opentelemetry-operations-e2e-testing:0.20.1
49 |
--------------------------------------------------------------------------------
/cloudbuild-e2e-gae.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 | # 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 | steps:
16 | # Wait for the image to exist
17 | - name: "docker"
18 | id: wait-for-image
19 | entrypoint: "sh"
20 | timeout: 10m
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=python
34 |
35 | logsBucket: gs://opentelemetry-ops-e2e-cloud-build-logs
36 | timeout: 20m
37 | substitutions:
38 | _TEST_RUNNER_IMAGE: us-central1-docker.pkg.dev/${PROJECT_ID}/e2e-testing/opentelemetry-operations-e2e-testing:0.20.1
39 | _TEST_SERVER_IMAGE: us-central1-docker.pkg.dev/${PROJECT_ID}/e2e-testing/opentelemetry-operations-python-e2e-test-server:${SHORT_SHA}
40 |
--------------------------------------------------------------------------------
/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 | - --health-check-timeout=5m
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-python-e2e-test-server:${SHORT_SHA}
39 |
--------------------------------------------------------------------------------
/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-python-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 |
26 | docker build --tag=${_TEST_SERVER_IMAGE} --file=e2e-test-server/Dockerfile .
27 | docker push ${_TEST_SERVER_IMAGE}
28 |
29 | logsBucket: gs://opentelemetry-ops-e2e-cloud-build-logs
30 | substitutions:
31 | _TEST_SERVER_IMAGE: us-central1-docker.pkg.dev/${PROJECT_ID}/e2e-testing/opentelemetry-operations-python-e2e-test-server:${SHORT_SHA}
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-python-e2e-test-server:${SHORT_SHA}
45 |
--------------------------------------------------------------------------------
/dev-constraints.txt:
--------------------------------------------------------------------------------
1 | black==22.3.0
2 | flake8==3.9.2
3 | # 3rd party package until https://github.com/googleapis/python-api-common-protos/issues/135 is
4 | # fixed
5 | googleapis-common-protos-stubs==2.1.0
6 | isort==5.8.0
7 | mypy-extensions==0.4.3
8 | mypy==0.982
9 | pylint==2.8.3
10 | Sphinx==7.2.6
11 | syrupy==3.0.4
12 | types-protobuf==3.20.4.2
13 | types-requests==2.28.11.2
14 | types-setuptools==65.5.0.2
15 | types-urllib3==1.26.25.1
16 | setuptools==69.5.1
17 |
18 | # pinned for snapshot tests. this should be bumped regularly and snapshots updated by running
19 | # tox -f py311-test -- --snapshot-update
20 | opentelemetry-api==1.30.0
21 | opentelemetry-sdk==1.30.0
22 |
--------------------------------------------------------------------------------
/docs-requirements.txt:
--------------------------------------------------------------------------------
1 | -c dev-constraints.txt
2 | Sphinx
3 | sphinx-autodoc-typehints
4 | -e ./opentelemetry-exporter-gcp-trace
5 | -e ./opentelemetry-exporter-gcp-monitoring
6 | -e ./opentelemetry-propagator-gcp
7 | -e ./opentelemetry-resourcedetector-gcp
8 |
--------------------------------------------------------------------------------
/docs/Makefile:
--------------------------------------------------------------------------------
1 | # Minimal makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line, and also
5 | # from the environment for the first two.
6 | SPHINXOPTS ?=
7 | SPHINXBUILD ?= sphinx-build
8 | SOURCEDIR = .
9 | BUILDDIR = _build
10 |
11 | # Put it first so that "make" without argument is like "make help".
12 | help:
13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
14 |
15 | .PHONY: help Makefile
16 |
17 | # Catch-all target: route all unknown targets to Sphinx using the new
18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
19 | %: Makefile
20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
21 |
--------------------------------------------------------------------------------
/docs/_static/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GoogleCloudPlatform/opentelemetry-operations-python/54cb8a6db1f707ecc639e11c0a0d808deca6ac9e/docs/_static/.gitkeep
--------------------------------------------------------------------------------
/docs/_templates/custom-class-template.rst:
--------------------------------------------------------------------------------
1 | {{ fullname | escape | underline}}
2 |
3 | .. currentmodule:: {{ module }}
4 |
5 | .. autoclass:: {{ objname }}
6 | :members:
7 | :show-inheritance:
8 | :inherited-members:
9 | :special-members: __call__, __add__, __mul__
10 |
11 | {% block methods %}
12 | {% if methods %}
13 | .. rubric:: {{ _('Methods') }}
14 |
15 | .. autosummary::
16 | :nosignatures:
17 | {% for item in methods %}
18 | {%- if not item.startswith('_') %}
19 | ~{{ name }}.{{ item }}
20 | {%- endif -%}
21 | {%- endfor %}
22 | {% endif %}
23 | {% endblock %}
24 |
25 | {% block attributes %}
26 | {% if attributes %}
27 | .. rubric:: {{ _('Attributes') }}
28 |
29 | .. autosummary::
30 | {% for item in attributes %}
31 | ~{{ name }}.{{ item }}
32 | {%- endfor %}
33 | {% endif %}
34 | {% endblock %}
35 |
--------------------------------------------------------------------------------
/docs/_templates/custom-module-template.rst:
--------------------------------------------------------------------------------
1 | {{ fullname | escape | underline}}
2 |
3 | .. automodule:: {{ fullname }}
4 |
5 | {% block attributes %}
6 | {% if attributes %}
7 | .. rubric:: Module attributes
8 |
9 | .. autosummary::
10 | :toctree:
11 | {% for item in attributes %}
12 | {{ item }}
13 | {%- endfor %}
14 | {% endif %}
15 | {% endblock %}
16 |
17 | {% block functions %}
18 | {% if functions %}
19 | .. rubric:: {{ _('Functions') }}
20 |
21 | .. autosummary::
22 | :toctree:
23 | :nosignatures:
24 | {% for item in functions %}
25 | {{ item }}
26 | {%- endfor %}
27 | {% endif %}
28 | {% endblock %}
29 |
30 | {% block classes %}
31 | {% if classes %}
32 | .. rubric:: {{ _('Classes') }}
33 |
34 | .. autosummary::
35 | :toctree:
36 | :template: custom-class-template.rst
37 | :nosignatures:
38 | {% for item in classes %}
39 | {{ item }}
40 | {%- endfor %}
41 | {% endif %}
42 | {% endblock %}
43 |
44 | {% block exceptions %}
45 | {% if exceptions %}
46 | .. rubric:: {{ _('Exceptions') }}
47 |
48 | .. autosummary::
49 | :toctree:
50 | {% for item in exceptions %}
51 | {{ item }}
52 | {%- endfor %}
53 | {% endif %}
54 | {% endblock %}
55 |
56 | {% block modules %}
57 | {% if modules %}
58 | .. autosummary::
59 | :toctree:
60 | :template: custom-module-template.rst
61 | :recursive:
62 | {% for item in modules %}
63 | {{ item }}
64 | {%- endfor %}
65 | {% endif %}
66 | {% endblock %}
67 |
--------------------------------------------------------------------------------
/docs/apireference.rst:
--------------------------------------------------------------------------------
1 | API Reference
2 | =============
3 |
4 | ..
5 | The above .. prevents the autosummary table from rendering in the
6 | document, but still causes the recursive generation of autodoc stub files.
7 |
8 | .. autosummary::
9 | :toctree: _autosummary
10 | :caption: API Reference
11 | :template: custom-module-template.rst
12 | :recursive:
13 |
14 | opentelemetry.exporter
15 | opentelemetry.propagators.cloud_trace_propagator
16 | opentelemetry.resourcedetector
17 |
18 |
19 | .. toctree::
20 | :maxdepth: 5
21 | :caption: API Reference
22 | :name: apireference
23 |
24 | _autosummary/opentelemetry.exporter
25 | _autosummary/opentelemetry.propagators.cloud_trace_propagator
26 | _autosummary/opentelemetry.resourcedetector
27 |
--------------------------------------------------------------------------------
/docs/cloud_monitoring/cloud_monitoring.rst:
--------------------------------------------------------------------------------
1 | OpenTelemetry Cloud Monitoring Exporter
2 | =======================================
3 |
4 | .. image:: https://badge.fury.io/py/opentelemetry-exporter-gcp-monitoring.svg
5 | :target: https://badge.fury.io/py/opentelemetry-exporter-gcp-monitoring
6 |
7 | .. automodule:: opentelemetry.exporter.cloud_monitoring
8 | :members:
9 | :undoc-members:
10 | :show-inheritance:
11 | :noindex:
12 |
--------------------------------------------------------------------------------
/docs/cloud_trace/cloud_trace.rst:
--------------------------------------------------------------------------------
1 | OpenTelemetry Cloud Trace Exporter
2 | ==================================
3 |
4 | .. image:: https://badge.fury.io/py/opentelemetry-exporter-gcp-trace.svg
5 | :target: https://badge.fury.io/py/opentelemetry-exporter-gcp-trace
6 |
7 | .. automodule:: opentelemetry.exporter.cloud_trace
8 | :members:
9 | :undoc-members:
10 | :show-inheritance:
11 | :noindex:
12 |
--------------------------------------------------------------------------------
/docs/cloud_trace/cloud_trace_propagator.rst:
--------------------------------------------------------------------------------
1 | OpenTelemetry Cloud Trace Propagator
2 | ==================================
3 |
4 | .. image:: https://badge.fury.io/py/opentelemetry-propagator-gcp.svg
5 | :target: https://badge.fury.io/py/opentelemetry-propagator-gcp
6 |
7 | .. automodule:: opentelemetry.propagators.cloud_trace_propagator
8 | :members:
9 | :undoc-members:
10 | :show-inheritance:
11 | :noindex:
12 |
--------------------------------------------------------------------------------
/docs/examples/cloud_monitoring/README.rst:
--------------------------------------------------------------------------------
1 | Cloud Monitoring Exporter Example
2 | =================================
3 |
4 | These examples show how to use OpenTelemetry to send metrics data to Cloud Monitoring.
5 |
6 |
7 | Basic Example
8 | -------------
9 |
10 | To use this exporter you first need to:
11 |
12 | * `Create a Google Cloud project `_.
13 | * Set up `Application Default Credentials
14 | `_ by `installing
15 | gcloud `_ and running ``gcloud auth
16 | application-default login``.
17 |
18 | * Installation
19 |
20 | .. code-block:: sh
21 |
22 | pip install opentelemetry-exporter-gcp-monitoring \
23 | opentelemetry-api \
24 | opentelemetry-sdk
25 |
26 | * Run example code
27 |
28 | .. literalinclude:: basic_metrics.py
29 | :language: python
30 | :lines: 1-
31 |
32 | Viewing Output
33 | --------------------------
34 |
35 | After running the example:
36 |
37 | * Go to the `Cloud Monitoring Metrics Explorer page `_.
38 | * In "Select a Metric" enter "workload.googleapis.com/request_counter".
39 | * You can filter by labels and change the graphical output here as well.
40 |
41 | Troubleshooting
42 | --------------------------
43 |
44 | ``One or more points were written more frequently than the maximum sampling period configured for the metric``
45 | ##############################################################################################################
46 |
47 | Currently, Cloud Monitoring allows one write every 5 seconds for any unique tuple (metric_name, metric_label_value_1, metric_label_value_2, ...). The exporter should rate limit on its own but issues arise if:
48 |
49 | * You are restarting the server more than once every 5 seconds.
50 | * You have a multiple exporters (possibly on different threads) writing to the same tuple.
51 |
52 | For both cases, you can pass ``add_unique_identifier=True`` to the CloudMonitoringMetricsExporter constructor. This adds a UUID label_value, making the tuple unique again. For the first case, you can also choose to just wait longer than 5 seconds between restarts.
53 |
--------------------------------------------------------------------------------
/docs/examples/cloud_monitoring/basic_metrics.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # Copyright 2021 The OpenTelemetry Authors
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 | import time
17 |
18 | from opentelemetry import metrics
19 | from opentelemetry.exporter.cloud_monitoring import (
20 | CloudMonitoringMetricsExporter,
21 | )
22 | from opentelemetry.sdk.metrics import MeterProvider
23 | from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
24 | from opentelemetry.sdk.resources import Resource
25 |
26 | metrics.set_meter_provider(
27 | MeterProvider(
28 | metric_readers=[
29 | PeriodicExportingMetricReader(
30 | CloudMonitoringMetricsExporter(), export_interval_millis=5000
31 | )
32 | ],
33 | resource=Resource.create(
34 | {
35 | "service.name": "basic_metrics",
36 | "service.namespace": "examples",
37 | "service.instance.id": "instance123",
38 | }
39 | ),
40 | )
41 | )
42 | meter = metrics.get_meter(__name__)
43 |
44 | # Creates metric workload.googleapis.com/request_counter with monitored resource generic_task
45 | requests_counter = meter.create_counter(
46 | name="request_counter",
47 | description="number of requests",
48 | unit="1",
49 | )
50 |
51 | staging_labels = {"environment": "staging"}
52 |
53 | for i in range(20):
54 | requests_counter.add(25, staging_labels)
55 | time.sleep(5)
56 |
--------------------------------------------------------------------------------
/docs/examples/cloud_monitoring/requirements.in:
--------------------------------------------------------------------------------
1 | -e ../../../opentelemetry-exporter-gcp-monitoring
2 | -e ../../../opentelemetry-resourcedetector-gcp
3 | opentelemetry-api
4 | opentelemetry-sdk
5 |
--------------------------------------------------------------------------------
/docs/examples/cloud_monitoring/requirements.txt:
--------------------------------------------------------------------------------
1 | #
2 | # This file is autogenerated by pip-compile with Python 3.11
3 | # by the following command:
4 | #
5 | # pip-compile --output-file=requirements.txt requirements.in
6 | #
7 | -e file:///usr/local/google/home/aaronabbott/repo/opentelemetry-operations-python/opentelemetry-exporter-gcp-monitoring
8 | # via -r requirements.in
9 | -e file:///usr/local/google/home/aaronabbott/repo/opentelemetry-operations-python/opentelemetry-resourcedetector-gcp
10 | # via
11 | # -r requirements.in
12 | # opentelemetry-exporter-gcp-monitoring
13 | cachetools==5.4.0
14 | # via google-auth
15 | certifi==2024.7.4
16 | # via requests
17 | charset-normalizer==3.3.2
18 | # via requests
19 | deprecated==1.2.14
20 | # via opentelemetry-api
21 | google-api-core[grpc]==2.19.1
22 | # via google-cloud-monitoring
23 | google-auth==2.32.0
24 | # via
25 | # google-api-core
26 | # google-cloud-monitoring
27 | google-cloud-monitoring==2.22.1
28 | # via opentelemetry-exporter-gcp-monitoring
29 | googleapis-common-protos==1.63.2
30 | # via
31 | # google-api-core
32 | # grpcio-status
33 | grpcio==1.64.1
34 | # via
35 | # google-api-core
36 | # grpcio-status
37 | grpcio-status==1.64.1
38 | # via google-api-core
39 | idna==3.7
40 | # via requests
41 | importlib-metadata==7.1.0
42 | # via opentelemetry-api
43 | opentelemetry-api==1.25.0
44 | # via
45 | # -r requirements.in
46 | # opentelemetry-exporter-gcp-monitoring
47 | # opentelemetry-resourcedetector-gcp
48 | # opentelemetry-sdk
49 | # opentelemetry-semantic-conventions
50 | opentelemetry-sdk==1.25.0
51 | # via
52 | # -r requirements.in
53 | # opentelemetry-exporter-gcp-monitoring
54 | # opentelemetry-resourcedetector-gcp
55 | opentelemetry-semantic-conventions==0.46b0
56 | # via opentelemetry-sdk
57 | proto-plus==1.24.0
58 | # via
59 | # google-api-core
60 | # google-cloud-monitoring
61 | protobuf==5.27.2
62 | # via
63 | # google-api-core
64 | # google-cloud-monitoring
65 | # googleapis-common-protos
66 | # grpcio-status
67 | # proto-plus
68 | pyasn1==0.6.0
69 | # via
70 | # pyasn1-modules
71 | # rsa
72 | pyasn1-modules==0.4.0
73 | # via google-auth
74 | requests==2.32.3
75 | # via
76 | # google-api-core
77 | # opentelemetry-resourcedetector-gcp
78 | rsa==4.9
79 | # via google-auth
80 | typing-extensions==4.12.2
81 | # via
82 | # opentelemetry-resourcedetector-gcp
83 | # opentelemetry-sdk
84 | urllib3==2.2.2
85 | # via requests
86 | wrapt==1.16.0
87 | # via deprecated
88 | zipp==3.19.2
89 | # via importlib-metadata
90 |
--------------------------------------------------------------------------------
/docs/examples/cloud_resource_detector/requirements.in:
--------------------------------------------------------------------------------
1 | -e ../../../opentelemetry-exporter-gcp-monitoring
2 | -e ../../../opentelemetry-exporter-gcp-trace
3 | -e ../../../opentelemetry-resourcedetector-gcp
4 | opentelemetry-api
5 | opentelemetry-sdk
6 |
--------------------------------------------------------------------------------
/docs/examples/cloud_resource_detector/resource_detector_metrics.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # Copyright 2021 The OpenTelemetry Authors
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 | import time
17 |
18 | from opentelemetry import metrics
19 | from opentelemetry.exporter.cloud_monitoring import (
20 | CloudMonitoringMetricsExporter,
21 | )
22 | from opentelemetry.sdk.metrics import MeterProvider
23 | from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
24 | from opentelemetry.sdk.resources import get_aggregated_resources
25 | from opentelemetry.resourcedetector.gcp_resource_detector import (
26 | GoogleCloudResourceDetector,
27 | )
28 |
29 | resource = get_aggregated_resources(
30 | [GoogleCloudResourceDetector(raise_on_error=True)]
31 | )
32 |
33 | meter_provider = MeterProvider(
34 | resource=resource,
35 | metric_readers=[
36 | PeriodicExportingMetricReader(
37 | CloudMonitoringMetricsExporter(), export_interval_millis=5000
38 | )
39 | ],
40 | )
41 | metrics.set_meter_provider(meter_provider)
42 | meter = metrics.get_meter(__name__)
43 |
44 | requests_counter = meter.create_counter(
45 | name="request_counter_with_resource",
46 | description="number of requests",
47 | unit="1",
48 | )
49 |
50 | staging_labels = {"environment": "staging"}
51 |
52 | for i in range(20):
53 | requests_counter.add(25, staging_labels)
54 | time.sleep(10)
55 |
--------------------------------------------------------------------------------
/docs/examples/cloud_resource_detector/resource_detector_trace.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # Copyright 2021 The OpenTelemetry Authors
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 | from opentelemetry import trace
17 | from opentelemetry.exporter.cloud_trace import CloudTraceSpanExporter
18 | from opentelemetry.sdk.resources import get_aggregated_resources
19 | from opentelemetry.sdk.trace import TracerProvider
20 | from opentelemetry.sdk.trace.export import BatchSpanProcessor
21 | from opentelemetry.resourcedetector.gcp_resource_detector import (
22 | GoogleCloudResourceDetector,
23 | )
24 |
25 | resource = get_aggregated_resources(
26 | [GoogleCloudResourceDetector(raise_on_error=True)]
27 | )
28 |
29 | # Pass the detected resources to the provider, which will in turn pass it to all
30 | # created spans
31 | trace.set_tracer_provider(TracerProvider(resource=resource))
32 |
33 | # Cloud Trace exporter will automatically format these resources and export
34 | cloud_trace_exporter = CloudTraceSpanExporter(
35 | # send all resource attributes
36 | resource_regex=r".*"
37 | )
38 | trace.get_tracer_provider().add_span_processor(
39 | BatchSpanProcessor(cloud_trace_exporter)
40 | )
41 | tracer = trace.get_tracer(__name__)
42 | with tracer.start_as_current_span("foo"):
43 | print("Hello world!")
44 |
--------------------------------------------------------------------------------
/docs/examples/cloud_trace_exporter/basic_trace.py:
--------------------------------------------------------------------------------
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 opentelemetry import trace
16 | from opentelemetry.exporter.cloud_trace import CloudTraceSpanExporter
17 | from opentelemetry.sdk.trace import TracerProvider
18 | from opentelemetry.sdk.trace.export import BatchSpanProcessor
19 |
20 | trace.set_tracer_provider(TracerProvider())
21 |
22 | cloud_trace_exporter = CloudTraceSpanExporter()
23 | trace.get_tracer_provider().add_span_processor(
24 | BatchSpanProcessor(cloud_trace_exporter)
25 | )
26 | tracer = trace.get_tracer(__name__)
27 | with tracer.start_as_current_span("foo"):
28 | print("Hello world!")
29 |
--------------------------------------------------------------------------------
/docs/examples/cloud_trace_exporter/requirements.in:
--------------------------------------------------------------------------------
1 | -e ../../../opentelemetry-exporter-gcp-trace
2 | -e ../../../opentelemetry-resourcedetector-gcp
3 | opentelemetry-api
4 | opentelemetry-sdk
5 |
--------------------------------------------------------------------------------
/docs/examples/cloud_trace_exporter/requirements.txt:
--------------------------------------------------------------------------------
1 | #
2 | # This file is autogenerated by pip-compile with Python 3.11
3 | # by the following command:
4 | #
5 | # pip-compile --output-file=requirements.txt requirements.in
6 | #
7 | -e file:///usr/local/google/home/aaronabbott/repo/opentelemetry-operations-python/opentelemetry-exporter-gcp-trace
8 | # via -r requirements.in
9 | -e file:///usr/local/google/home/aaronabbott/repo/opentelemetry-operations-python/opentelemetry-resourcedetector-gcp
10 | # via
11 | # -r requirements.in
12 | # opentelemetry-exporter-gcp-trace
13 | cachetools==5.4.0
14 | # via google-auth
15 | certifi==2024.7.4
16 | # via requests
17 | charset-normalizer==3.3.2
18 | # via requests
19 | deprecated==1.2.14
20 | # via opentelemetry-api
21 | google-api-core[grpc]==2.19.1
22 | # via google-cloud-trace
23 | google-auth==2.32.0
24 | # via
25 | # google-api-core
26 | # google-cloud-trace
27 | google-cloud-trace==1.13.4
28 | # via opentelemetry-exporter-gcp-trace
29 | googleapis-common-protos==1.63.2
30 | # via
31 | # google-api-core
32 | # grpcio-status
33 | grpcio==1.64.1
34 | # via
35 | # google-api-core
36 | # grpcio-status
37 | grpcio-status==1.64.1
38 | # via google-api-core
39 | idna==3.7
40 | # via requests
41 | importlib-metadata==7.1.0
42 | # via opentelemetry-api
43 | opentelemetry-api==1.25.0
44 | # via
45 | # -r requirements.in
46 | # opentelemetry-exporter-gcp-trace
47 | # opentelemetry-resourcedetector-gcp
48 | # opentelemetry-sdk
49 | # opentelemetry-semantic-conventions
50 | opentelemetry-sdk==1.25.0
51 | # via
52 | # -r requirements.in
53 | # opentelemetry-exporter-gcp-trace
54 | # opentelemetry-resourcedetector-gcp
55 | opentelemetry-semantic-conventions==0.46b0
56 | # via opentelemetry-sdk
57 | proto-plus==1.24.0
58 | # via
59 | # google-api-core
60 | # google-cloud-trace
61 | protobuf==5.27.2
62 | # via
63 | # google-api-core
64 | # google-cloud-trace
65 | # googleapis-common-protos
66 | # grpcio-status
67 | # proto-plus
68 | pyasn1==0.6.0
69 | # via
70 | # pyasn1-modules
71 | # rsa
72 | pyasn1-modules==0.4.0
73 | # via google-auth
74 | requests==2.32.3
75 | # via
76 | # google-api-core
77 | # opentelemetry-resourcedetector-gcp
78 | rsa==4.9
79 | # via google-auth
80 | typing-extensions==4.12.2
81 | # via
82 | # opentelemetry-resourcedetector-gcp
83 | # opentelemetry-sdk
84 | urllib3==2.2.2
85 | # via requests
86 | wrapt==1.16.0
87 | # via deprecated
88 | zipp==3.19.2
89 | # via importlib-metadata
90 |
--------------------------------------------------------------------------------
/docs/examples/cloud_trace_propagator/README.rst:
--------------------------------------------------------------------------------
1 | Cloud Trace Propagator Example
2 | ==============================
3 |
4 | These examples show how to make OpenTelemetry use the
5 | ``X-Cloud-Trace-Context`` header for context propagation.
6 |
7 |
8 | Basic Example
9 | -------------
10 |
11 | To use this feature you first need to:
12 |
13 | * Create a Google Cloud project. You can `create one here `_.
14 | * Set up `Application Default Credentials
15 | `_ by `installing
16 | gcloud `_ and running ``gcloud auth
17 | application-default login``.
18 |
19 |
20 | * Installation
21 |
22 | .. code-block:: sh
23 |
24 | pip install opentelemetry-api \
25 | opentelemetry-sdk \
26 | opentelemetry-instrumentation-flask \
27 | opentelemetry-instrumentation-requests \
28 | opentelemetry-exporter-gcp-trace \
29 | opentelemetry-propagator-gcp \
30 | Flask
31 |
32 | * Create a server that uses the Cloud Trace header
33 |
34 | .. literalinclude:: server.py
35 | :language: python
36 | :lines: 1-
37 |
38 | * Make a client that uses the Cloud Trace header
39 |
40 | .. literalinclude:: client.py
41 | :language: python
42 | :lines: 1-
43 |
44 |
45 | Checking Output
46 | --------------------------
47 |
48 | After running these examples, you can go to `Cloud Trace overview `_ to see the results.
49 |
--------------------------------------------------------------------------------
/docs/examples/cloud_trace_propagator/client.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # Copyright 2021 The OpenTelemetry Authors
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 | from opentelemetry.instrumentation.requests import RequestsInstrumentor
17 | import requests
18 | from opentelemetry import trace
19 | from opentelemetry.exporter.cloud_trace import CloudTraceSpanExporter
20 | from opentelemetry.propagate import set_global_textmap
21 | from opentelemetry.sdk.trace import TracerProvider
22 | from opentelemetry.sdk.trace.export import BatchSpanProcessor
23 | from opentelemetry.propagators.cloud_trace_propagator import (
24 | CloudTraceFormatPropagator,
25 | )
26 |
27 | # Instrumenting requests
28 | RequestsInstrumentor().instrument()
29 |
30 | # Tracer boilerplate
31 | trace.set_tracer_provider(TracerProvider())
32 | trace.get_tracer_provider().add_span_processor(
33 | BatchSpanProcessor(CloudTraceSpanExporter())
34 | )
35 |
36 | # Using the X-Cloud-Trace-Context header
37 | set_global_textmap(CloudTraceFormatPropagator())
38 |
39 | tracer = trace.get_tracer(__name__)
40 | with tracer.start_as_current_span("client_span"):
41 | response = requests.get("http://localhost:5000/")
42 |
--------------------------------------------------------------------------------
/docs/examples/cloud_trace_propagator/requirements.in:
--------------------------------------------------------------------------------
1 | -e ../../../opentelemetry-exporter-gcp-monitoring
2 | -e ../../../opentelemetry-exporter-gcp-trace
3 | -e ../../../opentelemetry-propagator-gcp
4 | -e ../../../opentelemetry-resourcedetector-gcp
5 | flask
6 | opentelemetry-api
7 | opentelemetry-instrumentation-flask
8 | opentelemetry-instrumentation-requests
9 | opentelemetry-sdk
10 | requests
11 |
--------------------------------------------------------------------------------
/docs/examples/cloud_trace_propagator/server.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # Copyright 2021 The OpenTelemetry Authors
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 | from opentelemetry.instrumentation.requests import RequestsInstrumentor
17 | from opentelemetry.instrumentation.flask import FlaskInstrumentor
18 | from opentelemetry import trace
19 | from opentelemetry.exporter.cloud_trace import CloudTraceSpanExporter
20 | from opentelemetry.instrumentation.flask import FlaskInstrumentor
21 | from opentelemetry.propagate import set_global_textmap
22 | from opentelemetry.sdk.trace import TracerProvider
23 | from opentelemetry.sdk.trace.export import BatchSpanProcessor
24 | from opentelemetry.propagators.cloud_trace_propagator import (
25 | CloudTraceFormatPropagator,
26 | )
27 |
28 | from flask import Flask
29 |
30 | # Instrumenting requests
31 | RequestsInstrumentor().instrument()
32 |
33 | # Instrumenting flask
34 | app = Flask(__name__)
35 | FlaskInstrumentor().instrument_app(app)
36 |
37 | # Tracer boilerplate
38 | trace.set_tracer_provider(TracerProvider())
39 | trace.get_tracer_provider().add_span_processor(
40 | BatchSpanProcessor(CloudTraceSpanExporter())
41 | )
42 |
43 | # Using the X-Cloud-Trace-Context header
44 | set_global_textmap(CloudTraceFormatPropagator())
45 |
46 |
47 | @app.route("/")
48 | def hello_world():
49 | tracer = trace.get_tracer(__name__)
50 | with tracer.start_as_current_span("server_span"):
51 | return "Hello World!"
52 |
53 |
54 | if __name__ == "__main__":
55 | port = 5000
56 | app.run(port=port)
57 |
--------------------------------------------------------------------------------
/docs/examples/flask_e2e/client.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # Copyright 2021 The OpenTelemetry Authors
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 | import requests
17 | from opentelemetry import metrics, trace
18 | from opentelemetry.exporter.cloud_monitoring import (
19 | CloudMonitoringMetricsExporter,
20 | )
21 | from opentelemetry.exporter.cloud_trace import CloudTraceSpanExporter
22 | from opentelemetry.instrumentation.requests import RequestsInstrumentor
23 | from opentelemetry.propagate import set_global_textmap
24 | from opentelemetry.propagators.cloud_trace_propagator import (
25 | CloudTraceFormatPropagator,
26 | )
27 | from opentelemetry.sdk.metrics import MeterProvider
28 | from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
29 | from opentelemetry.sdk.resources import Resource
30 | from opentelemetry.sdk.trace import TracerProvider
31 | from opentelemetry.sdk.trace.export import BatchSpanProcessor
32 |
33 | set_global_textmap(CloudTraceFormatPropagator())
34 |
35 | resource = Resource.create(
36 | {
37 | "service.name": "flask_e2e_client",
38 | "service.namespace": "examples",
39 | "service.instance.id": "instance554",
40 | }
41 | )
42 |
43 | tracer_provider = TracerProvider()
44 | cloud_trace_exporter = CloudTraceSpanExporter()
45 | tracer_provider.add_span_processor(
46 | # BatchSpanProcessor buffers spans and sends them in batches in a
47 | # background thread. The default parameters are sensible, but can be
48 | # tweaked to optimize your performance
49 | BatchSpanProcessor(cloud_trace_exporter)
50 | )
51 |
52 | meter_provider = MeterProvider(
53 | metric_readers=[
54 | PeriodicExportingMetricReader(
55 | CloudMonitoringMetricsExporter(), export_interval_millis=5000
56 | )
57 | ],
58 | resource=resource,
59 | )
60 |
61 | trace.set_tracer_provider(tracer_provider)
62 | metrics.set_meter_provider(meter_provider)
63 |
64 | tracer = trace.get_tracer(__name__)
65 | meter = metrics.get_meter(__name__)
66 |
67 | RequestsInstrumentor().instrument()
68 |
69 | res = requests.get("http://localhost:6000")
70 | print(res.text)
71 |
--------------------------------------------------------------------------------
/docs/examples/flask_e2e/gcm_latency.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GoogleCloudPlatform/opentelemetry-operations-python/54cb8a6db1f707ecc639e11c0a0d808deca6ac9e/docs/examples/flask_e2e/gcm_latency.png
--------------------------------------------------------------------------------
/docs/examples/flask_e2e/gct_result.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GoogleCloudPlatform/opentelemetry-operations-python/54cb8a6db1f707ecc639e11c0a0d808deca6ac9e/docs/examples/flask_e2e/gct_result.png
--------------------------------------------------------------------------------
/docs/examples/flask_e2e/metrics_explorer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GoogleCloudPlatform/opentelemetry-operations-python/54cb8a6db1f707ecc639e11c0a0d808deca6ac9e/docs/examples/flask_e2e/metrics_explorer.png
--------------------------------------------------------------------------------
/docs/examples/flask_e2e/requirements.in:
--------------------------------------------------------------------------------
1 | -e ../../../opentelemetry-exporter-gcp-monitoring
2 | -e ../../../opentelemetry-exporter-gcp-trace
3 | -e ../../../opentelemetry-propagator-gcp
4 | -e ../../../opentelemetry-resourcedetector-gcp
5 | flask
6 | opentelemetry-api
7 | opentelemetry-instrumentation-flask
8 | opentelemetry-instrumentation-requests
9 | opentelemetry-sdk
10 | requests
11 |
--------------------------------------------------------------------------------
/docs/examples/prometheus_exemplars/docker-compose.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 | # 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 | services:
16 | # OpenTelemetry collector. Make sure you set USERID and GOOGLE_APPLICATION_CREDENTIALS
17 | # environment variables for your container to authenticate correctly
18 | otel-collector:
19 | user: ${USERID?set USERID=$(id -u)}
20 | image: otel/opentelemetry-collector-contrib:0.77.0
21 | environment:
22 | - GOOGLE_APPLICATION_CREDENTIALS=${GOOGLE_APPLICATION_CREDENTIALS?}
23 | - PROJECT_ID=${PROJECT_ID?}
24 | volumes:
25 | - ./otel-collector-config.yaml:/etc/otelcol-contrib/config.yaml
26 | - ${GOOGLE_APPLICATION_CREDENTIALS}:${GOOGLE_APPLICATION_CREDENTIALS}
27 | ports:
28 | - 4317:4317 # OTLP gRPC receiver
29 |
30 | # runs server.py
31 | python-server:
32 | build:
33 | context: .
34 | dockerfile: server.dockerfile
35 | init: true
36 | ports:
37 | - 6000:6000
38 |
39 | # load generator that sends requests to the python server
40 | hey-loadgen:
41 | build:
42 | context: .
43 | dockerfile: hey.dockerfile
44 | command: -c 50 -n 100000000 http://python-server:6000
45 |
--------------------------------------------------------------------------------
/docs/examples/prometheus_exemplars/heatmap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GoogleCloudPlatform/opentelemetry-operations-python/54cb8a6db1f707ecc639e11c0a0d808deca6ac9e/docs/examples/prometheus_exemplars/heatmap.png
--------------------------------------------------------------------------------
/docs/examples/prometheus_exemplars/hey.dockerfile:
--------------------------------------------------------------------------------
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 | FROM golang:1.20-alpine
15 | RUN go install github.com/rakyll/hey@latest
16 | ENTRYPOINT ["hey"]
17 |
--------------------------------------------------------------------------------
/docs/examples/prometheus_exemplars/requirements.in:
--------------------------------------------------------------------------------
1 | flask
2 | opentelemetry-api
3 | opentelemetry-exporter-otlp-proto-grpc
4 | opentelemetry-instrumentation-flask
5 | opentelemetry-sdk
6 | prometheus-client
7 | werkzeug
8 |
--------------------------------------------------------------------------------
/docs/examples/prometheus_exemplars/select_metric.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GoogleCloudPlatform/opentelemetry-operations-python/54cb8a6db1f707ecc639e11c0a0d808deca6ac9e/docs/examples/prometheus_exemplars/select_metric.png
--------------------------------------------------------------------------------
/docs/examples/prometheus_exemplars/server.dockerfile:
--------------------------------------------------------------------------------
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 | FROM python:3.10-alpine
16 | COPY requirements.txt .
17 | RUN pip install -r requirements.txt
18 | COPY server.py .
19 | ENV FLASK_APP=server.py
20 | ENTRYPOINT ["flask", "run", "-h", "0.0.0.0", "-p", "6000"]
21 |
--------------------------------------------------------------------------------
/docs/examples/prometheus_exemplars/trace_details.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GoogleCloudPlatform/opentelemetry-operations-python/54cb8a6db1f707ecc639e11c0a0d808deca6ac9e/docs/examples/prometheus_exemplars/trace_details.png
--------------------------------------------------------------------------------
/docs/index.rst:
--------------------------------------------------------------------------------
1 | .. Google Cloud OpenTelemetry documentation main file, created by
2 | sphinx-quickstart on Fri Jul 17 19:47:46 2020.
3 | You can adapt this file completely to your liking, but it should at least
4 | contain the root `toctree` directive.
5 |
6 | Welcome to Google Cloud OpenTelemetry's documentation!
7 | ======================================================
8 |
9 | .. image:: https://badge.fury.io/py/opentelemetry-exporter-gcp-trace.svg
10 | :target: https://badge.fury.io/py/opentelemetry-exporter-gcp-trace
11 |
12 | .. image:: https://badge.fury.io/py/opentelemetry-exporter-gcp-monitoring.svg
13 | :target: https://badge.fury.io/py/opentelemetry-exporter-gcp-monitoring
14 |
15 | .. image:: https://badge.fury.io/py/opentelemetry-resourcedetector-gcp.svg
16 | :target: https://badge.fury.io/py/opentelemetry-resourcedetector-gcp
17 |
18 | .. image:: https://badge.fury.io/py/opentelemetry-propagator-gcp.svg
19 | :target: https://badge.fury.io/py/opentelemetry-propagator-gcp
20 |
21 | This documentation describes OpenTelemetry Python exporters, propagators, and
22 | resource detectors for Google Cloud Platform. Development for these packages
23 | takes place on `Github
24 | `_.
25 |
26 | To get started with instrumentation in Google Cloud, see `Generate traces and metrics with
27 | Python `_.
28 |
29 | To learn more about instrumentation and observability, including opinionated recommendations
30 | for Google Cloud Observability, visit `Instrumentation and observability
31 | `_.
32 |
33 | Installation
34 | ------------
35 |
36 | To install the Cloud Trace exporter:
37 |
38 | .. code-block:: bash
39 |
40 | pip install opentelemetry-exporter-gcp-trace
41 |
42 | To install Cloud Monitoring exporter:
43 |
44 | .. code-block:: bash
45 |
46 | pip install opentelemetry-exporter-gcp-monitoring
47 |
48 | To install the GCP resource detector:
49 |
50 | .. code-block:: bash
51 |
52 | pip install opentelemetry-resourcedetector-gcp
53 |
54 | To install the GCP trace propagator:
55 |
56 | .. code-block:: bash
57 |
58 | pip install opentelemetry-propagator-gcp
59 |
60 |
61 | .. toctree::
62 | :maxdepth: 1
63 | :caption: Exporters
64 | :name: exporters
65 | :glob:
66 |
67 | cloud_monitoring/**
68 | cloud_trace/**
69 |
70 |
71 | .. toctree::
72 | :maxdepth: 1
73 | :caption: Examples
74 | :name: examples
75 | :glob:
76 |
77 | examples/**
78 |
79 |
80 | .. toctree::
81 | :hidden:
82 |
83 | apireference
84 |
85 | :ref:`apireference`
86 |
87 |
88 |
89 | Indices and tables
90 | ==================
91 |
92 | * :ref:`genindex`
93 | * :ref:`modindex`
94 | * :ref:`search`
95 |
--------------------------------------------------------------------------------
/docs/make.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | pushd %~dp0
4 |
5 | REM Command file for Sphinx documentation
6 |
7 | if "%SPHINXBUILD%" == "" (
8 | set SPHINXBUILD=sphinx-build
9 | )
10 | set SOURCEDIR=.
11 | set BUILDDIR=_build
12 |
13 | if "%1" == "" goto help
14 |
15 | %SPHINXBUILD% >NUL 2>NUL
16 | if errorlevel 9009 (
17 | echo.
18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
19 | echo.installed, then set the SPHINXBUILD environment variable to point
20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you
21 | echo.may add the Sphinx directory to PATH.
22 | echo.
23 | echo.If you don't have Sphinx installed, grab it from
24 | echo.http://sphinx-doc.org/
25 | exit /b 1
26 | )
27 |
28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
29 | goto end
30 |
31 | :help
32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
33 |
34 | :end
35 | popd
36 |
--------------------------------------------------------------------------------
/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 | # 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 | # Build relative to root of repository i.e. `docker build --file Dockerfile --tag=$tag ..`
16 |
17 | FROM python:3.9-slim as python-base
18 | ENV PYTHONFAULTHANDLER=1 \
19 | PYTHONUNBUFFERED=1 \
20 | PYTHONHASHSEED=random \
21 | PIP_NO_CACHE_DIR=off \
22 | PIP_DISABLE_PIP_VERSION_CHECK=on \
23 | PIP_DEFAULT_TIMEOUT=100 \
24 | SRC="/src"
25 | WORKDIR $SRC
26 |
27 | FROM python-base as build-base
28 | # copy local dependencies
29 | COPY opentelemetry-exporter-gcp-trace opentelemetry-exporter-gcp-trace
30 | COPY opentelemetry-propagator-gcp opentelemetry-propagator-gcp
31 | COPY opentelemetry-resourcedetector-gcp opentelemetry-resourcedetector-gcp
32 | WORKDIR $SRC/e2e-test-server
33 | # copy requirements/constraints
34 | COPY e2e-test-server/*.txt ./
35 | RUN python -m venv venv && ./venv/bin/pip install -r requirements-dockerfile.txt
36 |
37 | FROM python-base
38 | WORKDIR $SRC/e2e-test-server
39 | COPY --from=build-base $SRC/e2e-test-server/venv venv/
40 | COPY e2e-test-server/ ./
41 |
42 | ENTRYPOINT ["./venv/bin/python", "main.py"]
43 |
--------------------------------------------------------------------------------
/e2e-test-server/constraints.txt:
--------------------------------------------------------------------------------
1 | annotated-types==0.6.0
2 | blinker==1.6.3
3 | cachetools==5.3.1
4 | certifi==2023.7.22
5 | charset-normalizer==3.3.0
6 | click==8.1.7
7 | cloudevents==1.11.0
8 | Deprecated==1.2.14
9 | deprecation==2.1.0
10 | Flask==3.0.0
11 | functions-framework==3.8.0
12 | google-api-core==2.12.0
13 | google-auth==2.23.3
14 | google-cloud-pubsub==2.18.4
15 | google-cloud-trace==1.11.2
16 | googleapis-common-protos==1.61.0
17 | grpc-google-iam-v1==0.12.6
18 | grpcio==1.59.0
19 | grpcio-status==1.59.0
20 | gunicorn==22.0.0
21 | idna==3.4
22 | importlib-metadata==6.8.0
23 | itsdangerous==2.1.2
24 | Jinja2==3.1.2
25 | MarkupSafe==2.1.3
26 | opentelemetry-api==1.30.0
27 | opentelemetry-sdk==1.30.0
28 | opentelemetry-semantic-conventions==0.51b0
29 | packaging==24.1
30 | proto-plus==1.22.3
31 | protobuf==4.24.4
32 | pyasn1==0.5.0
33 | pyasn1-modules==0.3.0
34 | pydantic==2.4.2
35 | pydantic_core==2.10.1
36 | requests==2.31.0
37 | rsa==4.9
38 | typing_extensions==4.8.0
39 | urllib3==2.0.6
40 | waitress==2.1.2
41 | watchdog==4.0.1
42 | Werkzeug==3.0.0
43 | wrapt==1.15.0
44 | zipp==3.17.0
45 |
--------------------------------------------------------------------------------
/e2e-test-server/e2e_test_server/constants.py:
--------------------------------------------------------------------------------
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 | import enum
16 | import os
17 |
18 |
19 | class SubscriptionMode(enum.Enum):
20 | PULL = "pull"
21 | PUSH = "push"
22 | UNDEFINED = None
23 |
24 |
25 | INSTRUMENTING_MODULE_NAME = "opentelemetry-ops-e2e-test-server"
26 | SCENARIO = "scenario"
27 | STATUS_CODE = "status_code"
28 | TEST_ID = "test_id"
29 | TRACE_ID = "trace_id"
30 | SUBSCRIPTION_MODE: SubscriptionMode = SubscriptionMode(
31 | os.environ.get("SUBSCRIPTION_MODE")
32 | )
33 | PROJECT_ID = os.environ["PROJECT_ID"]
34 | REQUEST_SUBSCRIPTION_NAME = os.environ.get("REQUEST_SUBSCRIPTION_NAME")
35 | RESPONSE_TOPIC_NAME = os.environ["RESPONSE_TOPIC_NAME"]
36 | PUSH_PORT = (
37 | os.environ["PUSH_PORT"]
38 | if SUBSCRIPTION_MODE is SubscriptionMode.PUSH
39 | else None
40 | )
41 |
--------------------------------------------------------------------------------
/e2e-test-server/e2e_test_server/types.py:
--------------------------------------------------------------------------------
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 | import base64
16 | from dataclasses import dataclass
17 | from typing import Mapping, Protocol
18 |
19 | from pydantic import BaseModel, Field
20 |
21 |
22 | @dataclass(frozen=True)
23 | class PubsubMessage:
24 | """Wrapper for message that can be used for push and pull apis"""
25 |
26 | attributes: Mapping[str, str]
27 | data: bytes
28 |
29 |
30 | class PubsubPushPayload(BaseModel):
31 | """Shape of the JSON payload coming from a push subscription"""
32 |
33 | class Message(BaseModel):
34 | attributes: Mapping[str, str]
35 | data_base64: str = Field(default="", alias="data")
36 |
37 | def to_pubsub_message(self) -> PubsubMessage:
38 | return PubsubMessage(
39 | attributes=self.attributes,
40 | data=base64.b64decode(self.data_base64),
41 | )
42 |
43 | message: Message
44 | subscription: str
45 |
--------------------------------------------------------------------------------
/e2e-test-server/main.py:
--------------------------------------------------------------------------------
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 | import logging
16 |
17 | from e2e_test_server import server
18 | from e2e_test_server.server import cloud_functions_handler
19 | from e2e_test_server.constants import SUBSCRIPTION_MODE, SubscriptionMode
20 |
21 | if __name__ == "__main__":
22 | logging.basicConfig(level=logging.INFO)
23 |
24 | if SUBSCRIPTION_MODE is SubscriptionMode.PULL:
25 | server.pubsub_pull()
26 | elif SUBSCRIPTION_MODE is SubscriptionMode.PUSH:
27 | server.pubsub_push()
28 |
29 | # Expose handler to functions-framework
30 | __all__ = ["cloud_functions_handler"]
31 |
--------------------------------------------------------------------------------
/e2e-test-server/requirements-dockerfile.txt:
--------------------------------------------------------------------------------
1 | # Used for installing from the monorepo in the Dockerfile
2 | -r requirements-shared.txt
3 | ../opentelemetry-exporter-gcp-trace
4 | ../opentelemetry-propagator-gcp
5 | ../opentelemetry-resourcedetector-gcp
6 |
--------------------------------------------------------------------------------
/e2e-test-server/requirements-shared.txt:
--------------------------------------------------------------------------------
1 | # Shared by all requirements files
2 | -c constraints.txt
3 | opentelemetry-sdk
4 | opentelemetry-api
5 | Flask
6 | google-cloud-pubsub
7 | googleapis-common-protos
8 | pydantic
9 | waitress
10 | functions-framework
11 |
--------------------------------------------------------------------------------
/e2e-test-server/requirements.txt:
--------------------------------------------------------------------------------
1 | # Used for Cloud Functions and GAE, has to be named requirements.txt
2 | -r requirements-shared.txt
3 |
4 | # allow installing dev versions so pip doesn't pull from pypi
5 | --pre
6 | # install monorepo packages from local vendored wheels directory
7 | --find-links wheels/
8 | opentelemetry-exporter-gcp-trace
9 | opentelemetry-propagator-gcp
10 | opentelemetry-resourcedetector-gcp
11 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/get_mock_server.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
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 | # Use this envvar when testing a local mock_server binary
17 | if [ "$SKIP_GET_MOCK_SERVER" == "true" ]; then
18 | exit
19 | fi
20 |
21 | VERSION=v2-alpha
22 | BINARY=mock_server-x64-linux-$VERSION
23 | if ! [ -e $1/$BINARY ]; then
24 | curl -L -o $1/$BINARY https://github.com/googleinterns/cloud-operations-api-mock/releases/download/$VERSION/$BINARY
25 | chmod +x $1/$BINARY
26 | fi
27 |
28 | ln -sf $1/$BINARY $1/mock_server
29 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-logging/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## Unreleased
4 |
5 | Added support for when `bytes` or `list['bytes']` is in `LogRecord.body` and
6 | body is of type Mapping. Update opentelemetry-api/sdk dependencies to 1.3.
7 |
8 | ## Version 1.9.0a0
9 |
10 | Released 2025-02-03
11 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-logging/MANIFEST.in:
--------------------------------------------------------------------------------
1 | graft src
2 | graft tests
3 | global-exclude *.pyc
4 | global-exclude *.pyo
5 | global-exclude __pycache__/*
6 | include CHANGELOG.md
7 | include MANIFEST.in
8 | include README.rst
9 | include LICENSE
10 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-logging/README.rst:
--------------------------------------------------------------------------------
1 | OpenTelemetry Google Cloud Logging Exporter
2 | ==============================================
3 |
4 | .. image:: https://badge.fury.io/py/opentelemetry-exporter-gcp-logging.svg
5 | :target: https://badge.fury.io/py/opentelemetry-exporter-gcp-logging
6 |
7 | .. image:: https://readthedocs.org/projects/google-cloud-opentelemetry/badge/?version=latest
8 | :target: https://google-cloud-opentelemetry.readthedocs.io/en/latest/?badge=latest
9 | :alt: Documentation Status
10 |
11 | This library provides support for exporting logs to Google Cloud
12 | Logging.
13 |
14 | To get started with instrumentation in Google Cloud, see `Generate traces and metrics with
15 | Python `_.
16 |
17 | To learn more about instrumentation and observability, including opinionated recommendations
18 | for Google Cloud Observability, visit `Instrumentation and observability
19 | `_.
20 |
21 | For resource detection and GCP trace context propagation, see
22 | `opentelemetry-tools-google-cloud
23 | `_. For the
24 | Google Cloud Trace exporter, see `opentelemetry-exporter-gcp-trace
25 | `_.
26 |
27 | Installation
28 | ------------
29 |
30 | .. code:: bash
31 |
32 | pip install opentelemetry-exporter-gcp-logging
33 |
34 | Usage
35 | -----
36 |
37 | .. code:: python
38 |
39 | import logging
40 | from opentelemetry.exporter.cloud_logging import (
41 | CloudLoggingExporter,
42 | )
43 | from opentelemetry.sdk.resources import Resource
44 | from opentelemetry._logs import set_logger_provider
45 | from opentelemetry.sdk._logs import LoggerProvider, LoggingHandler
46 | from opentelemetry.sdk._logs.export import BatchLogRecordProcessor
47 |
48 | logger_provider = LoggerProvider(
49 | resource=Resource.create(
50 | {
51 | "service.name": "shoppingcart",
52 | "service.instance.id": "instance-12",
53 | }
54 | ),
55 | )
56 | set_logger_provider(logger_provider)
57 | exporter = CloudLoggingExporter(default_log_name='my_log')
58 | logger_provider.add_log_record_processor(BatchLogRecordProcessor(exporter))
59 | handler = LoggingHandler(level=logging.ERROR, logger_provider=logger_provider)
60 |
61 | # Attach OTLP handler to root logger
62 | logging.getLogger().addHandler(handler)
63 |
64 | # Create namespaced logger
65 | # It is recommended to not use the root logger with OTLP handler
66 | # so telemetry is collected only for the application
67 | logger1 = logging.getLogger("myapp.area1")
68 |
69 | logger1.warning("string log %s", "here")
70 |
71 | References
72 | ----------
73 |
74 | * `Cloud Logging `_
75 | * `OpenTelemetry Project `_
76 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-logging/mypy.ini:
--------------------------------------------------------------------------------
1 | [mypy]
2 | namespace_packages = True
3 | explicit_package_bases = True
4 | mypy_path = $MYPY_CONFIG_FILE_DIR/src
5 |
6 | [mypy-google.auth.*]
7 | ignore_missing_imports = True
8 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-logging/setup.cfg:
--------------------------------------------------------------------------------
1 | [metadata]
2 | name = opentelemetry-exporter-gcp-logging
3 | description = Google Cloud Logging exporter for OpenTelemetry
4 | long_description = file: README.rst
5 | long_description_content_type = text/x-rst
6 | author = Google
7 | author_email = opentelemetry-pypi@google.com
8 | url = https://github.com/GoogleCloudPlatform/opentelemetry-operations-python/tree/main/opentelemetry-exporter-gcp-logging
9 | platforms = any
10 | license = Apache-2.0
11 | classifiers =
12 | Development Status :: 4 - Beta
13 | Intended Audience :: Developers
14 | License :: OSI Approved :: Apache Software License
15 | Programming Language :: Python
16 | Programming Language :: Python :: 3
17 | Programming Language :: Python :: 3.8
18 | Programming Language :: Python :: 3.9
19 | Programming Language :: Python :: 3.10
20 | Programming Language :: Python :: 3.11
21 | Programming Language :: Python :: 3.12
22 |
23 | [options]
24 | python_requires = >=3.8
25 | package_dir=
26 | =src
27 | packages=find_namespace:
28 | install_requires =
29 | google-cloud-logging ~= 3.0
30 | opentelemetry-sdk ~= 1.30
31 | opentelemetry-api ~= 1.30
32 | opentelemetry-resourcedetector-gcp >= 1.5.0dev0, == 1.*
33 |
34 | [options.packages.find]
35 | where = src
36 |
37 | [options.extras_require]
38 | test =
39 |
40 | [options.entry_points]
41 | opentelemetry_logs_exporter =
42 | gcp_logging = opentelemetry.exporter.cloud_logging:CloudLoggingExporter
43 | opentelemetry_environment_variables =
44 | gcp_logging = opentelemetry.exporter.cloud_logging.environment_variables
45 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-logging/setup.py:
--------------------------------------------------------------------------------
1 | # Copyright 2025 The 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 | import os
15 |
16 | import setuptools
17 |
18 | BASE_DIR = os.path.dirname(__file__)
19 | VERSION_FILENAME = os.path.join(
20 | BASE_DIR,
21 | "src",
22 | "opentelemetry",
23 | "exporter",
24 | "cloud_logging",
25 | "version.py",
26 | )
27 | PACKAGE_INFO = {}
28 | with open(VERSION_FILENAME) as f:
29 | exec(f.read(), PACKAGE_INFO)
30 |
31 | setuptools.setup(
32 | version=PACKAGE_INFO["__version__"],
33 | package_data={"opentelemetry": ["py.typed"]},
34 | )
35 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-logging/src/opentelemetry/exporter/cloud_logging/environment_variables.py:
--------------------------------------------------------------------------------
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 | OTEL_EXPORTER_GCP_LOGGING_PROJECT_ID = "OTEL_EXPORTER_GCP_LOGGING_PROJECT_ID"
16 | """
17 | .. envvar:: OTEL_EXPORTER_GCP_LOGGING_PROJECT_ID
18 |
19 | GCP project ID for the exporter to send logs to. Equivalent to constructor parameter to
20 | :class:`opentelemetry.exporter.cloud_logging.CloudLoggingExporter`.
21 | """
22 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-logging/src/opentelemetry/exporter/cloud_logging/version.py:
--------------------------------------------------------------------------------
1 | # Copyright 2025 The 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 | __version__ = "1.10.0.dev0"
16 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-logging/tests/__snapshots__/test_cloud_logging/test_convert_non_json_dict_bytes.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "entries": [
4 | {
5 | "logName": "projects/fakeproject/logs/test",
6 | "resource": {
7 | "labels": {
8 | "location": "global",
9 | "namespace": "",
10 | "node_id": ""
11 | },
12 | "type": "generic_node"
13 | },
14 | "textPayload": "MTIz",
15 | "timestamp": "2025-01-15T21:25:10.997977393Z"
16 | }
17 | ],
18 | "partialSuccess": true
19 | }
20 | ]
21 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-logging/tests/__snapshots__/test_cloud_logging/test_convert_otlp_dict_body.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "entries": [
4 | {
5 | "jsonPayload": {
6 | "kvlistValue": {
7 | "bytes_field": "Ynl0ZXM=",
8 | "repeated_bytes_field": [
9 | "Ynl0ZXM=",
10 | "Ynl0ZXM=",
11 | "Ynl0ZXM="
12 | ],
13 | "values": [
14 | {
15 | "key": "content",
16 | "value": {
17 | "stringValue": "You're a helpful assistant."
18 | }
19 | }
20 | ]
21 | }
22 | },
23 | "labels": {
24 | "event.name": "gen_ai.system.message",
25 | "gen_ai.system": "true",
26 | "test": "23"
27 | },
28 | "logName": "projects/fakeproject/logs/test",
29 | "resource": {
30 | "labels": {
31 | "location": "global",
32 | "namespace": "",
33 | "node_id": ""
34 | },
35 | "type": "generic_node"
36 | },
37 | "severity": "ERROR",
38 | "spanId": "0000000000000016",
39 | "timestamp": "2025-01-15T21:25:10.997977393Z",
40 | "trace": "projects/fakeproject/traces/00000000000000000000000000000019"
41 | }
42 | ],
43 | "partialSuccess": true
44 | }
45 | ]
46 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-logging/tests/__snapshots__/test_cloud_logging/test_convert_otlp_various_different_types_in_attrs_and_bytes_body.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "entries": [
4 | {
5 | "jsonPayload": {
6 | "Classe": [
7 | "Email addresses",
8 | "Passwords"
9 | ],
10 | "CreationDate": "2012-05-05",
11 | "Date": "2016-05-21T21:35:40Z",
12 | "Link": "http://some_link.com",
13 | "LogoType": "png",
14 | "Ref": 164611595.0
15 | },
16 | "labels": {
17 | "boolArray": "[true, false, true, true]",
18 | "float": "25.43231",
19 | "int": "25",
20 | "intArray": "[21, 18, 23, 17]"
21 | },
22 | "logName": "projects/fakeproject/logs/test",
23 | "resource": {
24 | "labels": {
25 | "location": "global",
26 | "namespace": "",
27 | "node_id": ""
28 | },
29 | "type": "generic_node"
30 | },
31 | "timestamp": "2025-01-15T21:25:10.997977393Z"
32 | }
33 | ],
34 | "partialSuccess": true
35 | }
36 | ]
37 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-logging/tests/__snapshots__/test_cloud_logging/test_convert_various_types_of_bodies[bool].json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "entries": [
4 | {
5 | "logName": "projects/fakeproject/logs/test",
6 | "resource": {
7 | "labels": {
8 | "location": "global",
9 | "namespace": "",
10 | "node_id": ""
11 | },
12 | "type": "generic_node"
13 | },
14 | "textPayload": "true",
15 | "timestamp": "2025-01-15T21:25:10.997977393Z"
16 | }
17 | ],
18 | "partialSuccess": true
19 | }
20 | ]
21 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-logging/tests/__snapshots__/test_cloud_logging/test_convert_various_types_of_bodies[str].json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "entries": [
4 | {
5 | "logName": "projects/fakeproject/logs/test",
6 | "resource": {
7 | "labels": {
8 | "location": "global",
9 | "namespace": "",
10 | "node_id": ""
11 | },
12 | "type": "generic_node"
13 | },
14 | "textPayload": "A text body",
15 | "timestamp": "2025-01-15T21:25:10.997977393Z"
16 | }
17 | ],
18 | "partialSuccess": true
19 | }
20 | ]
21 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-logging/tests/conftest.py:
--------------------------------------------------------------------------------
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 | # pylint: disable=unused-import
16 |
17 | # import fixtures to be made available to other tests
18 | from fixtures.cloud_logging_fake import fixture_cloudloggingfake
19 | from fixtures.snapshot_logging_calls import fixture_snapshot_writelogentrycalls
20 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-logging/tests/fixtures/snapshot_logging_calls.py:
--------------------------------------------------------------------------------
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 | from typing import List, Optional, cast
16 |
17 | import pytest
18 | from fixtures.cloud_logging_fake import WriteLogEntriesCall
19 | from google.protobuf import json_format
20 | from syrupy.extensions.json import JSONSnapshotExtension
21 | from syrupy.types import (
22 | PropertyFilter,
23 | PropertyMatcher,
24 | SerializableData,
25 | SerializedData,
26 | )
27 |
28 |
29 | # pylint: disable=too-many-ancestors
30 | class WriteLogEntryCallSnapshotExtension(JSONSnapshotExtension):
31 | """syrupy extension to serialize WriteLogEntriesRequest to JSON for storing as a snapshot."""
32 |
33 | def serialize(
34 | self,
35 | data: SerializableData,
36 | *,
37 | exclude: Optional[PropertyFilter] = None,
38 | matcher: Optional[PropertyMatcher] = None,
39 | ) -> SerializedData:
40 | json = [
41 | json_format.MessageToDict(
42 | type(call.write_log_entries_request).pb(
43 | call.write_log_entries_request
44 | )
45 | )
46 | for call in cast(List[WriteLogEntriesCall], data)
47 | ]
48 | return super().serialize(json, exclude=exclude, matcher=matcher)
49 |
50 |
51 | @pytest.fixture(name="snapshot_writelogentrycalls")
52 | def fixture_snapshot_writelogentrycalls(snapshot):
53 | """Fixture for snapshot testing of WriteLogEntriesCalls"""
54 | return snapshot.use_extension(WriteLogEntryCallSnapshotExtension)()
55 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-monitoring/MANIFEST.in:
--------------------------------------------------------------------------------
1 | graft src
2 | graft tests
3 | global-exclude *.pyc
4 | global-exclude *.pyo
5 | global-exclude __pycache__/*
6 | include CHANGELOG.md
7 | include MANIFEST.in
8 | include README.rst
9 | include LICENSE
10 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-monitoring/mypy.ini:
--------------------------------------------------------------------------------
1 | [mypy]
2 | namespace_packages = True
3 | explicit_package_bases = True
4 | mypy_path = $MYPY_CONFIG_FILE_DIR/src
5 |
6 | [mypy-google.auth.*]
7 | ignore_missing_imports = True
8 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-monitoring/setup.cfg:
--------------------------------------------------------------------------------
1 | [metadata]
2 | name = opentelemetry-exporter-gcp-monitoring
3 | description = Google Cloud Monitoring exporter for OpenTelemetry
4 | long_description = file: README.rst
5 | long_description_content_type = text/x-rst
6 | author = Google
7 | author_email = opentelemetry-pypi@google.com
8 | url = https://github.com/GoogleCloudPlatform/opentelemetry-operations-python/tree/main/opentelemetry-exporter-gcp-monitoring
9 | platforms = any
10 | license = Apache-2.0
11 | classifiers =
12 | Development Status :: 4 - Beta
13 | Intended Audience :: Developers
14 | License :: OSI Approved :: Apache Software License
15 | Programming Language :: Python
16 | Programming Language :: Python :: 3
17 | Programming Language :: Python :: 3.8
18 | Programming Language :: Python :: 3.9
19 | Programming Language :: Python :: 3.10
20 | Programming Language :: Python :: 3.11
21 | Programming Language :: Python :: 3.12
22 | Programming Language :: Python :: 3.13
23 |
24 | [options]
25 | python_requires = >=3.8
26 | package_dir=
27 | =src
28 | packages=find_namespace:
29 | install_requires =
30 | google-cloud-monitoring ~= 2.0
31 | opentelemetry-api ~= 1.30
32 | opentelemetry-sdk ~= 1.30
33 | opentelemetry-resourcedetector-gcp >= 1.5.0dev0, == 1.*
34 |
35 | [options.packages.find]
36 | where = src
37 |
38 | [options.extras_require]
39 | test =
40 |
41 | [options.entry_points]
42 | opentelemetry_metrics_exporter =
43 | gcp_monitoring = opentelemetry.exporter.cloud_monitoring:CloudMonitoringMetricsExporter
44 | opentelemetry_environment_variables =
45 | gcp_monitoring = opentelemetry.exporter.cloud_monitoring.environment_variables
46 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-monitoring/setup.py:
--------------------------------------------------------------------------------
1 | # Copyright 2021 The 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 | import os
15 |
16 | import setuptools
17 |
18 | BASE_DIR = os.path.dirname(__file__)
19 | VERSION_FILENAME = os.path.join(
20 | BASE_DIR,
21 | "src",
22 | "opentelemetry",
23 | "exporter",
24 | "cloud_monitoring",
25 | "version.py",
26 | )
27 | PACKAGE_INFO = {}
28 | with open(VERSION_FILENAME) as f:
29 | exec(f.read(), PACKAGE_INFO)
30 |
31 | setuptools.setup(
32 | version=PACKAGE_INFO["__version__"],
33 | package_data={"opentelemetry": ["py.typed"]},
34 | )
35 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-monitoring/src/opentelemetry/exporter/cloud_monitoring/environment_variables.py:
--------------------------------------------------------------------------------
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 | OTEL_EXPORTER_GCP_MONITORING_PROJECT_ID = (
16 | "OTEL_EXPORTER_GCP_MONITORING_PROJECT_ID"
17 | )
18 | """
19 | .. envvar:: OTEL_EXPORTER_GCP_MONITORING_PROJECT_ID
20 |
21 | GCP project ID for the exporter to send metrics to. Equivalent to constructor parameter to
22 | :class:`opentelemetry.exporter.cloud_monitoring.CloudMonitoringMetricsExporter`.
23 | """
24 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-monitoring/src/opentelemetry/exporter/cloud_monitoring/version.py:
--------------------------------------------------------------------------------
1 | # Copyright 2021 The 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 | __version__ = "1.10.0.dev0"
16 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-monitoring/src/opentelemetry/py.typed:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GoogleCloudPlatform/opentelemetry-operations-python/54cb8a6db1f707ecc639e11c0a0d808deca6ac9e/opentelemetry-exporter-gcp-monitoring/src/opentelemetry/py.typed
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-monitoring/tests/__snapshots__/test_cloud_monitoring/test_counter[float].json:
--------------------------------------------------------------------------------
1 | {
2 | "/google.monitoring.v3.MetricService/CreateMetricDescriptor": [
3 | {
4 | "metricDescriptor": {
5 | "description": "foo",
6 | "displayName": "mycounter",
7 | "labels": [
8 | {
9 | "key": "string"
10 | },
11 | {
12 | "key": "int"
13 | },
14 | {
15 | "key": "float"
16 | }
17 | ],
18 | "metricKind": "CUMULATIVE",
19 | "type": "workload.googleapis.com/mycounter",
20 | "unit": "{myunit}",
21 | "valueType": "DOUBLE"
22 | },
23 | "name": "projects/fakeproject"
24 | }
25 | ],
26 | "/google.monitoring.v3.MetricService/CreateTimeSeries": [
27 | {
28 | "name": "projects/fakeproject",
29 | "timeSeries": [
30 | {
31 | "metric": {
32 | "labels": {
33 | "float": "123.4",
34 | "int": "123",
35 | "string": "string"
36 | },
37 | "type": "workload.googleapis.com/mycounter"
38 | },
39 | "metricKind": "CUMULATIVE",
40 | "points": [
41 | {
42 | "interval": {
43 | "endTime": "str",
44 | "startTime": "str"
45 | },
46 | "value": {
47 | "doubleValue": 45.6
48 | }
49 | }
50 | ],
51 | "resource": {
52 | "labels": {
53 | "location": "global",
54 | "namespace": "",
55 | "node_id": ""
56 | },
57 | "type": "generic_node"
58 | },
59 | "unit": "{myunit}"
60 | }
61 | ]
62 | }
63 | ]
64 | }
65 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-monitoring/tests/__snapshots__/test_cloud_monitoring/test_counter[int].json:
--------------------------------------------------------------------------------
1 | {
2 | "/google.monitoring.v3.MetricService/CreateMetricDescriptor": [
3 | {
4 | "metricDescriptor": {
5 | "description": "foo",
6 | "displayName": "mycounter",
7 | "labels": [
8 | {
9 | "key": "string"
10 | },
11 | {
12 | "key": "int"
13 | },
14 | {
15 | "key": "float"
16 | }
17 | ],
18 | "metricKind": "CUMULATIVE",
19 | "type": "workload.googleapis.com/mycounter",
20 | "unit": "{myunit}",
21 | "valueType": "INT64"
22 | },
23 | "name": "projects/fakeproject"
24 | }
25 | ],
26 | "/google.monitoring.v3.MetricService/CreateTimeSeries": [
27 | {
28 | "name": "projects/fakeproject",
29 | "timeSeries": [
30 | {
31 | "metric": {
32 | "labels": {
33 | "float": "123.4",
34 | "int": "123",
35 | "string": "string"
36 | },
37 | "type": "workload.googleapis.com/mycounter"
38 | },
39 | "metricKind": "CUMULATIVE",
40 | "points": [
41 | {
42 | "interval": {
43 | "endTime": "str",
44 | "startTime": "str"
45 | },
46 | "value": {
47 | "int64Value": "123"
48 | }
49 | }
50 | ],
51 | "resource": {
52 | "labels": {
53 | "location": "global",
54 | "namespace": "",
55 | "node_id": ""
56 | },
57 | "type": "generic_node"
58 | },
59 | "unit": "{myunit}"
60 | }
61 | ]
62 | }
63 | ]
64 | }
65 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-monitoring/tests/__snapshots__/test_cloud_monitoring/test_histogram_single_bucket.json:
--------------------------------------------------------------------------------
1 | {
2 | "/google.monitoring.v3.MetricService/CreateMetricDescriptor": [
3 | {
4 | "metricDescriptor": {
5 | "description": "foo",
6 | "displayName": "myhistogram",
7 | "labels": [
8 | {
9 | "key": "string"
10 | },
11 | {
12 | "key": "int"
13 | },
14 | {
15 | "key": "float"
16 | }
17 | ],
18 | "metricKind": "CUMULATIVE",
19 | "type": "workload.googleapis.com/myhistogram",
20 | "unit": "{myunit}",
21 | "valueType": "DISTRIBUTION"
22 | },
23 | "name": "projects/fakeproject"
24 | }
25 | ],
26 | "/google.monitoring.v3.MetricService/CreateTimeSeries": [
27 | {
28 | "name": "projects/fakeproject",
29 | "timeSeries": [
30 | {
31 | "metric": {
32 | "labels": {
33 | "float": "123.4",
34 | "int": "123",
35 | "string": "string"
36 | },
37 | "type": "workload.googleapis.com/myhistogram"
38 | },
39 | "metricKind": "CUMULATIVE",
40 | "points": [
41 | {
42 | "interval": {
43 | "endTime": "str",
44 | "startTime": "str"
45 | },
46 | "value": {
47 | "distributionValue": {
48 | "bucketCounts": [
49 | "6",
50 | "9994"
51 | ],
52 | "bucketOptions": {
53 | "explicitBuckets": {
54 | "bounds": [
55 | 5.5
56 | ]
57 | }
58 | },
59 | "count": "10000",
60 | "mean": 4999.5
61 | }
62 | }
63 | }
64 | ],
65 | "resource": {
66 | "labels": {
67 | "location": "global",
68 | "namespace": "",
69 | "node_id": ""
70 | },
71 | "type": "generic_node"
72 | },
73 | "unit": "{myunit}"
74 | }
75 | ]
76 | }
77 | ]
78 | }
79 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-monitoring/tests/__snapshots__/test_cloud_monitoring/test_invalid_label_keys.json:
--------------------------------------------------------------------------------
1 | {
2 | "/google.monitoring.v3.MetricService/CreateMetricDescriptor": [
3 | {
4 | "metricDescriptor": {
5 | "description": "foo",
6 | "displayName": "mycounter",
7 | "labels": [
8 | {
9 | "key": "key_1some_invalid__key"
10 | }
11 | ],
12 | "metricKind": "CUMULATIVE",
13 | "type": "workload.googleapis.com/mycounter",
14 | "unit": "{myunit}",
15 | "valueType": "INT64"
16 | },
17 | "name": "projects/fakeproject"
18 | }
19 | ],
20 | "/google.monitoring.v3.MetricService/CreateTimeSeries": [
21 | {
22 | "name": "projects/fakeproject",
23 | "timeSeries": [
24 | {
25 | "metric": {
26 | "labels": {
27 | "key_1some_invalid__key": "value"
28 | },
29 | "type": "workload.googleapis.com/mycounter"
30 | },
31 | "metricKind": "CUMULATIVE",
32 | "points": [
33 | {
34 | "interval": {
35 | "endTime": "str",
36 | "startTime": "str"
37 | },
38 | "value": {
39 | "int64Value": "12"
40 | }
41 | }
42 | ],
43 | "resource": {
44 | "labels": {
45 | "location": "global",
46 | "namespace": "",
47 | "node_id": ""
48 | },
49 | "type": "generic_node"
50 | },
51 | "unit": "{myunit}"
52 | }
53 | ]
54 | }
55 | ]
56 | }
57 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-monitoring/tests/__snapshots__/test_cloud_monitoring/test_observable_counter[float].json:
--------------------------------------------------------------------------------
1 | {
2 | "/google.monitoring.v3.MetricService/CreateMetricDescriptor": [
3 | {
4 | "metricDescriptor": {
5 | "description": "foo",
6 | "displayName": "myobservablecounter",
7 | "labels": [
8 | {
9 | "key": "string"
10 | },
11 | {
12 | "key": "int"
13 | },
14 | {
15 | "key": "float"
16 | }
17 | ],
18 | "metricKind": "CUMULATIVE",
19 | "type": "workload.googleapis.com/myobservablecounter",
20 | "unit": "{myunit}",
21 | "valueType": "DOUBLE"
22 | },
23 | "name": "projects/fakeproject"
24 | }
25 | ],
26 | "/google.monitoring.v3.MetricService/CreateTimeSeries": [
27 | {
28 | "name": "projects/fakeproject",
29 | "timeSeries": [
30 | {
31 | "metric": {
32 | "labels": {
33 | "float": "123.4",
34 | "int": "123",
35 | "string": "string"
36 | },
37 | "type": "workload.googleapis.com/myobservablecounter"
38 | },
39 | "metricKind": "CUMULATIVE",
40 | "points": [
41 | {
42 | "interval": {
43 | "endTime": "str",
44 | "startTime": "str"
45 | },
46 | "value": {
47 | "doubleValue": 45.6
48 | }
49 | }
50 | ],
51 | "resource": {
52 | "labels": {
53 | "location": "global",
54 | "namespace": "",
55 | "node_id": ""
56 | },
57 | "type": "generic_node"
58 | },
59 | "unit": "{myunit}"
60 | }
61 | ]
62 | }
63 | ]
64 | }
65 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-monitoring/tests/__snapshots__/test_cloud_monitoring/test_observable_counter[int].json:
--------------------------------------------------------------------------------
1 | {
2 | "/google.monitoring.v3.MetricService/CreateMetricDescriptor": [
3 | {
4 | "metricDescriptor": {
5 | "description": "foo",
6 | "displayName": "myobservablecounter",
7 | "labels": [
8 | {
9 | "key": "string"
10 | },
11 | {
12 | "key": "int"
13 | },
14 | {
15 | "key": "float"
16 | }
17 | ],
18 | "metricKind": "CUMULATIVE",
19 | "type": "workload.googleapis.com/myobservablecounter",
20 | "unit": "{myunit}",
21 | "valueType": "INT64"
22 | },
23 | "name": "projects/fakeproject"
24 | }
25 | ],
26 | "/google.monitoring.v3.MetricService/CreateTimeSeries": [
27 | {
28 | "name": "projects/fakeproject",
29 | "timeSeries": [
30 | {
31 | "metric": {
32 | "labels": {
33 | "float": "123.4",
34 | "int": "123",
35 | "string": "string"
36 | },
37 | "type": "workload.googleapis.com/myobservablecounter"
38 | },
39 | "metricKind": "CUMULATIVE",
40 | "points": [
41 | {
42 | "interval": {
43 | "endTime": "str",
44 | "startTime": "str"
45 | },
46 | "value": {
47 | "int64Value": "123"
48 | }
49 | }
50 | ],
51 | "resource": {
52 | "labels": {
53 | "location": "global",
54 | "namespace": "",
55 | "node_id": ""
56 | },
57 | "type": "generic_node"
58 | },
59 | "unit": "{myunit}"
60 | }
61 | ]
62 | }
63 | ]
64 | }
65 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-monitoring/tests/__snapshots__/test_cloud_monitoring/test_observable_gauge[float].json:
--------------------------------------------------------------------------------
1 | {
2 | "/google.monitoring.v3.MetricService/CreateMetricDescriptor": [
3 | {
4 | "metricDescriptor": {
5 | "description": "foo",
6 | "displayName": "myobservablegauge",
7 | "labels": [
8 | {
9 | "key": "string"
10 | },
11 | {
12 | "key": "int"
13 | },
14 | {
15 | "key": "float"
16 | }
17 | ],
18 | "metricKind": "GAUGE",
19 | "type": "workload.googleapis.com/myobservablegauge",
20 | "unit": "{myunit}",
21 | "valueType": "DOUBLE"
22 | },
23 | "name": "projects/fakeproject"
24 | }
25 | ],
26 | "/google.monitoring.v3.MetricService/CreateTimeSeries": [
27 | {
28 | "name": "projects/fakeproject",
29 | "timeSeries": [
30 | {
31 | "metric": {
32 | "labels": {
33 | "float": "123.4",
34 | "int": "123",
35 | "string": "string"
36 | },
37 | "type": "workload.googleapis.com/myobservablegauge"
38 | },
39 | "metricKind": "GAUGE",
40 | "points": [
41 | {
42 | "interval": {
43 | "endTime": "str"
44 | },
45 | "value": {
46 | "doubleValue": 45.6
47 | }
48 | }
49 | ],
50 | "resource": {
51 | "labels": {
52 | "location": "global",
53 | "namespace": "",
54 | "node_id": ""
55 | },
56 | "type": "generic_node"
57 | },
58 | "unit": "{myunit}"
59 | }
60 | ]
61 | }
62 | ]
63 | }
64 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-monitoring/tests/__snapshots__/test_cloud_monitoring/test_observable_gauge[int].json:
--------------------------------------------------------------------------------
1 | {
2 | "/google.monitoring.v3.MetricService/CreateMetricDescriptor": [
3 | {
4 | "metricDescriptor": {
5 | "description": "foo",
6 | "displayName": "myobservablegauge",
7 | "labels": [
8 | {
9 | "key": "string"
10 | },
11 | {
12 | "key": "int"
13 | },
14 | {
15 | "key": "float"
16 | }
17 | ],
18 | "metricKind": "GAUGE",
19 | "type": "workload.googleapis.com/myobservablegauge",
20 | "unit": "{myunit}",
21 | "valueType": "INT64"
22 | },
23 | "name": "projects/fakeproject"
24 | }
25 | ],
26 | "/google.monitoring.v3.MetricService/CreateTimeSeries": [
27 | {
28 | "name": "projects/fakeproject",
29 | "timeSeries": [
30 | {
31 | "metric": {
32 | "labels": {
33 | "float": "123.4",
34 | "int": "123",
35 | "string": "string"
36 | },
37 | "type": "workload.googleapis.com/myobservablegauge"
38 | },
39 | "metricKind": "GAUGE",
40 | "points": [
41 | {
42 | "interval": {
43 | "endTime": "str"
44 | },
45 | "value": {
46 | "int64Value": "123"
47 | }
48 | }
49 | ],
50 | "resource": {
51 | "labels": {
52 | "location": "global",
53 | "namespace": "",
54 | "node_id": ""
55 | },
56 | "type": "generic_node"
57 | },
58 | "unit": "{myunit}"
59 | }
60 | ]
61 | }
62 | ]
63 | }
64 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-monitoring/tests/__snapshots__/test_cloud_monitoring/test_observable_updowncounter[float].json:
--------------------------------------------------------------------------------
1 | {
2 | "/google.monitoring.v3.MetricService/CreateMetricDescriptor": [
3 | {
4 | "metricDescriptor": {
5 | "description": "foo",
6 | "displayName": "myobservableupdowncounter",
7 | "labels": [
8 | {
9 | "key": "string"
10 | },
11 | {
12 | "key": "int"
13 | },
14 | {
15 | "key": "float"
16 | }
17 | ],
18 | "metricKind": "GAUGE",
19 | "type": "workload.googleapis.com/myobservableupdowncounter",
20 | "unit": "{myunit}",
21 | "valueType": "DOUBLE"
22 | },
23 | "name": "projects/fakeproject"
24 | }
25 | ],
26 | "/google.monitoring.v3.MetricService/CreateTimeSeries": [
27 | {
28 | "name": "projects/fakeproject",
29 | "timeSeries": [
30 | {
31 | "metric": {
32 | "labels": {
33 | "float": "123.4",
34 | "int": "123",
35 | "string": "string"
36 | },
37 | "type": "workload.googleapis.com/myobservableupdowncounter"
38 | },
39 | "metricKind": "GAUGE",
40 | "points": [
41 | {
42 | "interval": {
43 | "endTime": "str"
44 | },
45 | "value": {
46 | "doubleValue": 45.6
47 | }
48 | }
49 | ],
50 | "resource": {
51 | "labels": {
52 | "location": "global",
53 | "namespace": "",
54 | "node_id": ""
55 | },
56 | "type": "generic_node"
57 | },
58 | "unit": "{myunit}"
59 | }
60 | ]
61 | }
62 | ]
63 | }
64 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-monitoring/tests/__snapshots__/test_cloud_monitoring/test_observable_updowncounter[int].json:
--------------------------------------------------------------------------------
1 | {
2 | "/google.monitoring.v3.MetricService/CreateMetricDescriptor": [
3 | {
4 | "metricDescriptor": {
5 | "description": "foo",
6 | "displayName": "myobservableupdowncounter",
7 | "labels": [
8 | {
9 | "key": "string"
10 | },
11 | {
12 | "key": "int"
13 | },
14 | {
15 | "key": "float"
16 | }
17 | ],
18 | "metricKind": "GAUGE",
19 | "type": "workload.googleapis.com/myobservableupdowncounter",
20 | "unit": "{myunit}",
21 | "valueType": "INT64"
22 | },
23 | "name": "projects/fakeproject"
24 | }
25 | ],
26 | "/google.monitoring.v3.MetricService/CreateTimeSeries": [
27 | {
28 | "name": "projects/fakeproject",
29 | "timeSeries": [
30 | {
31 | "metric": {
32 | "labels": {
33 | "float": "123.4",
34 | "int": "123",
35 | "string": "string"
36 | },
37 | "type": "workload.googleapis.com/myobservableupdowncounter"
38 | },
39 | "metricKind": "GAUGE",
40 | "points": [
41 | {
42 | "interval": {
43 | "endTime": "str"
44 | },
45 | "value": {
46 | "int64Value": "123"
47 | }
48 | }
49 | ],
50 | "resource": {
51 | "labels": {
52 | "location": "global",
53 | "namespace": "",
54 | "node_id": ""
55 | },
56 | "type": "generic_node"
57 | },
58 | "unit": "{myunit}"
59 | }
60 | ]
61 | }
62 | ]
63 | }
64 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-monitoring/tests/__snapshots__/test_cloud_monitoring/test_up_down_counter[float].json:
--------------------------------------------------------------------------------
1 | {
2 | "/google.monitoring.v3.MetricService/CreateMetricDescriptor": [
3 | {
4 | "metricDescriptor": {
5 | "description": "foo",
6 | "displayName": "myupdowncounter",
7 | "labels": [
8 | {
9 | "key": "string"
10 | },
11 | {
12 | "key": "int"
13 | },
14 | {
15 | "key": "float"
16 | }
17 | ],
18 | "metricKind": "GAUGE",
19 | "type": "workload.googleapis.com/myupdowncounter",
20 | "unit": "{myunit}",
21 | "valueType": "DOUBLE"
22 | },
23 | "name": "projects/fakeproject"
24 | }
25 | ],
26 | "/google.monitoring.v3.MetricService/CreateTimeSeries": [
27 | {
28 | "name": "projects/fakeproject",
29 | "timeSeries": [
30 | {
31 | "metric": {
32 | "labels": {
33 | "float": "123.4",
34 | "int": "123",
35 | "string": "string"
36 | },
37 | "type": "workload.googleapis.com/myupdowncounter"
38 | },
39 | "metricKind": "GAUGE",
40 | "points": [
41 | {
42 | "interval": {
43 | "endTime": "str"
44 | },
45 | "value": {
46 | "doubleValue": 45.6
47 | }
48 | }
49 | ],
50 | "resource": {
51 | "labels": {
52 | "location": "global",
53 | "namespace": "",
54 | "node_id": ""
55 | },
56 | "type": "generic_node"
57 | },
58 | "unit": "{myunit}"
59 | }
60 | ]
61 | }
62 | ]
63 | }
64 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-monitoring/tests/__snapshots__/test_cloud_monitoring/test_up_down_counter[int].json:
--------------------------------------------------------------------------------
1 | {
2 | "/google.monitoring.v3.MetricService/CreateMetricDescriptor": [
3 | {
4 | "metricDescriptor": {
5 | "description": "foo",
6 | "displayName": "myupdowncounter",
7 | "labels": [
8 | {
9 | "key": "string"
10 | },
11 | {
12 | "key": "int"
13 | },
14 | {
15 | "key": "float"
16 | }
17 | ],
18 | "metricKind": "GAUGE",
19 | "type": "workload.googleapis.com/myupdowncounter",
20 | "unit": "{myunit}",
21 | "valueType": "INT64"
22 | },
23 | "name": "projects/fakeproject"
24 | }
25 | ],
26 | "/google.monitoring.v3.MetricService/CreateTimeSeries": [
27 | {
28 | "name": "projects/fakeproject",
29 | "timeSeries": [
30 | {
31 | "metric": {
32 | "labels": {
33 | "float": "123.4",
34 | "int": "123",
35 | "string": "string"
36 | },
37 | "type": "workload.googleapis.com/myupdowncounter"
38 | },
39 | "metricKind": "GAUGE",
40 | "points": [
41 | {
42 | "interval": {
43 | "endTime": "str"
44 | },
45 | "value": {
46 | "int64Value": "123"
47 | }
48 | }
49 | ],
50 | "resource": {
51 | "labels": {
52 | "location": "global",
53 | "namespace": "",
54 | "node_id": ""
55 | },
56 | "type": "generic_node"
57 | },
58 | "unit": "{myunit}"
59 | }
60 | ]
61 | }
62 | ]
63 | }
64 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-monitoring/tests/__snapshots__/test_cloud_monitoring/test_with_resource.json:
--------------------------------------------------------------------------------
1 | {
2 | "/google.monitoring.v3.MetricService/CreateMetricDescriptor": [
3 | {
4 | "metricDescriptor": {
5 | "description": "foo",
6 | "displayName": "mycounter",
7 | "labels": [
8 | {
9 | "key": "string"
10 | },
11 | {
12 | "key": "int"
13 | },
14 | {
15 | "key": "float"
16 | }
17 | ],
18 | "metricKind": "CUMULATIVE",
19 | "type": "workload.googleapis.com/mycounter",
20 | "unit": "{myunit}",
21 | "valueType": "INT64"
22 | },
23 | "name": "projects/fakeproject"
24 | }
25 | ],
26 | "/google.monitoring.v3.MetricService/CreateTimeSeries": [
27 | {
28 | "name": "projects/fakeproject",
29 | "timeSeries": [
30 | {
31 | "metric": {
32 | "labels": {
33 | "float": "123.4",
34 | "int": "123",
35 | "string": "string"
36 | },
37 | "type": "workload.googleapis.com/mycounter"
38 | },
39 | "metricKind": "CUMULATIVE",
40 | "points": [
41 | {
42 | "interval": {
43 | "endTime": "str",
44 | "startTime": "str"
45 | },
46 | "value": {
47 | "int64Value": "12"
48 | }
49 | }
50 | ],
51 | "resource": {
52 | "labels": {
53 | "cluster_name": "mycluster",
54 | "container_name": "mycontainer",
55 | "location": "myavailzone",
56 | "namespace_name": "myns",
57 | "pod_name": "mypod"
58 | },
59 | "type": "k8s_container"
60 | },
61 | "unit": "{myunit}"
62 | }
63 | ]
64 | }
65 | ]
66 | }
67 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-monitoring/tests/conftest.py:
--------------------------------------------------------------------------------
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 | # pylint: disable=unused-import
16 |
17 | # import fixtures to be made available to other tests
18 | from fixtures.gcmfake import fixture_gcmfake, fixture_make_meter_provider
19 | from fixtures.snapshot_gcmcalls import fixture_snapshot_gcmcalls
20 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-monitoring/tests/fixtures/snapshot_gcmcalls.py:
--------------------------------------------------------------------------------
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 | from typing import Optional, cast
16 |
17 | import google.protobuf.message
18 | import proto
19 | import pytest
20 | from fixtures.gcmfake import GcmCalls
21 | from google.protobuf import json_format
22 | from syrupy.extensions.json import JSONSnapshotExtension
23 | from syrupy.matchers import path_type
24 | from syrupy.types import (
25 | PropertyFilter,
26 | PropertyMatcher,
27 | SerializableData,
28 | SerializedData,
29 | )
30 |
31 |
32 | # pylint: disable=too-many-ancestors
33 | class GcmCallsSnapshotExtension(JSONSnapshotExtension):
34 | """syrupy extension to serialize GcmCalls.
35 |
36 | Serializes the protobufs for each method call into JSON for storing as a snapshot.
37 | """
38 |
39 | def serialize(
40 | self,
41 | data: SerializableData,
42 | *,
43 | exclude: Optional[PropertyFilter] = None,
44 | matcher: Optional[PropertyMatcher] = None,
45 | ) -> SerializedData:
46 | gcmcalls = cast(GcmCalls, data)
47 | json = {}
48 | for method, calls in gcmcalls.items():
49 | dict_requests = []
50 | for call in calls:
51 | if isinstance(call.message, proto.message.Message):
52 | call.message = type(call.message).pb(call.message)
53 | elif isinstance(call.message, google.protobuf.message.Message):
54 | pass
55 | else:
56 | raise ValueError(
57 | f"Excepted a proto-plus or protobuf message, got {type(call)}"
58 | )
59 | dict_requests.append(json_format.MessageToDict(call.message))
60 | json[method] = dict_requests
61 |
62 | return super().serialize(json, exclude=exclude, matcher=matcher)
63 |
64 |
65 | @pytest.fixture(name="snapshot_gcmcalls")
66 | def fixture_snapshot_gcmcalls(snapshot):
67 | """Fixture for snapshot testing of GcmCalls
68 |
69 | TimeInterval.start_time and TimeInterval.end_time timestamps are "redacted" since they are
70 | dynamic depending on when the test is run.
71 | """
72 | return snapshot.use_extension(GcmCallsSnapshotExtension)(
73 | matcher=path_type(
74 | {r".*\.interval\.(start|end)Time": (str,)},
75 | regex=True,
76 | )
77 | )
78 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-monitoring/tests/test_cloud_monitoring_auto_instrument.py:
--------------------------------------------------------------------------------
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 | from unittest import TestCase
16 |
17 | from opentelemetry.exporter.cloud_monitoring import (
18 | CloudMonitoringMetricsExporter,
19 | )
20 |
21 | # private import for testing only
22 | from opentelemetry.sdk._configuration import _import_exporters
23 |
24 |
25 | class TestCloudTraceAutoInstrument(TestCase):
26 | def test_loads_cloud_trace_exporter(self):
27 | """Test that OTel configuration internals can load the exporter from entrypoint by
28 | name"""
29 | _, metric_exporters, _ = _import_exporters(
30 | trace_exporter_names=[],
31 | log_exporter_names=[],
32 | metric_exporter_names=["gcp_monitoring"],
33 | )
34 | self.assertEqual(
35 | metric_exporters,
36 | {"gcp_monitoring": CloudMonitoringMetricsExporter},
37 | )
38 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-monitoring/tests/test_normalize_label_key.py:
--------------------------------------------------------------------------------
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 | import pytest
16 | from opentelemetry.exporter.cloud_monitoring import _normalize_label_key
17 |
18 |
19 | @pytest.mark.parametrize(
20 | ("key", "expected"),
21 | [
22 | ("valid_key_1", "valid_key_1"),
23 | ("hellø", "hellø"),
24 | ("123", "key_123"),
25 | ("key!321", "key_321"),
26 | ("key!321", "key_321"),
27 | ("hyphens-dots.slashes/", "hyphens_dots_slashes_"),
28 | ("non_letters_:£¢$∞", "non_letters______"),
29 | ],
30 | )
31 | def test_normalize_label_key(key: str, expected: str) -> None:
32 | assert _normalize_label_key(key) == expected
33 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-monitoring/tests/test_user_agent.py:
--------------------------------------------------------------------------------
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 | import re
16 |
17 | from fixtures.gcmfake import GcmFake, GcmFakeMeterProvider
18 |
19 |
20 | def test_with_resource(
21 | gcmfake_meter_provider: GcmFakeMeterProvider,
22 | gcmfake: GcmFake,
23 | ) -> None:
24 | meter_provider = gcmfake_meter_provider()
25 | counter = meter_provider.get_meter(__name__).create_counter(
26 | "mycounter", description="foo", unit="{myunit}"
27 | )
28 | counter.add(12)
29 | meter_provider.force_flush()
30 |
31 | for calls in gcmfake.get_calls().values():
32 | for call in calls:
33 | assert (
34 | re.match(
35 | r"^opentelemetry-python \S+; google-cloud-metric-exporter \S+ grpc-python/\S+",
36 | call.user_agent,
37 | )
38 | is not None
39 | )
40 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-trace/MANIFEST.in:
--------------------------------------------------------------------------------
1 | graft src
2 | graft tests
3 | global-exclude *.pyc
4 | global-exclude *.pyo
5 | global-exclude __pycache__/*
6 | include CHANGELOG.md
7 | include MANIFEST.in
8 | include README.rst
9 | include LICENSE
10 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-trace/README.rst:
--------------------------------------------------------------------------------
1 | OpenTelemetry Google Cloud Integration
2 | ======================================
3 |
4 | .. image:: https://badge.fury.io/py/opentelemetry-exporter-gcp-trace.svg
5 | :target: https://badge.fury.io/py/opentelemetry-exporter-gcp-trace
6 |
7 | .. image:: https://readthedocs.org/projects/google-cloud-opentelemetry/badge/?version=latest
8 | :target: https://google-cloud-opentelemetry.readthedocs.io/en/latest/?badge=latest
9 | :alt: Documentation Status
10 |
11 | This library provides support for exporting traces to Google Cloud Trace.
12 |
13 | To get started with instrumentation in Google Cloud, see `Generate traces and metrics with
14 | Python `_.
15 |
16 | To learn more about instrumentation and observability, including opinionated recommendations
17 | for Google Cloud Observability, visit `Instrumentation and observability
18 | `_.
19 |
20 | For resource detection and GCP trace context propagation, see
21 | `opentelemetry-tools-google-cloud
22 | `_. For the
23 | Google Cloud Monitoring exporter, see
24 | `opentelemetry-exporter-gcp-monitoring
25 | `_.
26 |
27 | Installation
28 | ------------
29 |
30 | .. code:: bash
31 |
32 | pip install opentelemetry-exporter-gcp-trace
33 |
34 | Usage
35 | -----
36 |
37 | .. code:: python
38 |
39 | from opentelemetry import trace
40 | from opentelemetry.exporter.cloud_trace import CloudTraceSpanExporter
41 | from opentelemetry.sdk.trace import TracerProvider
42 | from opentelemetry.sdk.trace.export import (
43 | SimpleSpanProcessor,
44 | )
45 |
46 | trace.set_tracer_provider(TracerProvider())
47 |
48 | cloud_trace_exporter = CloudTraceSpanExporter(
49 | project_id='my-gcloud-project',
50 | )
51 | trace.get_tracer_provider().add_span_processor(
52 | SimpleSpanProcessor(cloud_trace_exporter)
53 | )
54 | tracer = trace.get_tracer(__name__)
55 | with tracer.start_as_current_span('foo'):
56 | print('Hello world!')
57 |
58 |
59 | References
60 | ----------
61 |
62 | * `Cloud Trace `_
63 | * `OpenTelemetry Project `_
64 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-trace/mypy.ini:
--------------------------------------------------------------------------------
1 | [mypy]
2 | namespace_packages = True
3 | explicit_package_bases = True
4 | mypy_path = $MYPY_CONFIG_FILE_DIR/src
5 |
6 | [mypy-google.auth.*]
7 | ignore_missing_imports = True
8 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-trace/setup.cfg:
--------------------------------------------------------------------------------
1 | [metadata]
2 | name = opentelemetry-exporter-gcp-trace
3 | description = Google Cloud Trace exporter for OpenTelemetry
4 | long_description = file: README.rst
5 | long_description_content_type = text/x-rst
6 | author = Google
7 | author_email = opentelemetry-pypi@google.com
8 | url = https://github.com/GoogleCloudPlatform/opentelemetry-operations-python/tree/main/opentelemetry-exporter-gcp-trace
9 | platforms = any
10 | license = Apache-2.0
11 | classifiers =
12 | Development Status :: 4 - Beta
13 | Intended Audience :: Developers
14 | License :: OSI Approved :: Apache Software License
15 | Programming Language :: Python
16 | Programming Language :: Python :: 3
17 | Programming Language :: Python :: 3.8
18 | Programming Language :: Python :: 3.9
19 | Programming Language :: Python :: 3.10
20 | Programming Language :: Python :: 3.11
21 | Programming Language :: Python :: 3.12
22 | Programming Language :: Python :: 3.13
23 |
24 | [options]
25 | package_dir=
26 | =src
27 | packages=find_namespace:
28 | install_requires =
29 | google-cloud-trace ~= 1.1
30 | opentelemetry-api ~= 1.30
31 | opentelemetry-sdk ~= 1.30
32 | opentelemetry-resourcedetector-gcp >= 1.5.0dev0, == 1.*
33 |
34 | [options.packages.find]
35 | where = src
36 |
37 | [options.extras_require]
38 | test =
39 |
40 | [options.entry_points]
41 | opentelemetry_traces_exporter =
42 | gcp_trace = opentelemetry.exporter.cloud_trace:CloudTraceSpanExporter
43 | opentelemetry_environment_variables =
44 | gcp_trace = opentelemetry.exporter.cloud_trace.environment_variables
45 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-trace/setup.py:
--------------------------------------------------------------------------------
1 | # Copyright 2021 The 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 | import os
15 |
16 | import setuptools
17 |
18 | BASE_DIR = os.path.dirname(__file__)
19 | VERSION_FILENAME = os.path.join(
20 | BASE_DIR,
21 | "src",
22 | "opentelemetry",
23 | "exporter",
24 | "cloud_trace",
25 | "version.py",
26 | )
27 | PACKAGE_INFO = {}
28 | with open(VERSION_FILENAME) as f:
29 | exec(f.read(), PACKAGE_INFO)
30 |
31 | setuptools.setup(
32 | version=PACKAGE_INFO["__version__"],
33 | package_data={"opentelemetry": ["py.typed"]},
34 | )
35 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-trace/src/opentelemetry/exporter/cloud_trace/environment_variables.py:
--------------------------------------------------------------------------------
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 | OTEL_EXPORTER_GCP_TRACE_PROJECT_ID = "OTEL_EXPORTER_GCP_TRACE_PROJECT_ID"
16 | """
17 | .. envvar:: OTEL_EXPORTER_GCP_TRACE_PROJECT_ID
18 |
19 | GCP project ID for the project to send spans to. Equivalent to constructor parameter to
20 | :class:`opentelemetry.exporter.cloud_trace.CloudTraceSpanExporter`.
21 | """
22 |
23 | OTEL_EXPORTER_GCP_TRACE_RESOURCE_REGEX = (
24 | "OTEL_EXPORTER_GCP_TRACE_RESOURCE_REGEX"
25 | )
26 | """
27 | .. envvar:: OTEL_EXPORTER_GCP_TRACE_RESOURCE_REGEX
28 |
29 | Resource attributes with keys matching this regex will be added to exported spans as labels
30 | :class:`opentelemetry.exporter.cloud_trace.CloudTraceSpanExporter`. Equivalent to constructor parameter to
31 | :class:`opentelemetry.exporter.cloud_trace.CloudTraceSpanExporter`.
32 | """
33 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-trace/src/opentelemetry/exporter/cloud_trace/version.py:
--------------------------------------------------------------------------------
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 | __version__ = "1.10.0.dev0"
16 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-trace/src/opentelemetry/py.typed:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GoogleCloudPlatform/opentelemetry-operations-python/54cb8a6db1f707ecc639e11c0a0d808deca6ac9e/opentelemetry-exporter-gcp-trace/src/opentelemetry/py.typed
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-trace/tests/test_cloud_trace_auto_instrument.py:
--------------------------------------------------------------------------------
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 | from unittest import TestCase
16 |
17 | from opentelemetry.exporter.cloud_trace import CloudTraceSpanExporter
18 |
19 | # private import for testing only
20 | from opentelemetry.sdk._configuration import _import_exporters
21 |
22 |
23 | class TestCloudTraceAutoInstrument(TestCase):
24 | def test_loads_cloud_trace_exporter(self):
25 | """Test that OTel configuration internals can load the trace exporter from entrypoint
26 | by name"""
27 | trace_exporters, _, _ = _import_exporters(
28 | trace_exporter_names=["gcp_trace"],
29 | log_exporter_names=[],
30 | metric_exporter_names=[],
31 | )
32 | self.assertEqual(
33 | trace_exporters, {"gcp_trace": CloudTraceSpanExporter}
34 | )
35 |
--------------------------------------------------------------------------------
/opentelemetry-exporter-gcp-trace/tests/test_integration_cloud_trace_exporter.py:
--------------------------------------------------------------------------------
1 | # Copyright 2021 The 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 | import grpc
16 | from google.cloud.trace_v2 import TraceServiceClient
17 | from google.cloud.trace_v2.services.trace_service.transports.grpc import (
18 | TraceServiceGrpcTransport,
19 | )
20 | from opentelemetry.exporter.cloud_trace import CloudTraceSpanExporter
21 | from opentelemetry.sdk.resources import Resource
22 | from opentelemetry.sdk.trace import _Span as Span
23 | from opentelemetry.sdk.trace.export import SpanExportResult
24 | from opentelemetry.trace import SpanContext, SpanKind
25 | from test_common import BaseExporterIntegrationTest, time_ns
26 |
27 |
28 | class TestCloudTraceSpanExporter(BaseExporterIntegrationTest):
29 | def test_export(self):
30 | trace_id = "6e0c63257de34c92bf9efcd03927272e"
31 | span_id = "95bb5edabd45950f"
32 |
33 | # Create span and associated data.
34 | resource_info = Resource(
35 | {
36 | "cloud.account.id": 123,
37 | "host.id": "host",
38 | "cloud.zone": "US",
39 | "cloud.provider": "gcp",
40 | "gcp.resource_type": "gce_instance",
41 | }
42 | )
43 | span = Span(
44 | name="span_name",
45 | context=SpanContext(
46 | trace_id=int(trace_id, 16),
47 | span_id=int(span_id, 16),
48 | is_remote=False,
49 | ),
50 | parent=None,
51 | kind=SpanKind.INTERNAL,
52 | resource=resource_info,
53 | attributes={"attr_key": "attr_value"},
54 | )
55 |
56 | # pylint: disable=protected-access
57 | span._start_time = int(time_ns() - (60 * 1e9))
58 | span._end_time = time_ns()
59 | span_data = [span]
60 |
61 | # Setup the trace exporter.
62 | channel = grpc.insecure_channel(self.address)
63 | transport = TraceServiceGrpcTransport(channel=channel)
64 |
65 | client = TraceServiceClient(transport=transport)
66 | trace_exporter = CloudTraceSpanExporter(self.project_id, client=client)
67 |
68 | # Export the spans and verify the results.
69 | result = trace_exporter.export(span_data)
70 | self.assertEqual(result, SpanExportResult.SUCCESS)
71 |
--------------------------------------------------------------------------------
/opentelemetry-propagator-gcp/MANIFEST.in:
--------------------------------------------------------------------------------
1 | graft src
2 | graft tests
3 | global-exclude *.pyc
4 | global-exclude *.pyo
5 | global-exclude __pycache__/*
6 | include CHANGELOG.md
7 | include MANIFEST.in
8 | include README.rst
9 | include LICENSE
10 |
--------------------------------------------------------------------------------
/opentelemetry-propagator-gcp/mypy.ini:
--------------------------------------------------------------------------------
1 | [mypy]
2 | namespace_packages = True
3 | explicit_package_bases = True
4 | mypy_path = $MYPY_CONFIG_FILE_DIR/src
5 |
--------------------------------------------------------------------------------
/opentelemetry-propagator-gcp/setup.cfg:
--------------------------------------------------------------------------------
1 | [metadata]
2 | name = opentelemetry-propagator-gcp
3 | description = Google Cloud propagator for OpenTelemetry
4 | long_description = file: README.rst
5 | long_description_content_type = text/x-rst
6 | author = Google
7 | author_email = opentelemetry-pypi@google.com
8 | url = https://github.com/GoogleCloudPlatform/opentelemetry-operations-python/tree/main/opentelemetry-propagator-gcp
9 | platforms = any
10 | license = Apache-2.0
11 | classifiers =
12 | Development Status :: 4 - Beta
13 | Intended Audience :: Developers
14 | License :: OSI Approved :: Apache Software License
15 | Programming Language :: Python
16 | Programming Language :: Python :: 3
17 | Programming Language :: Python :: 3.8
18 | Programming Language :: Python :: 3.9
19 | Programming Language :: Python :: 3.10
20 | Programming Language :: Python :: 3.11
21 | Programming Language :: Python :: 3.12
22 | Programming Language :: Python :: 3.13
23 |
24 | [options]
25 | python_requires = >=3.8
26 | package_dir=
27 | =src
28 | packages=find_namespace:
29 | install_requires =
30 | opentelemetry-api ~= 1.0
31 |
32 | [options.packages.find]
33 | where = src
34 |
35 | [options.extras_require]
36 | test =
37 |
38 | [options.entry_points]
39 | opentelemetry_propagator =
40 | gcp_trace = opentelemetry.propagators.cloud_trace_propagator:CloudTraceFormatPropagator
41 |
--------------------------------------------------------------------------------
/opentelemetry-propagator-gcp/setup.py:
--------------------------------------------------------------------------------
1 | # Copyright 2021 The 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 | import os
15 |
16 | import setuptools
17 |
18 | BASE_DIR = os.path.dirname(__file__)
19 | VERSION_FILENAME = os.path.join(
20 | BASE_DIR,
21 | "src",
22 | "opentelemetry",
23 | "propagators",
24 | "cloud_trace_propagator",
25 | "version.py",
26 | )
27 | PACKAGE_INFO = {}
28 | with open(VERSION_FILENAME) as f:
29 | exec(f.read(), PACKAGE_INFO)
30 |
31 | setuptools.setup(
32 | version=PACKAGE_INFO["__version__"],
33 | package_data={"opentelemetry": ["py.typed"]},
34 | )
35 |
--------------------------------------------------------------------------------
/opentelemetry-propagator-gcp/src/opentelemetry/propagators/cloud_trace_propagator/version.py:
--------------------------------------------------------------------------------
1 | # Copyright 2021 The 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 | __version__ = "1.10.0.dev0"
16 |
--------------------------------------------------------------------------------
/opentelemetry-propagator-gcp/src/opentelemetry/py.typed:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GoogleCloudPlatform/opentelemetry-operations-python/54cb8a6db1f707ecc639e11c0a0d808deca6ac9e/opentelemetry-propagator-gcp/src/opentelemetry/py.typed
--------------------------------------------------------------------------------
/opentelemetry-propagator-gcp/tests/test_cloud_trace_propagator_auto_instrument.py:
--------------------------------------------------------------------------------
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 | from unittest import TestCase
16 | from unittest.mock import patch
17 |
18 | from opentelemetry.environment_variables import OTEL_PROPAGATORS
19 | from opentelemetry.propagators.cloud_trace_propagator import (
20 | CloudTraceFormatPropagator,
21 | )
22 |
23 |
24 | class TestCloudTracePropagatorAutoInstrument(TestCase):
25 | @patch.dict("os.environ", {OTEL_PROPAGATORS: "gcp_trace"})
26 | def test_loads_cloud_trace_propagator(self):
27 | # This test is a bit fragile as the propagator entry points are loaded on the first
28 | # import of opentelemetry.propagate and saved in a global variable. If another tests
29 | # imports that before this one, it can fail.
30 | # pylint: disable=import-outside-toplevel
31 | from opentelemetry.propagate import propagators
32 |
33 | self.assertEqual(len(propagators), 1)
34 | self.assertIsInstance(propagators[0], CloudTraceFormatPropagator)
35 |
--------------------------------------------------------------------------------
/opentelemetry-resourcedetector-gcp/MANIFEST.in:
--------------------------------------------------------------------------------
1 | graft src
2 | graft tests
3 | global-exclude *.pyc
4 | global-exclude *.pyo
5 | global-exclude __pycache__/*
6 | include CHANGELOG.md
7 | include MANIFEST.in
8 | include README.rst
9 | include LICENSE
10 |
--------------------------------------------------------------------------------
/opentelemetry-resourcedetector-gcp/README.rst:
--------------------------------------------------------------------------------
1 | OpenTelemetry Google Cloud Resource Detector
2 | ============================================
3 |
4 | .. image:: https://badge.fury.io/py/opentelemetry-resourcedetector-gcp.svg
5 | :target: https://badge.fury.io/py/opentelemetry-resourcedetector-gcp
6 |
7 | .. image:: https://readthedocs.org/projects/google-cloud-opentelemetry/badge/?version=latest
8 | :target: https://google-cloud-opentelemetry.readthedocs.io/en/latest/?badge=latest
9 | :alt: Documentation Status
10 |
11 | This library provides support for detecting GCP resources like GCE, GKE, etc.
12 |
13 | To get started with instrumentation in Google Cloud, see `Generate traces and metrics with
14 | Python `_.
15 |
16 | To learn more about instrumentation and observability, including opinionated recommendations
17 | for Google Cloud Observability, visit `Instrumentation and observability
18 | `_.
19 |
20 | Installation
21 | ------------
22 |
23 | .. code:: bash
24 |
25 | pip install opentelemetry-resourcedetector-gcp
26 |
27 | ..
28 | TODO: Add usage info here
29 |
30 |
31 | References
32 | ----------
33 |
34 | * `Cloud Monitoring `_
35 | * `OpenTelemetry Project `_
36 |
--------------------------------------------------------------------------------
/opentelemetry-resourcedetector-gcp/mypy.ini:
--------------------------------------------------------------------------------
1 | [mypy]
2 | namespace_packages = True
3 | explicit_package_bases = True
4 | mypy_path = $MYPY_CONFIG_FILE_DIR/src
5 |
--------------------------------------------------------------------------------
/opentelemetry-resourcedetector-gcp/setup.cfg:
--------------------------------------------------------------------------------
1 | [metadata]
2 | name = opentelemetry-resourcedetector-gcp
3 | description = Google Cloud resource detector for OpenTelemetry
4 | long_description = file: README.rst
5 | long_description_content_type = text/x-rst
6 | author = Google
7 | author_email = opentelemetry-pypi@google.com
8 | url = https://github.com/GoogleCloudPlatform/opentelemetry-operations-python/tree/main/opentelemetry-resourcedetector-gcp
9 | platforms = any
10 | license = Apache-2.0
11 | classifiers =
12 | Development Status :: 4 - Beta
13 | Intended Audience :: Developers
14 | License :: OSI Approved :: Apache Software License
15 | Programming Language :: Python
16 | Programming Language :: Python :: 3
17 | Programming Language :: Python :: 3.8
18 | Programming Language :: Python :: 3.9
19 | Programming Language :: Python :: 3.10
20 | Programming Language :: Python :: 3.11
21 | Programming Language :: Python :: 3.12
22 | Programming Language :: Python :: 3.13
23 |
24 | [options]
25 | python_requires = >=3.8
26 | package_dir=
27 | =src
28 | packages=find_namespace:
29 | install_requires =
30 | opentelemetry-api ~= 1.30
31 | opentelemetry-sdk ~= 1.30
32 | requests ~= 2.24
33 | # TODO: remove when Python 3.7 is dropped
34 | typing_extensions ~= 4.0
35 |
36 | [options.packages.find]
37 | where = src
38 |
39 | [options.extras_require]
40 | test =
41 |
--------------------------------------------------------------------------------
/opentelemetry-resourcedetector-gcp/setup.py:
--------------------------------------------------------------------------------
1 | # Copyright 2021 The 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 | import os
15 |
16 | import setuptools
17 |
18 | BASE_DIR = os.path.dirname(__file__)
19 | VERSION_FILENAME = os.path.join(
20 | BASE_DIR,
21 | "src",
22 | "opentelemetry",
23 | "resourcedetector",
24 | "gcp_resource_detector",
25 | "version.py",
26 | )
27 | PACKAGE_INFO = {}
28 | with open(VERSION_FILENAME) as f:
29 | exec(f.read(), PACKAGE_INFO)
30 |
31 | setuptools.setup(
32 | version=PACKAGE_INFO["__version__"],
33 | package_data={"opentelemetry": ["py.typed"]},
34 | )
35 |
--------------------------------------------------------------------------------
/opentelemetry-resourcedetector-gcp/src/opentelemetry/py.typed:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GoogleCloudPlatform/opentelemetry-operations-python/54cb8a6db1f707ecc639e11c0a0d808deca6ac9e/opentelemetry-resourcedetector-gcp/src/opentelemetry/py.typed
--------------------------------------------------------------------------------
/opentelemetry-resourcedetector-gcp/src/opentelemetry/resourcedetector/gcp_resource_detector/_constants.py:
--------------------------------------------------------------------------------
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 |
16 | # TODO: use opentelemetry-semantic-conventions package for these constants once it has
17 | # stabilized. Right now, pinning an unstable version would cause dependency conflicts for
18 | # users so these are copied in.
19 | class ResourceAttributes:
20 | AWS_EC2 = "aws_ec2"
21 | CLOUD_ACCOUNT_ID = "cloud.account.id"
22 | CLOUD_AVAILABILITY_ZONE = "cloud.availability_zone"
23 | CLOUD_PLATFORM_KEY = "cloud.platform"
24 | CLOUD_PROVIDER = "cloud.provider"
25 | CLOUD_REGION = "cloud.region"
26 | FAAS_INSTANCE = "faas.instance"
27 | FAAS_NAME = "faas.name"
28 | FAAS_VERSION = "faas.version"
29 | GCP_APP_ENGINE = "gcp_app_engine"
30 | GCP_CLOUD_FUNCTIONS = "gcp_cloud_functions"
31 | GCP_CLOUD_RUN = "gcp_cloud_run"
32 | GCP_COMPUTE_ENGINE = "gcp_compute_engine"
33 | GCP_KUBERNETES_ENGINE = "gcp_kubernetes_engine"
34 | HOST_ID = "host.id"
35 | HOST_NAME = "host.name"
36 | HOST_TYPE = "host.type"
37 | K8S_CLUSTER_NAME = "k8s.cluster.name"
38 | K8S_CONTAINER_NAME = "k8s.container.name"
39 | K8S_NAMESPACE_NAME = "k8s.namespace.name"
40 | K8S_NODE_NAME = "k8s.node.name"
41 | K8S_POD_NAME = "k8s.pod.name"
42 | SERVICE_INSTANCE_ID = "service.instance.id"
43 | SERVICE_NAME = "service.name"
44 | SERVICE_NAMESPACE = "service.namespace"
45 |
46 |
47 | AWS_ACCOUNT = "aws_account"
48 | AWS_EC2_INSTANCE = "aws_ec2_instance"
49 | CLUSTER_NAME = "cluster_name"
50 | CONTAINER_NAME = "container_name"
51 | GCE_INSTANCE = "gce_instance"
52 | GENERIC_NODE = "generic_node"
53 | GENERIC_TASK = "generic_task"
54 | INSTANCE_ID = "instance_id"
55 | JOB = "job"
56 | K8S_CLUSTER = "k8s_cluster"
57 | K8S_CONTAINER = "k8s_container"
58 | K8S_NODE = "k8s_node"
59 | K8S_POD = "k8s_pod"
60 | LOCATION = "location"
61 | NAMESPACE = "namespace"
62 | NAMESPACE_NAME = "namespace_name"
63 | NODE_ID = "node_id"
64 | NODE_NAME = "node_name"
65 | POD_NAME = "pod_name"
66 | REGION = "region"
67 | TASK_ID = "task_id"
68 | ZONE = "zone"
69 | UNKNOWN_SERVICE_PREFIX = "unknown_service"
70 |
--------------------------------------------------------------------------------
/opentelemetry-resourcedetector-gcp/src/opentelemetry/resourcedetector/gcp_resource_detector/_faas.py:
--------------------------------------------------------------------------------
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 | # Implementation in this file copied from
16 | # https://github.com/GoogleCloudPlatform/opentelemetry-operations-go/blob/v1.8.0/detectors/gcp/faas.go
17 |
18 | import os
19 |
20 | from opentelemetry.resourcedetector.gcp_resource_detector import _metadata
21 |
22 | _CLOUD_RUN_CONFIG_ENV = "K_CONFIGURATION"
23 | _CLOUD_FUNCTION_TARGET_ENV = "FUNCTION_TARGET"
24 | _FAAS_SERVICE_ENV = "K_SERVICE"
25 | _FAAS_REVISION_ENV = "K_REVISION"
26 |
27 |
28 | def on_cloud_run() -> bool:
29 | return _CLOUD_RUN_CONFIG_ENV in os.environ
30 |
31 |
32 | def on_cloud_functions() -> bool:
33 | return _CLOUD_FUNCTION_TARGET_ENV in os.environ
34 |
35 |
36 | def faas_name() -> str:
37 | """The name of the Cloud Run or Cloud Function.
38 |
39 | Check that on_cloud_run() or on_cloud_functions() is true before calling this, or it may
40 | throw exceptions.
41 | """
42 | return os.environ[_FAAS_SERVICE_ENV]
43 |
44 |
45 | def faas_version() -> str:
46 | """The version/revision of the Cloud Run or Cloud Function.
47 |
48 | Check that on_cloud_run() or on_cloud_functions() is true before calling this, or it may
49 | throw exceptions.
50 | """
51 | return os.environ[_FAAS_REVISION_ENV]
52 |
53 |
54 | def faas_instance() -> str:
55 | return str(_metadata.get_metadata()["instance"]["id"])
56 |
57 |
58 | def faas_cloud_region() -> str:
59 | region = _metadata.get_metadata()["instance"]["region"]
60 | return region[region.rfind("/") + 1 :]
61 |
--------------------------------------------------------------------------------
/opentelemetry-resourcedetector-gcp/src/opentelemetry/resourcedetector/gcp_resource_detector/_gce.py:
--------------------------------------------------------------------------------
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 | import logging
16 | import re
17 | from dataclasses import dataclass
18 |
19 | from opentelemetry.resourcedetector.gcp_resource_detector import _metadata
20 |
21 | # Format described in
22 | # https://cloud.google.com/compute/docs/metadata/default-metadata-values#vm_instance_metadata
23 | _ZONE_REGION_RE = re.compile(
24 | r"projects\/\d+\/zones\/(?P(?P\w+-\w+)-\w+)"
25 | )
26 |
27 | _logger = logging.getLogger(__name__)
28 |
29 |
30 | def on_gce() -> bool:
31 | try:
32 | _metadata.get_metadata()["instance"]["machineType"]
33 | except (_metadata.MetadataAccessException, KeyError):
34 | _logger.debug(
35 | "Could not fetch metadata attribute instance/machineType, "
36 | "assuming not on GCE.",
37 | exc_info=True,
38 | )
39 | return False
40 | return True
41 |
42 |
43 | def host_type() -> str:
44 | return _metadata.get_metadata()["instance"]["machineType"]
45 |
46 |
47 | def host_id() -> str:
48 | return str(_metadata.get_metadata()["instance"]["id"])
49 |
50 |
51 | def host_name() -> str:
52 | return _metadata.get_metadata()["instance"]["name"]
53 |
54 |
55 | @dataclass
56 | class ZoneAndRegion:
57 | zone: str
58 | region: str
59 |
60 |
61 | def availability_zone_and_region() -> ZoneAndRegion:
62 | full_zone = _metadata.get_metadata()["instance"]["zone"]
63 | match = _ZONE_REGION_RE.search(full_zone)
64 | if not match:
65 | raise Exception(
66 | "zone was not in the expected format: "
67 | f"projects/PROJECT_NUM/zones/COUNTRY-REGION-ZONE. Got {full_zone}"
68 | )
69 |
70 | return ZoneAndRegion(
71 | zone=match.group("zone"), region=match.group("region")
72 | )
73 |
--------------------------------------------------------------------------------
/opentelemetry-resourcedetector-gcp/src/opentelemetry/resourcedetector/gcp_resource_detector/_gke.py:
--------------------------------------------------------------------------------
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 | import os
16 | from dataclasses import dataclass
17 | from typing import Literal
18 |
19 | from opentelemetry.resourcedetector.gcp_resource_detector import (
20 | _gce,
21 | _metadata,
22 | )
23 |
24 | KUBERNETES_SERVICE_HOST_ENV = "KUBERNETES_SERVICE_HOST"
25 |
26 |
27 | def on_gke() -> bool:
28 | return os.environ.get(KUBERNETES_SERVICE_HOST_ENV) is not None
29 |
30 |
31 | def host_id() -> str:
32 | return _gce.host_id()
33 |
34 |
35 | def cluster_name() -> str:
36 | return _metadata.get_metadata()["instance"]["attributes"]["cluster-name"]
37 |
38 |
39 | @dataclass
40 | class ZoneOrRegion:
41 | type: Literal["zone", "region"]
42 | value: str
43 |
44 |
45 | def availability_zone_or_region() -> ZoneOrRegion:
46 | cluster_location = _metadata.get_metadata()["instance"]["attributes"][
47 | "cluster-location"
48 | ]
49 | hyphen_count = cluster_location.count("-")
50 | if hyphen_count == 1:
51 | return ZoneOrRegion(type="region", value=cluster_location)
52 | if hyphen_count == 2:
53 | return ZoneOrRegion(type="zone", value=cluster_location)
54 | raise Exception(
55 | f"unrecognized format for cluster location: {cluster_location}"
56 | )
57 |
--------------------------------------------------------------------------------
/opentelemetry-resourcedetector-gcp/src/opentelemetry/resourcedetector/gcp_resource_detector/_metadata.py:
--------------------------------------------------------------------------------
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 | import logging
16 | from functools import lru_cache
17 | from typing import TypedDict, Union
18 |
19 | import requests
20 |
21 | _GCP_METADATA_URL = "http://metadata.google.internal/computeMetadata/v1/"
22 | _INSTANCE = "instance"
23 | _RECURSIVE_PARAMS = {"recursive": "true"}
24 | _GCP_METADATA_URL_HEADER = {"Metadata-Flavor": "Google"}
25 | # Use a shorter timeout for connection so we won't block much if it's unreachable
26 | _TIMEOUT = (2, 5)
27 |
28 | _logger = logging.getLogger(__name__)
29 |
30 |
31 | class Project(TypedDict):
32 | projectId: str
33 |
34 |
35 | Attributes = TypedDict(
36 | "Attributes", {"cluster-location": str, "cluster-name": str}, total=False
37 | )
38 |
39 |
40 | class Instance(TypedDict):
41 | attributes: Attributes
42 | # id can be an integer on GCE VMs or a string on other environments
43 | id: Union[int, str]
44 | machineType: str
45 | name: str
46 | region: str
47 | zone: str
48 |
49 |
50 | class Metadata(TypedDict):
51 | instance: Instance
52 | project: Project
53 |
54 |
55 | class MetadataAccessException(Exception):
56 | pass
57 |
58 |
59 | @lru_cache(maxsize=None)
60 | def get_metadata() -> Metadata:
61 | """Get all instance and project metadata from the metadata server
62 |
63 | Cached for the lifetime of the process.
64 | """
65 | try:
66 | res = requests.get(
67 | f"{_GCP_METADATA_URL}",
68 | params=_RECURSIVE_PARAMS,
69 | headers=_GCP_METADATA_URL_HEADER,
70 | timeout=_TIMEOUT,
71 | )
72 | res.raise_for_status()
73 | all_metadata = res.json()
74 | except requests.RequestException as err:
75 | raise MetadataAccessException() from err
76 | return all_metadata
77 |
78 |
79 | @lru_cache(maxsize=None)
80 | def is_available() -> bool:
81 | try:
82 | requests.get(
83 | f"{_GCP_METADATA_URL}{_INSTANCE}/",
84 | headers=_GCP_METADATA_URL_HEADER,
85 | timeout=_TIMEOUT,
86 | ).raise_for_status()
87 | except requests.RequestException:
88 | _logger.debug(
89 | "Failed to make request to metadata server, assuming it's not available",
90 | exc_info=True,
91 | )
92 | return False
93 | return True
94 |
--------------------------------------------------------------------------------
/opentelemetry-resourcedetector-gcp/src/opentelemetry/resourcedetector/gcp_resource_detector/version.py:
--------------------------------------------------------------------------------
1 | # Copyright 2021 The 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 | __version__ = "1.10.0.dev0"
16 |
--------------------------------------------------------------------------------
/opentelemetry-resourcedetector-gcp/tests/__snapshots__/test_detector.ambr:
--------------------------------------------------------------------------------
1 | # name: test_detects_cloud_functions
2 | dict({
3 | 'cloud.account.id': 'fakeProject',
4 | 'cloud.platform': 'gcp_cloud_functions',
5 | 'cloud.provider': 'gcp',
6 | 'cloud.region': 'us-east4',
7 | 'faas.instance': '0087244a',
8 | 'faas.name': 'fake-service',
9 | 'faas.version': 'fake-revision',
10 | })
11 | # ---
12 | # name: test_detects_cloud_run
13 | dict({
14 | 'cloud.account.id': 'fakeProject',
15 | 'cloud.platform': 'gcp_cloud_run',
16 | 'cloud.provider': 'gcp',
17 | 'cloud.region': 'us-east4',
18 | 'faas.instance': '0087244a',
19 | 'faas.name': 'fake-service',
20 | 'faas.version': 'fake-revision',
21 | })
22 | # ---
23 | # name: test_detects_empty_as_fallback
24 | dict({
25 | })
26 | # ---
27 | # name: test_detects_empty_when_not_available
28 | dict({
29 | })
30 | # ---
31 | # name: test_detects_gae_flex
32 | dict({
33 | 'cloud.account.id': 'fakeProject',
34 | 'cloud.availability_zone': 'us-east4-b',
35 | 'cloud.platform': 'gcp_app_engine',
36 | 'cloud.provider': 'gcp',
37 | 'cloud.region': 'us-east4',
38 | 'faas.instance': 'fake-instance',
39 | 'faas.name': 'fake-service',
40 | 'faas.version': 'fake-version',
41 | })
42 | # ---
43 | # name: test_detects_gae_standard
44 | dict({
45 | 'cloud.account.id': 'fakeProject',
46 | 'cloud.availability_zone': 'us-east4-b',
47 | 'cloud.platform': 'gcp_app_engine',
48 | 'cloud.provider': 'gcp',
49 | 'cloud.region': 'us-east4',
50 | 'faas.instance': 'fake-instance',
51 | 'faas.name': 'fake-service',
52 | 'faas.version': 'fake-version',
53 | })
54 | # ---
55 | # name: test_detects_gce
56 | dict({
57 | 'cloud.account.id': 'fakeProject',
58 | 'cloud.availability_zone': 'us-east4-b',
59 | 'cloud.platform': 'gcp_compute_engine',
60 | 'cloud.provider': 'gcp',
61 | 'cloud.region': 'us-east4',
62 | 'host.id': '0087244a',
63 | 'host.name': 'fakeName',
64 | 'host.type': 'fakeMachineType',
65 | })
66 | # ---
67 | # name: test_detects_gke[regional]
68 | dict({
69 | 'cloud.account.id': 'fakeProject',
70 | 'cloud.platform': 'gcp_kubernetes_engine',
71 | 'cloud.provider': 'gcp',
72 | 'cloud.region': 'us-east4',
73 | 'host.id': '12345',
74 | 'k8s.cluster.name': 'fakeClusterName',
75 | })
76 | # ---
77 | # name: test_detects_gke[zonal]
78 | dict({
79 | 'cloud.account.id': 'fakeProject',
80 | 'cloud.availability_zone': 'us-east4-b',
81 | 'cloud.platform': 'gcp_kubernetes_engine',
82 | 'cloud.provider': 'gcp',
83 | 'host.id': '12345',
84 | 'k8s.cluster.name': 'fakeClusterName',
85 | })
86 | # ---
87 |
--------------------------------------------------------------------------------
/opentelemetry-resourcedetector-gcp/tests/conftest.py:
--------------------------------------------------------------------------------
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 | from unittest.mock import MagicMock
16 |
17 | import pytest
18 | from opentelemetry.resourcedetector.gcp_resource_detector import _metadata
19 |
20 |
21 | @pytest.fixture(name="fake_get_metadata")
22 | def fixture_fake_get_metadata(monkeypatch: pytest.MonkeyPatch) -> MagicMock:
23 | mock = MagicMock()
24 | monkeypatch.setattr(_metadata, "get_metadata", mock)
25 | return mock
26 |
--------------------------------------------------------------------------------
/opentelemetry-resourcedetector-gcp/tests/test_faas.py:
--------------------------------------------------------------------------------
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 | from unittest.mock import MagicMock
16 |
17 | import pytest
18 | from opentelemetry.resourcedetector.gcp_resource_detector import _faas
19 |
20 |
21 | # Reset stuff before every test
22 | # pylint: disable=unused-argument
23 | @pytest.fixture(autouse=True)
24 | def autouse(fake_get_metadata):
25 | pass
26 |
27 |
28 | def test_detects_on_cloud_run(monkeypatch: pytest.MonkeyPatch) -> None:
29 | monkeypatch.setenv("K_CONFIGURATION", "fake-configuration")
30 | assert _faas.on_cloud_run()
31 |
32 |
33 | def test_detects_not_on_cloud_run() -> None:
34 | assert not _faas.on_cloud_run()
35 |
36 |
37 | def test_detects_on_cloud_functions(monkeypatch: pytest.MonkeyPatch) -> None:
38 | monkeypatch.setenv("FUNCTION_TARGET", "fake-function-target")
39 | assert _faas.on_cloud_functions()
40 |
41 |
42 | def test_detects_not_on_cloud_functions() -> None:
43 | assert not _faas.on_cloud_functions()
44 |
45 |
46 | def test_detects_faas_name(monkeypatch: pytest.MonkeyPatch) -> None:
47 | monkeypatch.setenv("K_SERVICE", "fake-service")
48 | assert _faas.faas_name() == "fake-service"
49 |
50 |
51 | def test_detects_faas_version(monkeypatch: pytest.MonkeyPatch) -> None:
52 | monkeypatch.setenv("K_REVISION", "fake-revision")
53 | assert _faas.faas_version() == "fake-revision"
54 |
55 |
56 | def test_detects_faas_instance(fake_get_metadata: MagicMock) -> None:
57 | fake_get_metadata.return_value = {"instance": {"id": "0087244a"}}
58 | assert _faas.faas_instance() == "0087244a"
59 |
60 |
61 | def test_detects_faas_region(fake_get_metadata: MagicMock) -> None:
62 | fake_get_metadata.return_value = {
63 | "instance": {"region": "projects/233510669999/regions/us-east4"}
64 | }
65 | assert _faas.faas_cloud_region() == "us-east4"
66 |
--------------------------------------------------------------------------------
/opentelemetry-resourcedetector-gcp/tests/test_gce.py:
--------------------------------------------------------------------------------
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 | from unittest.mock import MagicMock
16 |
17 | import pytest
18 | from opentelemetry.resourcedetector.gcp_resource_detector import (
19 | _gce,
20 | _metadata,
21 | )
22 |
23 |
24 | # Reset stuff before every test
25 | # pylint: disable=unused-argument
26 | @pytest.fixture(autouse=True)
27 | def autouse(fake_get_metadata):
28 | pass
29 |
30 |
31 | def test_detects_on_gce() -> None:
32 | assert _gce.on_gce()
33 |
34 |
35 | def test_detects_not_on_gce(fake_get_metadata: MagicMock) -> None:
36 | # when the metadata server is not accessible
37 | fake_get_metadata.side_effect = _metadata.MetadataAccessException()
38 | assert not _gce.on_gce()
39 |
40 | # when the metadata server doesn't have the expected structure
41 | fake_get_metadata.return_value = {}
42 | assert not _gce.on_gce()
43 |
44 |
45 | def test_detects_host_type(fake_get_metadata: MagicMock) -> None:
46 | fake_get_metadata.return_value = {"instance": {"machineType": "fake"}}
47 | assert _gce.host_type() == "fake"
48 |
49 |
50 | def test_detects_host_id(fake_get_metadata: MagicMock) -> None:
51 | fake_get_metadata.return_value = {"instance": {"id": 12345}}
52 | assert _gce.host_id() == "12345"
53 |
54 |
55 | def test_detects_host_name(fake_get_metadata: MagicMock) -> None:
56 | fake_get_metadata.return_value = {"instance": {"name": "fake"}}
57 | assert _gce.host_name() == "fake"
58 |
59 |
60 | def test_detects_zone_and_region(fake_get_metadata: MagicMock) -> None:
61 | fake_get_metadata.return_value = {
62 | "instance": {"zone": "projects/233510669999/zones/us-east4-b"}
63 | }
64 | zone_and_region = _gce.availability_zone_and_region()
65 |
66 | assert zone_and_region.zone == "us-east4-b"
67 | assert zone_and_region.region == "us-east4"
68 |
69 |
70 | def test_throws_for_invalid_zone(fake_get_metadata: MagicMock) -> None:
71 | fake_get_metadata.return_value = {"instance": {"zone": ""}}
72 |
73 | with pytest.raises(Exception, match="zone was not in the expected format"):
74 | _gce.availability_zone_and_region()
75 |
--------------------------------------------------------------------------------
/opentelemetry-resourcedetector-gcp/tests/test_gke.py:
--------------------------------------------------------------------------------
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 | from unittest.mock import MagicMock
16 |
17 | import pytest
18 | from opentelemetry.resourcedetector.gcp_resource_detector import _gke
19 |
20 |
21 | def test_detects_on_gke(monkeypatch: pytest.MonkeyPatch) -> None:
22 | monkeypatch.setenv("KUBERNETES_SERVICE_HOST", "fakehost")
23 | assert _gke.on_gke()
24 |
25 |
26 | def test_detects_not_on_gke() -> None:
27 | assert not _gke.on_gke()
28 |
29 |
30 | def test_detects_host_id(fake_get_metadata: MagicMock) -> None:
31 | fake_get_metadata.return_value = {"instance": {"id": 12345}}
32 | assert _gke.host_id() == "12345"
33 |
34 |
35 | def test_detects_cluster_name(fake_get_metadata: MagicMock) -> None:
36 | fake_get_metadata.return_value = {
37 | "instance": {"attributes": {"cluster-name": "fake"}}
38 | }
39 | assert _gke.cluster_name() == "fake"
40 |
41 |
42 | def test_detects_zone(fake_get_metadata: MagicMock) -> None:
43 | fake_get_metadata.return_value = {
44 | "instance": {"attributes": {"cluster-location": "us-east4-b"}}
45 | }
46 | zone_or_region = _gke.availability_zone_or_region()
47 | assert zone_or_region.type == "zone"
48 | assert zone_or_region.value == "us-east4-b"
49 |
50 |
51 | def test_detects_region(fake_get_metadata: MagicMock) -> None:
52 | fake_get_metadata.return_value = {
53 | "instance": {"attributes": {"cluster-location": "us-east4"}}
54 | }
55 | zone_or_region = _gke.availability_zone_or_region()
56 | assert zone_or_region.type == "region"
57 | assert zone_or_region.value == "us-east4"
58 |
59 |
60 | def test_throws_for_invalid_cluster_location(
61 | fake_get_metadata: MagicMock,
62 | ) -> None:
63 | fake_get_metadata.return_value = {
64 | "instance": {"attributes": {"cluster-location": "invalid"}}
65 | }
66 |
67 | with pytest.raises(
68 | Exception, match="unrecognized format for cluster location"
69 | ):
70 | _gke.availability_zone_or_region()
71 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [tool.black]
2 | line-length = 79
3 |
--------------------------------------------------------------------------------
/samples/instrumentation-quickstart/.dockerignore:
--------------------------------------------------------------------------------
1 | integrationtest/
2 |
--------------------------------------------------------------------------------
/samples/instrumentation-quickstart/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.12-slim
2 | COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
3 | WORKDIR /usr/src/app
4 | COPY . .
5 | RUN uv sync --frozen
6 | CMD uv run gunicorn -b 0.0.0.0:8080 -w 4 'app:app' 2>&1 | tee /var/log/app.log
7 |
--------------------------------------------------------------------------------
/samples/instrumentation-quickstart/app.py:
--------------------------------------------------------------------------------
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 | import logging
16 | import time
17 | from random import randint, uniform
18 |
19 | import requests
20 | from flask import Flask, url_for
21 | from opentelemetry.instrumentation.flask import FlaskInstrumentor
22 | from opentelemetry.instrumentation.requests import RequestsInstrumentor
23 |
24 | from gcp_logging import setup_structured_logging
25 | from setup_opentelemetry import setup_opentelemetry
26 |
27 | # [START opentelemetry_instrumentation_main]
28 | logger = logging.getLogger(__name__)
29 |
30 | # Initialize OpenTelemetry Python SDK and structured logging
31 | setup_opentelemetry()
32 | setup_structured_logging()
33 |
34 | app = Flask(__name__)
35 |
36 | # Add instrumentation
37 | FlaskInstrumentor().instrument_app(app)
38 | RequestsInstrumentor().instrument()
39 | # [END opentelemetry_instrumentation_main]
40 |
41 |
42 | # [START opentelemetry_instrumentation_handle_multi]
43 | @app.route("/multi")
44 | def multi():
45 | """Handle an http request by making 3-7 http requests to the /single endpoint."""
46 | sub_requests = randint(3, 7)
47 | logger.info("handle /multi request", extra={"subRequests": sub_requests})
48 | for _ in range(sub_requests):
49 | requests.get(url_for("single", _external=True))
50 | return "ok"
51 |
52 |
53 | # [END opentelemetry_instrumentation_handle_multi]
54 |
55 |
56 | # [START opentelemetry_instrumentation_handle_single]
57 | @app.route("/single")
58 | def single():
59 | """Handle an http request by sleeping for 100-200 ms, and write the number of seconds slept as the response."""
60 | duration = uniform(0.1, 0.2)
61 | logger.info("handle /single request", extra={"duration": duration})
62 | time.sleep(duration)
63 | return f"slept {duration} seconds"
64 |
65 |
66 | # [END opentelemetry_instrumentation_handle_single]
67 |
--------------------------------------------------------------------------------
/samples/instrumentation-quickstart/cloudbuild-integration.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 | - name: golang:1.23
17 | dir: samples/instrumentation-quickstart/integrationtest
18 | env:
19 | - COMPOSE_OVERRIDE_FILE=../docker-compose.cloudbuild.yaml
20 | # https://github.com/testcontainers/testcontainers-go/issues/2754
21 | - TESTCONTAINERS_RYUK_CONNECTION_TIMEOUT=10m
22 | - TESTCONTAINERS_RYUK_RECONNECTION_TIMEOUT=10m
23 | script: go test -v
24 |
25 | logsBucket: gs://opentelemetry-ops-e2e-cloud-build-logs
26 | options:
27 | machineType: E2_HIGHCPU_8
28 |
--------------------------------------------------------------------------------
/samples/instrumentation-quickstart/docker-compose.cloudbuild.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 | # This compose file is only used for integration tests in Cloud Build
16 |
17 | version: "3"
18 |
19 | networks:
20 | # Make containers use default Cloud Build network for ADC
21 | # https://cloud.google.com/build/docs/build-config-file-schema#network
22 | default:
23 | name: cloudbuild
24 | external: true
25 |
--------------------------------------------------------------------------------
/samples/instrumentation-quickstart/docker-compose.creds.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 | # Use this compose file along with docker-compose.yaml to pass a credentials file from the host
16 | # into the collector container:
17 | #
18 | # ```
19 | # GOOGLE_CLOUD_PROJECT="otel-quickstart-demos" \
20 | # GOOGLE_APPLICATION_CREDENTIALS="$HOME/.config/gcloud/application_default_credentials.json" \
21 | # USERID="$(id -u)" \
22 | # docker compose -f docker-compose.yaml -f docker-compose.creds.yaml up --abort-on-container-exit
23 | # ```
24 |
25 | version: "3"
26 |
27 | services:
28 | otelcol:
29 | # If the collector does not have permission to read the mounted volumes, set
30 | # USERID=$(id -u) to run the container as the current user
31 | user: $USERID
32 | volumes:
33 | - ${GOOGLE_APPLICATION_CREDENTIALS?}:${GOOGLE_APPLICATION_CREDENTIALS}:ro
34 | environment:
35 | - GOOGLE_APPLICATION_CREDENTIALS
--------------------------------------------------------------------------------
/samples/instrumentation-quickstart/docker-compose.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 | version: "3"
16 |
17 | services:
18 | app:
19 | build: .
20 | environment:
21 | - OTEL_EXPORTER_OTLP_ENDPOINT=http://otelcol:4318
22 | - OTEL_SERVICE_NAME=otel-quickstart-python
23 | - OTEL_METRIC_EXPORT_INTERVAL=5000
24 | - OTEL_EXPORTER_OTLP_METRICS_DEFAULT_HISTOGRAM_AGGREGATION=base2_exponential_bucket_histogram
25 | volumes:
26 | - logs:/var/log:rw
27 | depends_on:
28 | - "otelcol"
29 | ports:
30 | - 8080
31 | otelcol:
32 | image: otel/opentelemetry-collector-contrib:0.115.1
33 | volumes:
34 | - ./otel-collector-config.yaml:/etc/otelcol-contrib/config.yaml:ro
35 | - logs:/var/log:ro
36 | environment:
37 | - GOOGLE_CLOUD_PROJECT
38 | - GOOGLE_CLOUD_QUOTA_PROJECT
39 | ports:
40 | # Collector prometheus port. The metrics are checked in tests
41 | - 8888
42 | loadgen:
43 | image: golang:1.21
44 | command:
45 | [
46 | "go",
47 | "run",
48 | "github.com/rakyll/hey@latest",
49 | "-c=2",
50 | "-q=1",
51 | "http://app:8080/multi",
52 | ]
53 | depends_on:
54 | - "app"
55 | volumes:
56 | logs:
57 |
--------------------------------------------------------------------------------
/samples/instrumentation-quickstart/gcp_logging.py:
--------------------------------------------------------------------------------
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 | import logging
16 | from datetime import datetime
17 | from typing import Optional
18 |
19 | from opentelemetry.instrumentation.logging import LoggingInstrumentor
20 | from pythonjsonlogger import jsonlogger
21 |
22 |
23 | # We override JsonFormatter.formatTime() instead of using the datefmt strftime parameter
24 | # because it does not support microsecond precision.
25 |
26 |
27 | # [START opentelemetry_instrumentation_setup_logging]
28 | class JsonFormatter(jsonlogger.JsonFormatter):
29 | def formatTime(self, record: logging.LogRecord, datefmt: Optional[str] = None):
30 | # Format the timestamp as RFC 3339 with microsecond precision
31 | isoformat = datetime.fromtimestamp(record.created).isoformat()
32 | return f"{isoformat}Z"
33 |
34 |
35 | def setup_structured_logging() -> None:
36 | LoggingInstrumentor().instrument()
37 |
38 | log_handler = logging.StreamHandler()
39 | formatter = JsonFormatter(
40 | "%(asctime)s %(levelname)s %(message)s %(otelTraceID)s %(otelSpanID)s %(otelTraceSampled)s",
41 | rename_fields={
42 | "levelname": "severity",
43 | "asctime": "timestamp",
44 | "otelTraceID": "logging.googleapis.com/trace",
45 | "otelSpanID": "logging.googleapis.com/spanId",
46 | "otelTraceSampled": "logging.googleapis.com/trace_sampled",
47 | },
48 | )
49 | log_handler.setFormatter(formatter)
50 | logging.basicConfig(
51 | level=logging.INFO,
52 | handlers=[log_handler],
53 | )
54 |
55 |
56 | # [END opentelemetry_instrumentation_setup_logging]
57 |
--------------------------------------------------------------------------------
/samples/instrumentation-quickstart/integrationtest/quickstart_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 | // Tests that docker compose services come up and that metrics, logs, and traces are
16 | // successfully sent from the collector to GCP. See
17 | // https://github.com/GoogleCloudPlatform/opentelemetry-operations-e2e-testing/blob/main/quickstarttest/README.md
18 | // for details
19 |
20 | package integrationtest
21 |
22 | import (
23 | "testing"
24 |
25 | "github.com/GoogleCloudPlatform/opentelemetry-operations-e2e-testing/quickstarttest"
26 | )
27 |
28 | func TestApp(t *testing.T) {
29 | quickstarttest.InstrumentationQuickstartTest(t, "..")
30 | }
31 |
--------------------------------------------------------------------------------
/samples/instrumentation-quickstart/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "instrumentation-quickstart"
3 | version = "0.1.0"
4 | description = "A Flask app instrumented with OpenTelemetry and structured logging for GCP"
5 | readme = "README.md"
6 | requires-python = ">=3.9"
7 | dependencies = [
8 | "flask>=3.1.0",
9 | "gunicorn>=23.0.0",
10 | "opentelemetry-api>=1.29.0",
11 | "opentelemetry-exporter-otlp-proto-http>=1.29.0",
12 | "opentelemetry-instrumentation-flask>=0.50b0",
13 | "opentelemetry-instrumentation-logging>=0.50b0",
14 | "opentelemetry-instrumentation-requests>=0.50b0",
15 | "opentelemetry-sdk>=1.29.0",
16 | "python-json-logger>=3.2.0",
17 | "requests>=2.32.3",
18 | ]
19 |
--------------------------------------------------------------------------------
/samples/instrumentation-quickstart/setup_opentelemetry.py:
--------------------------------------------------------------------------------
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 | import os
16 |
17 | from opentelemetry import _events as events
18 | from opentelemetry import _logs as logs
19 | from opentelemetry import metrics, trace
20 | from opentelemetry.exporter.otlp.proto.http._log_exporter import OTLPLogExporter
21 | from opentelemetry.exporter.otlp.proto.http.metric_exporter import OTLPMetricExporter
22 | from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
23 | from opentelemetry.sdk._events import EventLoggerProvider
24 | from opentelemetry.sdk._logs import LoggerProvider
25 | from opentelemetry.sdk._logs.export import BatchLogRecordProcessor
26 | from opentelemetry.sdk.metrics import MeterProvider
27 | from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
28 | from opentelemetry.sdk.resources import SERVICE_INSTANCE_ID, Resource
29 | from opentelemetry.sdk.trace import TracerProvider
30 | from opentelemetry.sdk.trace.export import BatchSpanProcessor
31 |
32 |
33 | # [START opentelemetry_instrumentation_setup_opentelemetry]
34 | def setup_opentelemetry() -> None:
35 | resource = Resource.create(
36 | attributes={
37 | # Use the PID as the service.instance.id to avoid duplicate timeseries
38 | # from different Gunicorn worker processes.
39 | SERVICE_INSTANCE_ID: f"worker-{os.getpid()}",
40 | }
41 | )
42 |
43 | # Set up OpenTelemetry Python SDK
44 | tracer_provider = TracerProvider(resource=resource)
45 | tracer_provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter()))
46 | trace.set_tracer_provider(tracer_provider)
47 |
48 | logger_provider = LoggerProvider(resource=resource)
49 | logger_provider.add_log_record_processor(BatchLogRecordProcessor(OTLPLogExporter()))
50 | logs.set_logger_provider(logger_provider)
51 |
52 | event_logger_provider = EventLoggerProvider(logger_provider)
53 | events.set_event_logger_provider(event_logger_provider)
54 |
55 | reader = PeriodicExportingMetricReader(OTLPMetricExporter())
56 | meter_provider = MeterProvider(metric_readers=[reader], resource=resource)
57 | metrics.set_meter_provider(meter_provider)
58 |
59 |
60 | # [END opentelemetry_instrumentation_setup_opentelemetry]
61 |
--------------------------------------------------------------------------------
/samples/langgraph-sql-agent/.python-version:
--------------------------------------------------------------------------------
1 | 3.13
2 |
--------------------------------------------------------------------------------
/samples/langgraph-sql-agent/README.md:
--------------------------------------------------------------------------------
1 | # OpenTelemetry LangGraph instrumentation example
2 |
3 |
4 |
5 | This sample is a LangGraph agent instrumented with OpenTelemetry to send traces and logs with
6 | GenAI prompts and responses, and metrics to Google Cloud Observability.
7 |
8 | The Agent is a SQL expert that has full access to an ephemeral SQLite database. The database is
9 | initially empty. It is built with the the LangGraph prebuilt [ReAct
10 | Agent](https://langchain-ai.github.io/langgraph/agents/agents/#basic-configuration#code) and the
11 | [SQLDatabaseToolkit](https://python.langchain.com/docs/integrations/tools/sql_database/).
12 |
13 | ## APIs and Permissions
14 |
15 | Enable the relevant Cloud Observability APIs if they aren't already enabled.
16 | ```sh
17 | gcloud services enable telemetry.googleapis.com logging.googleapis.com monitoring.googleapis.com cloudtrace.googleapis.com
18 | ```
19 |
20 | This sample writes to Cloud Logging, Cloud Monitoring, and Cloud Trace. Grant yourself the
21 | following roles to run the example:
22 | - `roles/logging.logWriter` – see https://cloud.google.com/logging/docs/access-control#permissions_and_roles
23 | - `roles/monitoring.metricWriter` – see https://cloud.google.com/monitoring/access-control#predefined_roles
24 | - `roles/telemetry.writer` – see https://cloud.google.com/trace/docs/iam#telemetry-roles
25 |
26 | ## Running the example
27 |
28 | The sample can easily be run in Cloud Shell. You can also use
29 | [Application Default Credentials][ADC] locally. Clone and set environment variables:
30 | ```sh
31 | git clone https://github.com/GoogleCloudPlatform/opentelemetry-operations-python.git
32 | cd opentelemetry-operations-python/samples/langgraph-sql-agent
33 |
34 | # Capture GenAI prompts and responses
35 | export OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=true
36 | # Capture application logs automatically
37 | export OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED=true
38 | ```
39 |
40 | Create a virtual environment and run the sample:
41 | ```sh
42 | python -m venv venv/
43 | source venv/bin/activate
44 | pip install -r requirements.txt
45 | python main.py
46 | ```
47 |
48 | Alternatively if you have [`uv`](https://docs.astral.sh/uv/) installed:
49 |
50 | ```sh
51 | uv run main.py
52 | ```
53 |
54 | ## Viewing the results
55 |
56 | To view the generated traces with [Generative AI
57 | events](https://cloud.google.com/trace/docs/finding-traces#view_generative_ai_events) in the
58 | GCP console, use the [Trace Explorer](https://cloud.google.com/trace/docs/finding-traces). Filter for spans named `invoke agent`.
59 |
60 | [ADC]: https://cloud.google.com/docs/authentication/application-default-credentials
61 |
--------------------------------------------------------------------------------
/samples/langgraph-sql-agent/patched_vertexai.py:
--------------------------------------------------------------------------------
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 | from __future__ import annotations
16 |
17 | from typing import Any
18 |
19 | from google.cloud.aiplatform_v1.types import (
20 | GenerateContentRequest as v1GenerateContentRequest,
21 | )
22 | from google.cloud.aiplatform_v1beta1.types import (
23 | GenerateContentRequest,
24 | )
25 | from langchain_core.messages import (
26 | BaseMessage,
27 | )
28 | from langchain_google_vertexai import ChatVertexAI
29 |
30 |
31 | class PatchedChatVertexAI(ChatVertexAI):
32 | def _prepare_request_gemini(
33 | self, messages: list[BaseMessage], *args: Any, **kwargs: Any
34 | ) -> v1GenerateContentRequest | GenerateContentRequest:
35 | # See https://github.com/langchain-ai/langchain-google/issues/886
36 | #
37 | # Filter out any blocked messages with no content which can appear if you have a blocked
38 | # message from finish_reason SAFETY:
39 | #
40 | # AIMessage(
41 | # content="",
42 | # additional_kwargs={},
43 | # response_metadata={
44 | # "is_blocked": True,
45 | # "safety_ratings": [ ... ],
46 | # "finish_reason": "SAFETY",
47 | # },
48 | # ...
49 | # )
50 | #
51 | # These cause `google.api_core.exceptions.InvalidArgument: 400 Unable to submit request
52 | # because it must include at least one parts field`
53 |
54 | messages = [
55 | message
56 | for message in messages
57 | if not message.response_metadata.get("is_blocked", False)
58 | ]
59 | return super()._prepare_request_gemini(messages, *args, **kwargs)
60 |
--------------------------------------------------------------------------------
/samples/langgraph-sql-agent/pyproject.toml:
--------------------------------------------------------------------------------
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 | [project]
16 | name = "langgraph-sql-agent"
17 | version = "0.1.0"
18 | description = "A LangGraph ReAct agent that can run queries on an ephemeral SQLite database"
19 | readme = "README.md"
20 | requires-python = ">=3.12"
21 | dependencies = [
22 | "langchain-community>=0.3.16",
23 | "langchain-google-vertexai>=2.0.7",
24 | "langgraph>=0.4.3",
25 | "opentelemetry-exporter-gcp-logging>=1.9.0a0",
26 | "opentelemetry-exporter-gcp-monitoring>=1.9.0a0",
27 | "opentelemetry-exporter-otlp-proto-grpc>=1.33.0",
28 | "opentelemetry-instrumentation-httpx>=0.54b0",
29 | "opentelemetry-instrumentation-requests>=0.54b0",
30 | "opentelemetry-instrumentation-sqlite3>=0.54b0",
31 | "opentelemetry-instrumentation-vertexai>=2.0b0",
32 | "rich>=14.0.0",
33 | ]
34 |
--------------------------------------------------------------------------------
/samples/langgraph-sql-agent/utils.py:
--------------------------------------------------------------------------------
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 | from typing import Iterable
16 |
17 | from langchain_core.messages.base import BaseMessage
18 | from rich.console import Console
19 | from rich.markdown import Markdown
20 |
21 | console = Console()
22 |
23 |
24 | def render_messages(messages: Iterable[BaseMessage]) -> None:
25 | for message in messages:
26 | _render_message(message)
27 | print_markdown("---")
28 |
29 |
30 | def _render_message(message: BaseMessage) -> None:
31 | # Filter out tool calls
32 | if message.type not in ("human", "ai"):
33 | return
34 |
35 | content = (
36 | message.content
37 | if isinstance(message.content, str)
38 | else message.content[-1]["text"]
39 | ).strip()
40 |
41 | # Response was probably blocked by a harm category, go check the trace for details
42 | if message.response_metadata.get("is_blocked", False):
43 | console.print("❌ Response blocked, try again")
44 |
45 | if not content:
46 | return
47 |
48 | if message.type == "human":
49 | print_markdown(f"👤 User:\n{content}")
50 | else:
51 | print_markdown(f"🤖 Agent:\n{content}")
52 |
53 |
54 | def print_markdown(markdown: str) -> None:
55 | console.print(Markdown(markdown))
56 |
57 |
58 | def ask_prompt() -> str:
59 | return console.input("[bold magenta]Talk to the SQL agent >> [/]")
60 |
--------------------------------------------------------------------------------
/samples/otlpmetric/README.md:
--------------------------------------------------------------------------------
1 | ### OTLP Export Sample with GCP Auth
2 | This example shows how to send metrics to an OTLP (OpenTelemetry Protocol) endpoint that is protected by GCP authentication. The sample showcases the metric export using gRPC.
3 |
4 | #### Installation
5 | Install the dependencies and libraries required to run the samples:
6 |
7 | ```sh
8 | # Move to the sample repository
9 | cd samples/otlpmetric
10 |
11 | pip install -r requirements.txt
12 | ```
13 |
14 | #### Prerequisites
15 | Get Google credentials on your machine:
16 |
17 | ```sh
18 | gcloud auth application-default login
19 | ```
20 |
21 | #### Run the Sample
22 | ```sh
23 | # export necessary OTEL environment variables
24 | export PROJECT_ID=
25 | export OTEL_EXPORTER_OTLP_ENDPOINT=
26 | export OTEL_RESOURCE_ATTRIBUTES="gcp.project_id=$PROJECT_ID,service.name=otlp-sample,service.instance.id=1"
27 |
28 | # from the samples/otlpmetric repository
29 | python3 example.py
30 | ```
31 |
--------------------------------------------------------------------------------
/samples/otlpmetric/example.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # Copyright 2025 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 | import time
17 |
18 | import google.auth
19 | import google.auth.transport.grpc
20 | import google.auth.transport.requests
21 | import grpc
22 | from google.auth.transport.grpc import AuthMetadataPlugin
23 | from opentelemetry import metrics
24 | from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import (
25 | OTLPMetricExporter,
26 | )
27 | from opentelemetry.resourcedetector.gcp_resource_detector._detector import (
28 | GoogleCloudResourceDetector,
29 | )
30 | from opentelemetry.sdk.resources import SERVICE_NAME, Resource, get_aggregated_resources
31 | from opentelemetry.sdk.metrics import MeterProvider
32 | from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
33 |
34 | """
35 | This is a sample script that exports OTLP metrics encoded as protobufs via gRPC.
36 | """
37 |
38 | credentials, project_id = google.auth.default()
39 | request = google.auth.transport.requests.Request()
40 | resource = get_aggregated_resources(
41 | [GoogleCloudResourceDetector(raise_on_error=True)]
42 | )
43 |
44 | auth_metadata_plugin = AuthMetadataPlugin(
45 | credentials=credentials, request=request
46 | )
47 | channel_creds = grpc.composite_channel_credentials(
48 | grpc.ssl_channel_credentials(),
49 | grpc.metadata_call_credentials(auth_metadata_plugin),
50 | )
51 |
52 | exporter = OTLPMetricExporter(credentials=channel_creds)
53 | reader = PeriodicExportingMetricReader(exporter)
54 | provider = MeterProvider(metric_readers=[reader],resource=resource)
55 | meter = provider.get_meter("gcp.otlp.sample")
56 | counter = meter.create_counter("sample.otlp.counter")
57 |
58 |
59 | def do_work():
60 | counter.add(1)
61 | # do some work that the 'counter' will track
62 | print("doing some work...")
63 |
64 |
65 | def do_work_repeatedly():
66 | try:
67 | while True:
68 | do_work()
69 | time.sleep(1)
70 | except KeyboardInterrupt:
71 | print("\nKeyboard Interrupt: Stopping work.")
72 |
73 |
74 | do_work_repeatedly()
75 |
--------------------------------------------------------------------------------
/samples/otlpmetric/requirements.txt:
--------------------------------------------------------------------------------
1 | # Dependencies require for trace export samples
2 | opentelemetry-api==1.24.0
3 | opentelemetry-sdk==1.24.0
4 | google-auth==2.18.1
5 | opentelemetry-exporter-otlp-proto-grpc==1.24.0
6 | grpcio==1.63.0
7 | opentelemetry-resourcedetector-gcp==1.8.0
8 |
--------------------------------------------------------------------------------
/samples/otlptrace/README.md:
--------------------------------------------------------------------------------
1 | ### OTLP Export Sample with GCP Auth
2 | This example shows how to send traces to an OTLP (OpenTelemetry Protocol) endpoint that is protected by GCP authentication. The sample showcases the trace export using:
3 | - gRPC
4 | - http with protobuf
5 |
6 | #### Installation
7 | Install the dependencies and libraries required to run the samples:
8 |
9 | ```sh
10 | # Move to the sample repository
11 | cd samples/otlptrace
12 |
13 | pip install -r requirements.txt
14 | ```
15 |
16 | #### Prerequisites
17 | Get Google credentials on your machine:
18 |
19 | ```sh
20 | gcloud auth application-default login
21 | ```
22 |
23 | #### Run the Sample
24 | ```sh
25 | # export necessary OTEL environment variables
26 | export OTEL_RESOURCE_ATTRIBUTES="gcp.project_id="
27 |
28 | # from the samples/otlptrace repository
29 | python3 example_grpc.py
30 | ```
31 | Other variations of the sample:
32 | - `python3 example_http.py` - will run a program that will export traces using http/protobuf.
33 |
--------------------------------------------------------------------------------
/samples/otlptrace/example_grpc.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
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 | import time
17 |
18 | import google.auth
19 | import google.auth.transport.grpc
20 | import google.auth.transport.requests
21 | import grpc
22 | from google.auth.transport.grpc import AuthMetadataPlugin
23 | from opentelemetry import trace
24 | from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import (
25 | OTLPSpanExporter,
26 | )
27 | from opentelemetry.sdk.resources import SERVICE_NAME, Resource
28 | from opentelemetry.sdk.trace import TracerProvider
29 | from opentelemetry.sdk.trace.export import BatchSpanProcessor
30 |
31 | """
32 | This is a sample script that exports OTLP traces encoded as protobufs via gRPC.
33 | """
34 |
35 | credentials, _ = google.auth.default()
36 | request = google.auth.transport.requests.Request()
37 | resource = Resource.create(attributes={SERVICE_NAME: "otlp-gcp-grpc-sample"})
38 |
39 | auth_metadata_plugin = AuthMetadataPlugin(credentials=credentials, request=request)
40 | channel_creds = grpc.composite_channel_credentials(
41 | grpc.ssl_channel_credentials(),
42 | grpc.metadata_call_credentials(auth_metadata_plugin),
43 | )
44 |
45 | trace_provider = TracerProvider(resource=resource)
46 | processor = BatchSpanProcessor(
47 | OTLPSpanExporter(
48 | credentials=channel_creds,
49 | endpoint="https://telemetry.googleapis.com:443/v1/traces",
50 | )
51 | )
52 | trace_provider.add_span_processor(processor)
53 | trace.set_tracer_provider(trace_provider)
54 | tracer = trace.get_tracer("my.tracer.name")
55 |
56 |
57 | def do_work():
58 | with tracer.start_as_current_span("span-grpc") as span:
59 | # do some work that 'span' will track
60 | print("doing some work...")
61 | # When the 'with' block goes out of scope, 'span' is closed for you
62 |
63 |
64 | def do_work_repeatedly():
65 | try:
66 | while True:
67 | do_work()
68 | time.sleep(10)
69 | except KeyboardInterrupt:
70 | print("\nKeyboard Interrupt: Stopping work.")
71 |
72 |
73 | do_work_repeatedly()
74 |
--------------------------------------------------------------------------------
/samples/otlptrace/example_http.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
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 | import google.auth
17 | import google.auth.transport.requests
18 | from opentelemetry import trace
19 | from opentelemetry.exporter.otlp.proto.http.trace_exporter import (
20 | OTLPSpanExporter,
21 | )
22 | from google.auth.transport.requests import AuthorizedSession
23 | from opentelemetry.sdk.resources import SERVICE_NAME, Resource
24 | from opentelemetry.sdk.trace import TracerProvider
25 | from opentelemetry.sdk.trace.export import BatchSpanProcessor
26 |
27 | credentials, _ = google.auth.default()
28 | trace_provider = TracerProvider(
29 | resource=Resource.create(attributes={SERVICE_NAME: "otlp-gcp-http-sample"})
30 | )
31 | processor = BatchSpanProcessor(
32 | OTLPSpanExporter(
33 | session=AuthorizedSession(credentials),
34 | endpoint="https://telemetry.googleapis.com:443/v1/traces",
35 | )
36 | )
37 | trace_provider.add_span_processor(processor)
38 | trace.set_tracer_provider(trace_provider)
39 | tracer = trace.get_tracer("my.tracer.name")
40 |
41 |
42 | def do_work():
43 | with tracer.start_as_current_span("span-http") as span:
44 | # do some work that 'span' will track
45 | print("doing some work...")
46 | # When the 'with' block goes out of scope, 'span' is closed for you
47 |
48 |
49 | do_work()
50 |
--------------------------------------------------------------------------------
/samples/otlptrace/requirements.txt:
--------------------------------------------------------------------------------
1 | # Dependencies require for trace export samples
2 | opentelemetry-api==1.24.0
3 | opentelemetry-sdk==1.24.0
4 | google-auth==2.18.1
5 | opentelemetry-exporter-otlp-proto-http==1.24.0
6 | opentelemetry-exporter-otlp-proto-grpc==1.24.0
7 | grpcio==1.63.0
8 |
--------------------------------------------------------------------------------
/test-common/MANIFEST.in:
--------------------------------------------------------------------------------
1 | graft src
2 | graft tests
3 | global-exclude *.pyc
4 | global-exclude *.pyo
5 | global-exclude __pycache__/*
6 | include MANIFEST.in
7 |
--------------------------------------------------------------------------------
/test-common/setup.cfg:
--------------------------------------------------------------------------------
1 | [metadata]
2 | name = test-common
3 | description = Test utilities used across packages in this repo
4 |
5 | [options]
6 | package_dir=
7 | =src
8 | packages=find_namespace:
9 | install_requires =
10 |
11 | [options.packages.find]
12 | where = src
13 |
14 |
--------------------------------------------------------------------------------
/test-common/setup.py:
--------------------------------------------------------------------------------
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 | import setuptools
16 |
17 | setuptools.setup()
18 |
--------------------------------------------------------------------------------
/test-common/src/test_common/__init__.py:
--------------------------------------------------------------------------------
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 | """Test utilities used across packages
16 |
17 | This code is only used in other modules' tests
18 | """
19 |
20 |
21 | from .base_exporter_integration_test import BaseExporterIntegrationTest
22 |
23 | try:
24 | from time import time_ns as _time_ns
25 | except ImportError:
26 | from time import time
27 |
28 | def _time_ns() -> int:
29 | return int(time() * 1e9)
30 |
31 |
32 | def time_ns() -> int:
33 | """
34 | Use time.time_ns if it is available or convert time.time() to nanoseconds
35 | (lower resolution)
36 |
37 | TODO: remove when python3.6 is dropped
38 | """
39 | return _time_ns()
40 |
41 |
42 | __all__ = ["time_ns", "BaseExporterIntegrationTest"]
43 |
44 |
--------------------------------------------------------------------------------
/test-common/src/test_common/base_exporter_integration_test.py:
--------------------------------------------------------------------------------
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 | import socket
16 | import subprocess
17 | import unittest
18 |
19 |
20 | class BaseExporterIntegrationTest(unittest.TestCase):
21 | def setUp(self) -> None:
22 | self.project_id = "TEST-PROJECT"
23 |
24 | # Find a free port to spin up our server at.
25 | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
26 | sock.bind(("localhost", 0))
27 | self.address = "localhost:" + str(sock.getsockname()[1])
28 | sock.close()
29 |
30 | # Start the mock server.
31 | args = ["mock_server", "-address", self.address]
32 | self.mock_server_process = subprocess.Popen(
33 | args, stderr=subprocess.PIPE, stdout=subprocess.PIPE
34 | )
35 | # Block until the mock server starts (it will output the address after starting).
36 | if (
37 | self.mock_server_process.stderr is None
38 | or self.mock_server_process.stdout is None
39 | ):
40 | raise RuntimeError("stderr or stdout is None")
41 | self.mock_server_process.stderr.readline()
42 |
43 | def tearDown(self) -> None:
44 | self.mock_server_process.kill()
45 | if (
46 | self.mock_server_process.stderr is None
47 | or self.mock_server_process.stdout is None
48 | ):
49 | raise RuntimeError("stderr or stdout is None")
50 | stdout = self.mock_server_process.stdout.read().decode()
51 | stderr = self.mock_server_process.stderr.read().decode()
52 | if stderr or stdout:
53 | self.fail(
54 | "Mock server should not have had any output, got stdout:\n%s\n\nstderr:\n%s",
55 | stdout,
56 | stderr,
57 | )
58 |
--------------------------------------------------------------------------------