Compare commits

...

325 Commits
stable ... main

Author SHA1 Message Date
OpenTelemetry Bot 109173fec7
Update version to 1.36.0.dev/0.57b0.dev (#3633) 2025-07-11 14:35:47 +02:00
Emídio Neto b63ca133be
Update CHANGELOG.md (#3632) 2025-07-11 13:33:10 +02:00
OpenTelemetry Bot 1f78c8acff
Sort contributor listings and remove affiliation from emeriti (#3627)
Co-authored-by: otelbot <197425009+otelbot@users.noreply.github.com>
2025-07-11 09:20:33 +00:00
Mike Dearman 49fa53131d
Add tornado WebSocketHandler instrumentation support (#3498)
* Add tornado WebSocketHandler instrumentation support. (https://github.com/open-telemetry/opentelemetry-python-contrib/issues/2761)

* Linting

* Update CHANGELOG.md

* Apply refactor changes from #3582

---------

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-07-10 17:41:36 +02:00
OpenTelemetry Bot 333fc5dcb4
Update opentelemetry-instrumentation-google-genai version to v0.4b0 (#3619) 2025-07-08 14:46:08 -04:00
warmagedon007 80c357bb16
pika: added instrumentation for pika.connection.Connection and pika.c… (#3584)
* pika: added instrumentation for pika.connection.Connection and pika.channel.Channel, thus added instrumentation support to all SelectConnection adapters.

* updated changelog.

---------

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-07-07 08:17:31 +00:00
Prajna Paramita Biswal 3c4d18cc13
ref(mysql): remove SpanAttributes (#3616)
* ref(mysql): remove SpanAttributes

* fix imports
2025-07-07 09:43:47 +02:00
Radoslav Kirilov b74633a552
feat(pymongo): aggregate and getMore capture statements support (#3601)
* feat(pymongo): aggregate and getMore capture statements

* chore: update changelog

* fix: tests

* fix: proper MockCommand and expectations

* chore: ruff-format
2025-07-02 07:23:51 +00:00
Carlos RC b1c2c7941b
fix excluded_urls in instrumentation-asgi (#3567)
* fix excluded_urls in instrumentation-asgi

* fix ExcludeList or str

* chhangelog

---------

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-07-01 12:33:01 +00:00
rads-1996 b69ebb7224
Redact specific url query string values and url credentials in instrumentations (#3508)
* Updated the instrumentation with aiohttp-server tests for url redaction

* Updated the aiohttp-server implementation and the query redaction logic

* Updated changelog and moved change to unreleased. Updated test files with license header

* Improved formatting

* Fixed failing tests

* Fixed ruff

* Update util/opentelemetry-util-http/src/opentelemetry/util/http/__init__.py

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>

---------

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
2025-07-01 12:26:47 +00:00
Andre Murbach Maidl 6977da3893
Improve asgi instrumentation example (#3576)
* Improve asgi instrumentation example

* Fix indentation of asgi instrumentation example

* Improve type hints of asgi instrumentation example

* Ignore pylint too-many-lines

---------

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-06-30 11:03:50 +02:00
Ezzio Moreira ca079cbc56
feat: change semcov util/opentelemetry-util-http (#3592) 2025-06-30 08:21:28 +00:00
OpenTelemetry Bot 40d8942bf5
Update community member listings (#3595)
* Update community member listings

* Fix outdated community membership link

---------

Co-authored-by: otelbot <197425009+otelbot@users.noreply.github.com>
2025-06-30 08:14:08 +00:00
Emídio Neto 78300e9642
Update CHANGELOG.md (#3593) 2025-06-26 12:01:51 +02:00
shwejan raj c4347e027c
adds NoOpTracerProvider test case for falcon instrumentation (#3382)
Signed-off-by: Shwejan Raj, Bhupathi <Bhupathi.ShwejanRaj@fmr.com>
Signed-off-by: Bhupathi Shwejan Raj <Bhupathi.ShwejanRaj@fmr.com>
2025-06-17 16:16:26 +00:00
f-kanari-safie 0a03c9abf2
refactor(tornado): replaces SpanAttributes by semconv attributes (#3582)
* refactor: fix import paths

* fix imports

---------

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-06-16 12:09:38 +00:00
Andre Murbach Maidl 85dbfe520a
Improve grpc instrumentation examples (#3575) 2025-06-16 09:31:12 +00:00
Andre Murbach Maidl b27225273b
Improve wsgi instrumenation example (#3577) 2025-06-16 09:06:34 +00:00
Andre Murbach Maidl 591051f8bb
Improve pyramid instrumentation example (#3578)
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-06-16 08:42:59 +00:00
Riccardo Magliocchetti 50cdeeee12
resource-detector-containerid: demote failure to read cgroup files to debug (#3579)
* resource-detector-containerid: demote failure to read cgroup files to debug

Make the detection more quiet so we can load it on application not
running on linux machines without spamming logs.

* Add changelog
2025-06-16 10:33:16 +02:00
Riccardo Magliocchetti 04f8899252
docs: update redis-py documentation link (#3581) 2025-06-13 10:01:16 -03:00
OpenTelemetry Bot 59cc34e9f3
Update version to 1.35.0.dev/0.56b0.dev (#3556) 2025-06-04 16:53:03 +02:00
Phillip Verheyden b7301823a0
Allow reraising the root exception if instrumentation fails (#3545)
* Allow reraising the root exception if instrumentation fails

I would rather completely fail startup in my services if instrumentation fails for whatever reason instead of just logging an exception and continuing.

Use case:

from opentelemetry import autoinstrumentation

autoinstrumentation.initialize(swallow_exceptions=False)

* Fix lint

* Type hinting, re-raise original exception

* One more type hint to indicate None return

---------

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-06-04 08:44:45 +00:00
Emídio Neto 4a21b3974b
resource-dector-container: package rename to `opentelemetry-resource-detector-containerid` (#3536)
* resource-dector-container: package rename

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* fix ruff

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* change entrypoint

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* fix

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* fix test

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* fix for entrypoint name

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* add changelog

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

---------

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>
2025-06-04 10:41:38 +02:00
Artem Ziborev 85ea8f382d
refactor(grpc): replace SpanAttributes with semconv attributes (#3540)
* refactor(grpc): replace SpanAttributes with semconv attributes

* refactor(flask): replace SpanAttributes with semconv attributes (fix ruff linting)

---------

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-06-03 15:31:50 +00:00
Sean Hood 8f7bab5337
Fixes container detector for systemd & cgroupv1 with Docker (#3429)
* Fixes container detector for systemd & cgroupv1 with Docker

* Update CHANGELOG

---------

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-06-03 15:27:09 +00:00
Hector Hernandez ccf9cabeee
feat(instrumentation-httpx): Add support for HTTP metrics (#3513)
* Add support for metrics

* Updated changelog

* Update package.py

* generate and lint

* Update

* Update

---------

Co-authored-by: Tammy Baylis <96076570+tammy-baylis-swi@users.noreply.github.com>
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-06-03 14:00:38 +00:00
Dmitriy 701d65b022
feat: support batch (getmany) in aiokafka instrumentation (#3257)
* feat: support batch (getmany) in aiokafka instrumentation

* test: fix unclosed resources and typing

* test: add test_wrap_getmany

* fix: get unique topic list in batch

* fix: update typing, run pyupgrade

* fix: remove json.dumps from SERVER_ADDRESS attribute

* fix pylint

* fix: sync span_kind with spec

* add CHANGELOG entry

* remove changes not from this issue

* move types under TYPE_CHECKING

* move CHANGELOG entry to unreleased

* enable pyright for aiokafka, fix key type

* Update CHANGELOG.md

---------

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
2025-06-03 13:52:00 +00:00
Anuraag (Rag) Agrawal b9a78e7475
opentelemetry-instrumentation-starlette: fix memory leak and double middleware (#3529)
* opentelemetry-instrumentation-starlette: fix memory leak and double middleware

* Changelog

* Update CHANGELOG.md

Co-authored-by: Joe McGinley <116890464+jomcgi@users.noreply.github.com>

---------

Co-authored-by: Joe McGinley <116890464+jomcgi@users.noreply.github.com>
2025-06-03 15:47:35 +02:00
Marc 77325aa89a
fix: respect supress_instrumentation functionality in sqlalchemy instrumentation (#3477)
* respect supress_instrumentation

* update changelog

* Update CHANGELOG.md

Fix changelog after release

---------

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-05-30 16:00:27 +00:00
Naofumi MURATA 6d8becf9ad
feat: respect supress_instrumentation functionality in dbapi instrumentation (#3460)
* respect supress_instrumentation

* update CHANGELOG

* fix link

* update CHANGELOG

---------

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
2025-05-30 17:49:29 +02:00
Andy Vu 6c89a56da5
replaced all uses of spanattributes in wsgi (#3546)
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-05-29 16:09:04 +00:00
Riccardo Magliocchetti 3e0632cb31
opentelemetry-instrumentation-botocore: fix handling of tool input chunked json in bedrock converse_stream (#3544)
* opentelemetry-instrumentation-botocore: fix handling of tool input chunked json in converse_stream

We need to accumulate all the tool input as string before decoding it
otherwise we may end up with invalid json.

* Add changelog

* Remove leftover print

* No need for too-many-statements disable
2025-05-29 09:51:38 +02:00
Srdjan Lulic 7bd0895d01
botocore: add dict type check before parsing tool_use from Bedrock messages (#3548)
Amazon Bedrock tool use extraction logic doesn't agree with som of the use cases (conversation construction), such as the case with pre-created assistant message: 

'messages': [{"role": "user", "content": "Placeholder text."}, {"role": "assistant", "content": "{"}],

This PR addresses this by adding a dict type check on the message content before attempting to get the value of `tool_use`from the content.
2025-05-28 14:17:33 +02:00
Hector Hernandez a912c9e57c
feat(instrumentation-aiohttp-client): Add support for HTTP metrics (#3517)
* Add metrics support

* Update instrumentation/opentelemetry-instrumentation-aiohttp-client/src/opentelemetry/instrumentation/aiohttp_client/__init__.py

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>

* Update instrumentation/opentelemetry-instrumentation-aiohttp-client/src/opentelemetry/instrumentation/aiohttp_client/__init__.py

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>

* Update instrumentation/opentelemetry-instrumentation-aiohttp-client/src/opentelemetry/instrumentation/aiohttp_client/__init__.py

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>

* Adding tests, updating changelog

* Adding server address and port to both spans and metrics

---------

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-05-27 20:41:00 +00:00
wesley 75c73d1e29
refactor aws lambda span (#3541)
* refactor: migrate http_attributes from SpanAttributes to new semantic conventions and refactor tests

* fix precommit linting

* refactor aws lambda to use new semantics

* refactor tests

* update resourceattributes to cloud attrs

* update main for attrs
2025-05-27 20:30:47 +00:00
Joe McGinley a164d37a3c
Chore: Drop support for Python 3.8 (#3399)
Python 3.8 was EoL @ 2024-10-07, our 6 month promise for support ended on 2024-04-07.

Changes:
* Updated basline refs to 3.9
* Removed 3.8 sys.version_info checks
* Fixed botocore test failure
* Applied ruff formatting
2025-05-27 17:26:02 +02:00
Mattias De Charleroy e2ba6d43c0
starlette: Remove maximum version constraint (#3456)
* ISSUE-3317: Remove maximum version constraint on starlette, by fixing unit tests. Fixed some warnings in unit tests.

* Updae changelog

* Implement code review remarks: update starlette dependencies in bootstrap/test-requirements. Use setUp/tearDown iso decorator on test class

* Increase minimal version of starlette to 0.37.2 to have functional 'oldest' tests.

* add uv.lock

* Revert "add uv.lock"

This reverts commit 08df2bee1e.

* Prevent massive changes of uv.lock due to newer uv which adds upload-time keyword

* Update test-requirements.in file of starlette instrumentation

* fixes

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* fix tests

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* increase delta

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* using same delta as fastapi

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* commit uv.lock back

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* Update CHANGELOG.md

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>

* Update CHANGELOG.md

---------

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>
Co-authored-by: emdneto <9735060+emdneto@users.noreply.github.com>
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-05-23 12:22:31 +00:00
wesley 4e42ed674a
refactor(boto): replace uses of SpanAttributes with opentelemetry.semconv.attributes (#3538)
* refactor: migrate http_attributes from SpanAttributes to new semantic conventions and refactor tests

* fix precommit linting

---------

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-05-23 08:55:13 +00:00
Riccardo Magliocchetti 72f437c456
opentelemetry-instrumentation-system-metrics: fix running on Google Cloud Run (#3533)
* opentelemetry-instrumentation-system-metrics: fix running on Google Cloud Run

psutil fails reading context switches fails on Google Cloud Run, so
before setting up the observable counter trying to read the values check
we are actually being able to do so.

* Please pylint
2025-05-23 08:45:33 +00:00
Riccardo Magliocchetti 93353660f6
opentelemetry-instrumentation-urllib3: add explicit http duration buckets for stable semconv (#3518)
* opentelemetry-instrumentation-urllib3: add explicit http duration buckets for stable semconv

* Add Changelog

* Update CHANGELOG.md

---------

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
2025-05-23 08:42:18 +00:00
Riccardo Magliocchetti 1953d97958
opentelemetry-instrumentation-urllib: add explicit http duration buckets for stable semconv (#3519)
* opentelemetry-instrumentation-urllib: add explicit http duration buckets for stable semconv

* Update CHANGELOG.md

---------

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
2025-05-23 08:38:15 +00:00
Srdjan Lulic df275921a9
Ensure spans complete on early stream closure for Bedrock Streaming APIs (#3481)
* Ensure spans end on early stream closure for Bedrock Streaming APIs

* Add changelog

* End span only if it's still recording in stream done callbacks. Assert that span status is unset.

* Extract response output and stream content into helper functions

* Update changelog after 1.33.0 release

* Keep track of bedrock stream ending and close spans accordingly

* Move stream output checks to a single method

* Update CHANGELOG.md

---------

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-05-23 08:33:00 +00:00
Christoph Heger c1a689507b
Refactor redis instrumentation to use semconv incubating attributes (#3534)
* Replaced usage of opentelemetry.semconv.trace with opentelemetry.semconv._incubating.attributes.

* Fixed ruff failure
2025-05-23 08:27:14 +00:00
Christoph Heger b3f98ab936
Replaced usage of SpanAttributes with opentelemetry.semconv._incubating.attributes. (#3535) 2025-05-23 08:13:09 +00:00
Riccardo Magliocchetti dc35754dbd
opentelemetry-instrumentation-falcon: add explicit http duration buckets for stable semconv (#3525) 2025-05-23 08:08:43 +00:00
Riccardo Magliocchetti fa6d972444
opentelemetry-instrumentation-wsgi: add explicit http duration buckets for stable semconv (#3527)
* opentelemetry-instrumentation-wsgi: add explicit http duration buckets for stable semconv

* Please pylint
2025-05-23 08:00:28 +00:00
Riccardo Magliocchetti 5e4b55812a
opentelemetry-instrumentation-asgi: add explicit http duration buckets for stable semconv (#3526)
* opentelemetry-instrumentation-asgi: add explicit http duration buckets for stable semconv

* Please pylint
2025-05-23 07:56:41 +00:00
Riccardo Magliocchetti 680f197515
opentelemetry-instrumentation-flask: add explicit http duration buckets for stable semconv (#3523)
* opentelemetry-instrumentation-flask: add explicit http duration buckets for stable semconv

* Update CHANGELOG.md

* Fix pylint
2025-05-23 07:49:08 +00:00
Riccardo Magliocchetti 1909c913b2
opentelemetry-instrumentation-django: add explicit http duration buckets for stable semconv (#3524)
* opentelemetry-instrumentation-django: add explicit http duration buckets for stable semconv

* Update CHANGELOG.md
2025-05-23 07:42:32 +00:00
Ivana Kellyer f9d9f19aa5
fix(grpc): Allow non-list interceptors (#3520)
* fix(grpc): Support non-list interceptors

The GRPC integration assumes that if interceptors are provided, they will be
a list, when GRPC itself types them as Sequence. With this change, we're
making the codepaths using interceptors more robust by explicitly turning them
into lists before manipulating them.

* Add a changelog entry

* .

* Run ruff

* Simplify
2025-05-23 07:35:46 +00:00
Christoph Heger 0db4d0bb8f
Replaced SpanAttributes with opentelemetry.semconv._incubating.attributes.db_attributes in tests. (#3532) 2025-05-22 16:07:21 +02:00
Emídio Neto 71bfc9550e
Update RELEASING.md (#3522) 2025-05-21 12:18:25 +00:00
Hector Hernandez 38f7413836
Update metric support table to include opentelemetry-instrumentation-aiohttp-server (#3514)
* opentelemetry-instrumentation-aiohttp-server metric support update

* Update

* Lint

* Update instrumentation/opentelemetry-instrumentation-aiohttp-server/src/opentelemetry/instrumentation/aiohttp_server/package.py

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>

* tox generate

* lint

---------

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
2025-05-21 09:56:11 +02:00
Adrian Garcia Badaracco 4d6893e8fa
fastapi: fix wrapping of middlewares (#3012)
* fastapi: fix wrapping of middlewares

* fix import, super

* add test

* changelog

* lint

* lint

* fix

* ci

* fix wip

* fix

* fix

* lint

* lint

* Exit?

* Update test_fastapi_instrumentation.py

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>

* remove break

* fix

* remove dunders

* add test

* lint

* add endpoint to class

* fmt

* pr feedback

* move type ignores

* fix sphinx?

* Update CHANGELOG.md

* update fastapi versions

* fix?

* generate

* stop passing on user-supplied error handler

This prevents potential side effects, such as logging, to be executed
more than once per request handler exception.

* fix ci

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* fix ruff

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* remove unused funcs

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>

* fix lint,ruff

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* fix changelog

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* add changelog note

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* fix conflicts with main

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

---------

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
Co-authored-by: Alexander Dorn <ad@not.one>
Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
2025-05-20 11:00:56 -03:00
Michael Safyan dbdff31220
feat(google-genai): add instrumentation to supplied tool call functions (#3446)
* Begin work to instrument tool calls.

* Add tests as well as the ability to record function details in span attributes.

* Add tests for the tool call wrapper utility.

* Update the changelog.

* Reformat with ruff.

* Switch to dictionary comprehension per lint output.

* Address generic names foo, bar flagged by lint.

* Reformat with ruff.

* Update to record function details only on the span.

* Reformat with ruff.

* Fix lint issue with refactoring improvement.

* Reformat with ruff.

* Improve attribute handling and align with 'execute_tool' span spec.

* Pass through the extra span arguments.

* Fix lint issues.

* Reformat with ruff.

* Update instrumentation-genai/opentelemetry-instrumentation-google-genai/src/opentelemetry/instrumentation/google_genai/tool_call_wrapper.py

---------

Co-authored-by: Aaron Abbott <aaronabbott@google.com>
2025-05-19 18:08:20 +00:00
Riccardo Magliocchetti ef2b5468d5
Fix ruff (#3515) 2025-05-19 09:59:28 -03:00
Prajna Paramita Biswal f21182890a
requests: migrate from SpanAttributes (#3493)
* ref: migrate from SpanAttributes

* B
reverted to SpanAttributes for the SCHEMA_URL

* replace SpanAttributes.SCHEMA_URL

* sort imports

---------

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-05-19 08:26:42 +00:00
Shubhendra Kushwaha ec731581af
refactor(fastapi): replace uses of `SpanAttributes` with `opentelemetry.semconv.attributes` (#3491)
* refactor(fastapi): migrate HTTP_ROUTE from SpanAttributes to new semantic conventions

Replaced usage of `SpanAttributes.HTTP_ROUTE` with `opentelemetry.semconv.attributes.http_attributes.HTTP_ROUTE`
as part of the migration away from `SpanAttributes`.

Refs: #3475

* refactor(fastapi): refactor tests

* refactor(fastapi): remove duplicated import

* sort imports

---------

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-05-19 08:15:49 +00:00
Tamara Dancheva ccdf522626
Refactor asyncpg : replace uses of SpanAttributes with opentelemetry.semconv.attributes (#3505)
* Replace span in asyncpg

* Update instrumentation/opentelemetry-instrumentation-asyncpg/src/opentelemetry/instrumentation/asyncpg/__init__.py

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>

* refactor

---------

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-05-15 19:07:54 +00:00
Almudena Sanz 9e1284687a
replace SpanAttributes by semconv attributes (#3503)
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-05-15 18:54:05 +00:00
Caterina Andreu 1034b746af
Refactor: replace use of SpanAttributes (#3504) 2025-05-15 18:15:44 +00:00
Caterina Andreu 3efd161cb6
Refactor: replace use of SpanAttributes (#3502)
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-05-15 17:58:37 +00:00
Almudena Sanz 99049a9652
replace SpanAttributes by semconv attributes (#3501)
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-05-15 17:21:16 +00:00
Srdjan Lulic 4b9b949dde
Use semantic convention attribute for cloud region for botocore API calls (#3474)
* Update botocore instrumentation to use semantic convention attribute for cloud region

* Update changelog

* Move cloud region attribute to the breaking changes in the changelog

---------

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-05-15 16:41:52 +00:00
Riccardo Magliocchetti dc37067b93
RELEASING: update after label automation in workflows (#3488) 2025-05-15 16:31:22 +00:00
Srdjan Lulic 517257cbef
Fix flaky availability checks in docker-tests by using exponential backoff in the retry mechanism (#3499) 2025-05-15 18:08:38 +02:00
OpenTelemetry Bot 4a1e0ce941
Update version to 1.34.0.dev/0.55b0.dev (#3484) 2025-05-09 17:10:08 +02:00
Emídio Neto 9bc7764139
requests: support explicit_bucket_boundaries_advisory in duration metrics (#3464)
* requests: add explicit_bucket_boundaries_advisory support for duration metrics

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* requests duration histogram stable semconv

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* fix examples

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* add changelog

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* rename buckets variable

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

---------

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-05-09 13:41:37 +00:00
Riccardo Magliocchetti abafc2131f
opentelemetry-exporter-prometheus-remote-write: workaround build failure with PyPy 3.8 (#3480)
Find a version that has a wheel for PyPy 3.8 skipping the failing test
while we bump the baseline to 3.9.
2025-05-09 10:36:11 -03:00
Oleg 2c0033f842
Add redis client only instrumentation (#3143)
* Rough draft of the contribution

* Add connection instrumentation based on the existing pattern.

add a helper function assert_span_count to simplify tests
add unit tests for pipeline hooks

* fix tests to use fake redis

* replace the redis version checks with defines

* Adjust comment and fix one test

* Update documentation with the client method

* Update the changelog

* Update the HTTPX readme to point to proper class method

* Add back the assert_span_count method

* Move the changelog update to the unreleased section

* Remove extra whitespace in the Changelog

* Fix linter complaints

* Remove hasattr assert

* Move the Changelog to Unreleased

* Review comments. Move types to types.py, move some functions to util.py. Tested and verified docs.

* Fix type compatibility

* fix typing and lint

---------

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
2025-05-09 09:13:46 +00:00
Andre Murbach Maidl cc7169cf2c
Improve aiopg instrumentation examples (#3468) 2025-05-07 12:43:03 +00:00
Andre Murbach Maidl 45797ec3a1
Improve aiokafka instrumentation examples (#3466) 2025-05-07 09:46:13 +00:00
Andre Murbach Maidl 5c76d04a35
Improve pymssql instrumentation examples (#3473) 2025-05-07 09:37:50 +00:00
Andre Murbach Maidl 9d41f9bf10
Improve mysqlclient instrumentation examples (#3470)
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-05-07 09:14:03 +00:00
Andre Murbach Maidl 02dc87ef73
Improve pymysql instrumentation examples (#3472) 2025-05-07 10:52:35 +02:00
Srdjan Lulic e6869cdc75
Capture server attributes for botocore API calls (#3448)
* Capture server attributes for botocore API calls

* fix: use typing.Dict for 3.8 compatibility and resolve failing tests

* Update changelog

* Add server and port assertions for Bedrock API calls

* Add server address and port to Bedrock metric attributes

* Add license header and deferred type hint evaluation in utils.py

* Refactor metric attributes creation and add linter suppression (too-many-lines) for bedrock.py

---------

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-04-30 14:29:12 +00:00
Emmanuel Ferdman dec311ff0e
Resolve datetime deprecation warnings (#3433)
* Resolve datetime deprecation warnings

Signed-off-by: Emmanuel Ferdman <emmanuelferdman@gmail.com>

* Resolve datetime deprecation warnings

Signed-off-by: Emmanuel Ferdman <emmanuelferdman@gmail.com>

---------

Signed-off-by: Emmanuel Ferdman <emmanuelferdman@gmail.com>
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-04-30 14:02:51 +00:00
OpenTelemetry Bot da661f6547
Copy changelog updates from package-release/opentelemetry-instrumentation-google-genai/v0.2bx (#3453) 2025-04-29 11:35:15 +02:00
OpenTelemetry Bot afc0d5531d
Update opentelemetry-instrumentation-google-genai version to v0.3b0 (#3443)
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-04-28 15:19:36 +00:00
Emídio Neto 8a83770d7b
fix sha-automation (#3445)
* fix sha-automation

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* use default github_token instead

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

---------

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>
2025-04-28 15:55:03 +02:00
Joe McGinley c6cdbeb51f
Add missing dependency to click / asyncclick instrumentations (#3447)
Using click / asyncclick instrumentation in a project that does not
already depend on opentelemetry-instrumentation raises a module
not found error.

Added opentelemetry-instrumentation as a dependency for click &
asyncclick.
2025-04-28 12:14:34 +02:00
Emídio Neto 7f347e54df
infra: Automate SHA procedure during releases (#3424) 2025-04-24 09:31:08 -08:00
Michael Safyan 369a9f2e00
Include more request configuration options into the span attributes for the Google GenAI SDK instrumentation (#3374)
* Create a utility to simplify recording request attributes.

* Update recording mechanism to record more request options.

* Improve the recording of span request attributes.

* Reformat with ruff.

* Update TODOs to reflect change made here.

* Update changelog now that PR has been created and can be referenced.

* Fix lint issues.

* Reformat with ruff.

* Add more documentation comments requested in the pull request.

* Add tests and comments that provide some additional clarity regarding the flattening logic in response to PR comments.

* Add tests and comments that provide some additional clarity regarding the flattening logic in response to PR comments.

* Handle corner case where flatten function returns compound output.

* Update prefix to match currently proposed SemConv.

* Update to specify attributes from SemConv constants per PR feedback.

* Use an allowlist for dynamic keys per PR feedback.

* Reformat with ruff.

* Fix lint issues.

* Reformat with ruff.

* Handle flattening errors more gracefully.

* Add support for more wildcards in the allowlist.

* Add a clearer type for the flatten functions.

* Simplify 'exclude_keys' initialization per PR feedback.

* Simplify AllowList constructor type annotation per PR feedback.

* Reformat with ruff.

* Resolve lint error concerning too many returns.

* Reformat with ruff.

* Update name to reflect requested changes in Semantic Conventions pull request #2125.

* Add test to verify correct handling of Unicode.

* Reformat with ruff.

* Remove deuplicated test.
2025-04-23 13:08:22 -04:00
Kevin Rauwolf c54292fa08
Check for None result in gRPC (#3380) (#3381) 2025-04-21 07:41:14 -08:00
Emídio Neto d6f6c60c16
autoinstrumentation: don't print duplicated conflict log error message (#3432)
* Update instrumentor.py

* Add tests for dependency conflict logging

* Format code in test_instrument_missing_dependency

* Add comments for dependency conflict handling
2025-04-18 16:53:35 +00:00
Eric Zhang dd151673d1
support InvokeModel GenAi instrumentation for additional Bedrock models (#3419)
This adds basic request and response gen_ai instrumentation for the following Bedrock model providers:
Cohere Command and Command R, Meta Llama, Mistral AI
2025-04-18 11:25:30 +02:00
Emídio Neto 3431a4e8b0
Update core_contrib_test_0.yml (#3431)
* Update core_contrib_test_0.yml

* Update core_contrib_test.yml.j2
2025-04-17 14:04:38 -04:00
Emídio Neto c47e341ab8
Update CHANGELOG.md (#3430) 2025-04-17 15:36:45 +02:00
Emídio Neto 8390db35ae
infra(ci): configure concurrency to cancel stale runs and setting timeouts (#3422)
Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-04-17 08:07:46 +00:00
Michael Safyan b8018c5262
Ensure that the Google GenAI SDK instrumentation correctly populates "finish_reasons" on the span. (#3417)
* Fix bug where 'gen_ai.response.finish_reasons' was not being correctly populated.

* Update changelog.

* Reformat with ruff.
2025-04-15 16:06:59 -04:00
Rahul Kumar ce90639428
Removed the unnesessary packages from tornado requirements file (#3411)
Signed-off-by: Rahul Kumar <Rahul.Kumar@fmr.com>
2025-04-15 20:11:17 +02:00
Allen Kim fce17db166
asyncio: fix duplicate instrumentation (#3408)
* #3383 fix duplicate instrument

* #3383 fix duplicate instrument

* feedback

* feat(asyncio): add weakref-based tracking for instrumented objects

* Use WeakKeyDictionary to safely track instrumented objects

* feedback

* feedback

* feedback

---------

Co-authored-by: allen <allen.k1m@kakaocorp.com>
2025-04-15 15:59:04 +00:00
Emídio Neto 9c969f363e
autoinstrumentation: catch `ModuleNotFoundError` when the library is not installed (#3423)
* catch ModuleNotFoundError when the library is not installed and prevent exception from bubbling up

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* cleanup

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* remove dup test

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* Update CHANGELOG.md

---------

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>
2025-04-15 09:43:13 +02:00
Andre Murbach Maidl 7562ff08f3
Improve tornado instrumentation example (#3410)
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-04-14 14:56:53 +00:00
Riccardo Magliocchetti 4b832859cc
test-requirements: Bump jinja2 to 3.1.6 (#3420)
To please dependabot
2025-04-11 18:01:16 +02:00
OpenTelemetry Bot 6587485d05
Update version to 1.33.0.dev/0.54b0.dev (#3413)
* Update version to 1.33.0.dev/0.54b0.dev

* Point CORE_REPO_SHA to opentelemetrybot/update-version-to-1.33.0.dev-0.54b0.dev

---------

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-04-10 13:53:58 +00:00
fcfangcc bb85f983a3
Fix aiokafka multiple values headers error. (#3332)
* Fix aiokafka multiple values headers

* modify testcase

* add changelog

---------

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-04-10 10:22:01 +00:00
Andre Murbach Maidl 04f9e8dd7f
Improve starlette instrumentation example (#3409) 2025-04-10 11:57:07 +02:00
RJ Duffner 6d5a5149d0
Make auto instrumentation use the same dependency resolver as manual instrumentation does (#3202) 2025-04-08 15:11:09 +02:00
Andre Murbach Maidl 6bde73ce34
Improve pika instrumentation examples (#3390) 2025-04-02 14:17:52 +00:00
Andre Murbach Maidl 3a585b4b58
Improve httpx instrumentation examples (#3387) 2025-04-02 10:40:39 +00:00
Andre Murbach Maidl e50cb3271f
Improve kafka-python instrumentation examples (#3388)
* Improve kafka-python instrumentation example

* Improve kafka-python instrumentation examples
2025-04-02 10:29:21 +00:00
Andre Murbach Maidl 5a2cfb3d65
Improve sqlalchemy instrumentation example (#3396) 2025-04-02 10:17:32 +00:00
Andre Murbach Maidl fdcd80d89f
Improve remoulade instrumentation example (#3391) 2025-04-02 09:58:35 +00:00
Riccardo Magliocchetti ff18e7c18b
Build instrumentation-genai/README.md (#3400)
* scripts: build a README also for instrumentation-genai

* opentelemetry-instrumentation-openai-v2: add supports_metrics to package

* opentelemetry-instrumentation-google-genai: add missing package.py

* Build instrumentation-genai/README.md
2025-04-02 09:45:56 +00:00
OpenTelemetry Bot 78373353f5
Add ossf-scorecard scanning workflow (#3398)
* Add ossf-scorecard scanning workflow

* Add end of file newline

---------

Co-authored-by: otelbot <197425009+otelbot@users.noreply.github.com>
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-04-02 09:28:12 +00:00
Jason Anderson fa499f5ca8
fix: grpc server ValueError when using unix sockets (#3394)
* fix: grpc server ValueError when using unix sockets

with some grpc implementations the full .peer address is available
for unix sockets, which includes the socket path. it seems that
in versions of grpc prior to 1.53.0, the full path is returned by
`context.peer()`. rather than change the dependency of the instrumentation,
this updates it to more gracefully handle the case of the socket path
being present or absent.

Fixes #3393

* add changelog entry

---------

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-04-02 08:42:29 +00:00
Riccardo Magliocchetti 642d8c4081
botocore: add some more content to the README (#3395)
* botocore: add some more content to the README

This is taken from __init__.py documentation.

* Move the content to the README since it's not really code specific

* Add link to examples

* Apply suggestions from code review

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>

---------

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
2025-04-01 12:44:09 +00:00
Andre Murbach Maidl 27d5d93a6a
Improve asyncpg instrumentation example (#3349)
Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-03-31 12:58:39 +00:00
Riccardo Magliocchetti 3d37106115
botocore: handle tool calls with Amazon nova with Bedrock InvokeModel* APIs (#3385)
* botocore: test invokemodel tool calls against amazon nova

* botocore: handle amazon nova tool calls events for InvokeModelWithResponseStream

* Update documentation

* Update Changelog

* Please pylint

* Cleanup

* Reduce branches in tool calls tests

Instead pass down a per-model object that implements the peculiar part.

And fix recording of amazon.nova stream no content test.

* Move stream content extraction for tool calls tests to a couple of helpers
2025-03-31 08:53:15 +00:00
Emídio Neto dde065b139
use type instead of pyright (#3392)
Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>
2025-03-28 20:15:42 +00:00
Aaron Abbott 8b2558f22e
VertexAI support for async calling (#3386)
* VertexAI support for async calling

* Clarify things a bit

* Fix python 3.8 and 3.9 tests

* Remove unnecessary record check

* Update instrumentation-genai/opentelemetry-instrumentation-vertexai/src/opentelemetry/instrumentation/vertexai/__init__.py

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>

* ruff

---------

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
2025-03-28 17:44:28 +00:00
Joe McGinley 0ea9998c4c
Add asyncclick instrumentation (#3319)
* Add asyncclick instrumentation

* Add instrumentation for asyncclick based CLI apps
* Add tox
* Add Changelog
* Update workflows

This implementation is based on the original click instrumentation work by:
- Emídio Neto <9735060+emdneto@users.noreply.github.com>
- Anuraag (Rag) Agrawal <anuraaga@gmail.com>
- Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>

* Update CHANGELOG.md

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>

* Fix async refs in code-block example

---------

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
2025-03-28 12:20:29 +01:00
Bharat Arya 50ab047143
bug_fix(1477): type handling in _add_sql_comment (#3113)
---------

Co-authored-by: Tammy Baylis <96076570+tammy-baylis-swi@users.noreply.github.com>
Co-authored-by: Leighton Chen <lechen@microsoft.com>
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-03-27 14:43:30 +01:00
jinjia 139d787168
fix: opentelemetry-instrumentation-openai-v2 version in example (#3350) 2025-03-26 08:22:12 +00:00
Googleplex af179659a2
Fix client address is set to server address in new semconv (#3354)
* Fix client address is set to server address

* fix: asgi tests

* docs: update CHANGELOG

* docs: update CHANGELOG

* refactor: only populate server address if missing

---------

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
Co-authored-by: Leighton Chen <lechen@microsoft.com>
2025-03-24 16:15:51 +01:00
Andre Murbach Maidl 76e614fac4
Improve botocore instrumentation examples (#3348) 2025-03-21 17:05:56 +00:00
Andre Murbach Maidl 46cf5b5257
Add instrumentation example to logging (#3314)
* Add instrumentation example to logging

* Add example output to logging instrumentation example

* Fix logging instrumentation example and output

* Fixing rst syntax for logging instrumentation examples

---------

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-03-21 17:33:51 +01:00
Andre Murbach Maidl 164259e149
Improve elasticsearch instrumentation examples (#3367)
* Improve elasticsearch instrumentation examples

* Fix doc_type for elasticsearch instrumentation examples
2025-03-21 15:15:31 +00:00
Andre Murbach Maidl db617eb3fd
Improve confluent-kafka instrumentation examples (#3369)
* Improve confluent-kafka instrumentation example

* Improve confluent-kafka tracer provider example

* Apply suggestions from code review

---------

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-03-21 14:25:38 +00:00
Andre Murbach Maidl 3c60b62ad1
Improve falcon instrumentation examples (#3370) 2025-03-21 13:53:54 +00:00
Andre Murbach Maidl 8d14f0bb2a
Improve flask instrumentation example (#3371) 2025-03-21 13:37:30 +00:00
Andre Murbach Maidl a5474c3b29
Improve fastapi instrumentation example (#3372) 2025-03-20 16:02:36 +00:00
Michael Safyan e43e8c91cd
[chore] Address TODO to migrate to VCRpy and remove bespoke RequestMocker code in Google GenAI SDK instrumentation (#3344)
* Remove bespoke request mocker. Replace with direct mocking of the underlying API.

* Refactor fake credentials to enable reuse.

* Add module to test end to end with a real client.

* Add redaction and minimal OTel mocking/testing in the e2e test.

* Fix wording of the documentation.

* Remove vcr migration from TODOs.

* Improve redaction and test naming.

* Minor tweaks in the code generation. Add casette files.

* Reformat with ruff.

* Fix lint and gzip issue.

* Reformat with ruff.

* Prevent fix for Python 3.9 from breaking tests in other versions.

* Record update in changelog.

* Don't double iterate when redacting by changing the value.

Co-authored-by: Aaron Abbott <aaronabbott@google.com>

---------

Co-authored-by: Aaron Abbott <aaronabbott@google.com>
2025-03-19 13:58:15 -04:00
Riccardo Magliocchetti ad29af3996
opentelemetry-instrumentation: fix RST syntax of README (#3362)
Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
2025-03-13 19:34:49 +01:00
Selcuk Ayguney 3c88163c99
Handle empty strings in sqlcommenter (#3309)
* Handle empty strings

Safer check for a trailing semicolon that could handle
empty strings as well.

* Updated CHANGELOG.md

* Test for empty SQL strings in sqlcommenter

---------

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-03-13 11:18:35 +00:00
Leighton Chen f96d14cc62
update (#3363) 2025-03-13 09:35:08 +01:00
OpenTelemetry Bot 6189be647c
Update version to 1.32.0.dev/0.53b0.dev (#3359) 2025-03-12 12:07:49 -08:00
Andre Murbach Maidl 6daf581f46
Improve urllib3 instrumentation examples (#3347)
* Improve urllib3 instrumentation example

* Port urllib3 instrumentation example improvements to README.rst

* Add trailing commas to urllib3 instrumentation examples

---------

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-03-12 14:08:50 +00:00
Emídio Neto db52193b3c
bump pyright (#3355)
Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>
2025-03-11 21:11:54 +00:00
Emídio Neto 3708604bb5
botocore: sns set destination name attribute to arn and redact phone number (#3249)
* set destination name only if not phone number

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* redact phone_number

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* add changelog

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

---------

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-03-10 09:39:12 +00:00
Andre Murbach Maidl d5dce5de99
Improve asyncio instrumentation examples (#3312)
* Improve asyncio instrumentation examples

* Port asyncio instrumentation example changes to README.rst

---------

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-03-07 16:27:35 +00:00
Joe McGinley ad2fe813ab
Fix threading instrumentation context types (#3322)
Add None check to context handling in threading instrumentation
Add testcases for None context

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-03-06 12:44:44 -05:00
Andre Murbach Maidl fde1ef84c7
Add instrumentation example to aiohttp-server (#3311) 2025-03-06 08:41:58 -08:00
Aaron Abbott 9811782358
Implement uninstrument for `opentelemetry-instrumentation-vertexai` (#3328)
* Implement uninstrument for `opentelemetry-insturmentation-vertexai`

* Reuse fixture from conftest.py
2025-03-06 15:43:49 +00:00
Andre Murbach Maidl 4f9ee01b5f
Improve django instrumentation example (#3313)
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
Co-authored-by: Leighton Chen <lechen@microsoft.com>
2025-03-06 14:18:14 +00:00
Riccardo Magliocchetti 2d5a21a3da
instrumentation: rename experimental semconv status to development in README (#3333)
* instrumentation: rename experimental to development in README

To match the current semantic conventions naming.

* Update generate_instrumentation_readme.py

* Update README.md

* Run generate

* Update the README too
2025-03-06 13:30:28 +00:00
Emídio Neto 3dd42960e0
Change affiliation for emdneto (#3343) 2025-03-06 13:05:15 +00:00
Riccardo Magliocchetti c0132c6ab0
urllib: don't assume we control the bucket metrics data point get in (#3341)
Instead of expecting an entry in a specific bucket, just sum all of them
and assert we have the correct number of entries.

Co-authored-by: Shalev Roda <65566801+shalevr@users.noreply.github.com>
2025-03-06 12:10:51 +00:00
dependabot[bot] 65720812f7
build(deps): bump jinja2 from 3.1.4 to 3.1.6 (#3340)
Bumps [jinja2](https://github.com/pallets/jinja) from 3.1.4 to 3.1.6.
- [Release notes](https://github.com/pallets/jinja/releases)
- [Changelog](https://github.com/pallets/jinja/blob/main/CHANGES.rst)
- [Commits](https://github.com/pallets/jinja/compare/3.1.4...3.1.6)

---
updated-dependencies:
- dependency-name: jinja2
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-03-06 11:20:54 +00:00
Riccardo Magliocchetti fa8a6995c7
botocore: don't crash when sending content as string with InvokeModel (#3342)
As apparently langchain does with Claude.
2025-03-06 09:50:10 +00:00
Emídio Neto 23cadea66a
requests: always record span status code in duration metrics (#3323)
* show test fail at main

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* implement fix -- ci should pass now

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* remove uneeded comment

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* Update instrumentation/opentelemetry-instrumentation-requests/tests/test_requests_integration.py

* use get_sorted_metrics

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

---------

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>
Co-authored-by: Leighton Chen <lechen@microsoft.com>
Co-authored-by: Shalev Roda <65566801+shalevr@users.noreply.github.com>
2025-03-06 08:56:41 +00:00
Andre Murbach Maidl 2371adf3f8
Improve requests instrumentation example (#3316) 2025-03-05 23:23:09 -08:00
Emídio Neto a83c8d9a04
make urllib test less flaky (#3336)
* make urllib test less flaky

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* Update instrumentation/opentelemetry-instrumentation-urllib/tests/test_metrics_instrumentation.py

* ruff

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

---------

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>
2025-03-05 21:39:37 +00:00
OpenTelemetry Bot a01564cf08
Update opentelemetry-instrumentation-google-genai version to v0.2b0 (#3334) 2025-03-05 14:28:54 -05:00
Aaron Abbott 9e4de00420
Small fixes for google-genai before releasing (#3330) 2025-03-05 10:40:00 -05:00
Riccardo Magliocchetti 0ff1032bdd
botocore: add genai metrics for bedrock extensions (#3326)
This add genai metrics regarding the operation duration and the tokens used to botocore bedrock extension.
2025-03-05 09:14:39 +00:00
Michael Safyan 81eaea57f9
Add support for async and streaming responses in the Google GenAI instrumentation (#3298)
* Begin instrumentation of GenAI SDK.

* Snapshot current state.

* Created minimal tests and got first test to pass.

* Added test for span attributes.

* Ensure that token counts work.

* Add more tests.

* Make it easy to turn off instrumentation for streaming and async to allow for rapid iteration.

* Add licenses and fill out main README.rst.

* Add a changelog file.

* Fill out 'requirements.txt' and 'README.rst' for the manual instrumentation example.

* Add missing exporter dependency for the manual instrumentation example.

* Fill out rest of the zero-code example.

* Add minimal tests for async, streaming cases.

* Update sync test to use indirection on top of 'client.models.generate_content' to simplify test reuse.

* Fix ruff check issues.

* Add subproject to top-level project build mechanism.

* Simplify invocation of pylint.

* Fix 'make test' command and lint issues.

* Add '.dev' suffix to version per feedback on pull request #3256

* Fix README.rst files for the examples.

* Add specific versions for the examples.

* Revamp 'make test' to not require local 'tox.ini' configuration.

* Extend separators per review comment.

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>

* Fix version conflict caused by non-hermetic requirements.

* Fix typo on the comment line.

* Add test for the use of the 'vertex_ai' system, and improve how this system is determined.

* Factor out testing logic to enable sharing with the async code.

* Addressed minor lint issues.

* Make it clearer that nonstreaming_base is a helper module that is not invoked directly.

* Integrate feedback from related pull request #3268.

* Update workflows with 'tox -e generate-workflows'.

* Improve data model and add some rudimentary type checking.

* Accept only 'true' for a true value to align with other code.

* Update the scope name used.

* Add **kwargs to patched methods to prevent future breakage due to the addition of future keyword arguments.

* Remove redundant list conversion in call to "sorted".

Co-authored-by: Aaron Abbott <aaronabbott@google.com>

* Reformat with 'tox -e ruff'.

* Fix failing lint workflow.

* Fix failing lint workflow.

* Exclude Google GenAI instrumentation from the bootstrap code for now.

* Minor improvements to the tooling shell files.

* Fix typo flagged by codespell spellchecker.

* Increase alignment with broader repo practices.

* Add more TODOs and documentation to clarify the intended work scope.

* Remove unneeded accessor from OTelWrapper.

* Add more comments to the tests.

* Reformat with ruff.

* Change 'desireable' to 'desirable' per codespell spellchecker.

* Make tests pass without pythonpath

* Fix new lint errors showing up after change

* Revert "Fix new lint errors showing up after change"

This reverts commit 567adc62a7.

pylint ignore instead

* Add TODO item required/requested from code review.

Co-authored-by: Aaron Abbott <aaronabbott@google.com>

* Simplify changelog per PR feedback.

* Remove square brackets from model name in span name per PR feedback.

* Checkpoint current state.

* Misc test cleanup. Now that scripts are invoked solely through pytest via tox, remove main functions and hash bang lines.

* Improve quality of event logging.

* Implement streaming support in RequestsMocker, get tests passing again.

* Add test with multiple responses.

* Remove support for async and streaming from TODOs, since this is now addressed.

* Increase testing coverage for streaming.

* Reformat with ruff.

* Add minor version bump with changelog.

* Change TODOs to bulleted list.

* Update per PR feedback

Co-authored-by: Aaron Abbott <aaronabbott@google.com>

* Restructure streaming async logic to begin execution earlier.

* Reformat with ruff.

* Disable pylint check for catching broad exception. Should be allowed given exception is re-raised.

* Simplify async streaming solution per PR comment.

---------

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
Co-authored-by: Aaron Abbott <aaronabbott@google.com>
2025-03-03 22:39:31 +00:00
Aaron Abbott c6c0162cef
Loosen `opentelemetry-instrumentation-starlette[instruments]` specifier (#3304)
* Loosen `opentelemetry-instrumentation-starlette[instruments]` specifier

* Compile locked requirements with uv

* Update comment for clarity

* Generate for python 3.8+

* Update package.py as well

* generate

* Oops, undo accidental change to starlette version

* Update uv pip compile command to remove core repo git SHAs and absolute paths
2025-03-03 20:22:57 +00:00
Andre Murbach Maidl f98f5688ae
Improve pymongo instrumentation example (#3315) 2025-03-03 10:17:02 +01:00
OpenTelemetry Bot 6114b60506
Copy changelog updates from package-release/opentelemetry-instrumentation-vertexai/v2.0bx (#3295)
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-02-28 15:28:39 +00:00
Aaron Abbott f17a1bd65a
Add opentelemetry-instrumentation-vertexai>=2.0b0 to opentelemetry-bootstrap (#3307)
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-02-28 14:23:38 +00:00
Andre Murbach Maidl e0189e25dc
Improves aiohttp_client code snippet (#3306)
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-02-28 14:10:25 +00:00
Riccardo Magliocchetti 2f4d4c56fc
botocore: send tool events for bedrock (#3302)
* botocore: send tool events for bedrock

This implements sending tool events for:
- Converse
- ConverseStream
- InvokeModel with anthropic claude 3+ models
- InvokeMoldeWithStreamResponse with anthropic claude 3+ models

* Add changelog

* Please pylint
2025-02-28 08:51:33 +00:00
Michael Safyan c09a299010
Initial version of instrumentation for the Google GenAI SDK (github.com/googleapis/python-genai) (#3256)
* Begin instrumentation of GenAI SDK.

* Snapshot current state.

* Created minimal tests and got first test to pass.

* Added test for span attributes.

* Ensure that token counts work.

* Add more tests.

* Make it easy to turn off instrumentation for streaming and async to allow for rapid iteration.

* Add licenses and fill out main README.rst.

* Add a changelog file.

* Fill out 'requirements.txt' and 'README.rst' for the manual instrumentation example.

* Add missing exporter dependency for the manual instrumentation example.

* Fill out rest of the zero-code example.

* Add minimal tests for async, streaming cases.

* Update sync test to use indirection on top of 'client.models.generate_content' to simplify test reuse.

* Fix ruff check issues.

* Add subproject to top-level project build mechanism.

* Simplify invocation of pylint.

* Fix 'make test' command and lint issues.

* Add '.dev' suffix to version per feedback on pull request #3256

* Fix README.rst files for the examples.

* Add specific versions for the examples.

* Revamp 'make test' to not require local 'tox.ini' configuration.

* Extend separators per review comment.

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>

* Fix version conflict caused by non-hermetic requirements.

* Fix typo on the comment line.

* Add test for the use of the 'vertex_ai' system, and improve how this system is determined.

* Factor out testing logic to enable sharing with the async code.

* Addressed minor lint issues.

* Make it clearer that nonstreaming_base is a helper module that is not invoked directly.

* Integrate feedback from related pull request #3268.

* Update workflows with 'tox -e generate-workflows'.

* Improve data model and add some rudimentary type checking.

* Accept only 'true' for a true value to align with other code.

* Update the scope name used.

* Add **kwargs to patched methods to prevent future breakage due to the addition of future keyword arguments.

* Remove redundant list conversion in call to "sorted".

Co-authored-by: Aaron Abbott <aaronabbott@google.com>

* Reformat with 'tox -e ruff'.

* Fix failing lint workflow.

* Fix failing lint workflow.

* Exclude Google GenAI instrumentation from the bootstrap code for now.

* Minor improvements to the tooling shell files.

* Fix typo flagged by codespell spellchecker.

* Increase alignment with broader repo practices.

* Add more TODOs and documentation to clarify the intended work scope.

* Remove unneeded accessor from OTelWrapper.

* Add more comments to the tests.

* Reformat with ruff.

* Change 'desireable' to 'desirable' per codespell spellchecker.

* Make tests pass without pythonpath

* Fix new lint errors showing up after change

* Revert "Fix new lint errors showing up after change"

This reverts commit 567adc62a7.

pylint ignore instead

* Add TODO item required/requested from code review.

Co-authored-by: Aaron Abbott <aaronabbott@google.com>

* Simplify changelog per PR feedback.

* Remove square brackets from model name in span name per PR feedback.

* Misc test cleanup. Now that scripts are invoked solely through pytest via tox, remove main functions and hash bang lines.

* Improve quality of event logging.

* Update operation name to use a constant for consistency.

* Reformat with ruff.

* Exclude opentelemetry-instrumentation-google-genai from root uv workspace

Until https://github.com/open-telemetry/opentelemetry-python-contrib/issues/3300 is fixed.

---------

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
Co-authored-by: Aaron Abbott <aaronabbott@google.com>
2025-02-27 11:37:40 -05:00
Guangya Liu 139f3e52d9
Update doc for OpenAI Instrumentation to support OpenAI Compatible Platforms (#3279)
* Update doc for OpenAI Instrumentation to support DeepSeek

* Update with Adrian's comments

Co-authored-by: Adrian Cole <64215+codefromthecrypt@users.noreply.github.com>

* rollback the blankspace remove

---------

Co-authored-by: Adrian Cole <64215+codefromthecrypt@users.noreply.github.com>
Co-authored-by: Shalev Roda <65566801+shalevr@users.noreply.github.com>
2025-02-26 13:03:29 +02:00
Aaron Abbott b76119bb8f
VertexAI fix RST title underline (#3292) 2025-02-24 13:07:27 -05:00
OpenTelemetry Bot c4eb3714c5
Update opentelemetry-instrumentation-vertexai version to v2.1b0 (#3286)
Co-authored-by: Aaron Abbott <aaronabbott@google.com>
2025-02-24 12:17:07 -05:00
Aaron Abbott dc01beda66
Add `run-name` with package name to single-package release workflows (#3287) 2025-02-24 15:48:36 +00:00
Riccardo Magliocchetti 38006e86c4
opentelemetry-instrumentation: expose a way to init autoinstrumentation programmatically (#3273)
* opentelemetry-instrumentation: expose a way to init autoinstrumentation

* Please pylint

* Add changelog

* Fix example

* Fix whitespace in README

* Add a note aboout ordering of initialization vs imports

* Don't touch PYTHONPATH if not set

* Update opentelemetry-instrumentation/README.rst

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>

* Update CHANGELOG.md

* Update opentelemetry-instrumentation/README.rst

Co-authored-by: Leighton Chen <lechen@microsoft.com>

---------

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
Co-authored-by: Leighton Chen <lechen@microsoft.com>
2025-02-24 11:15:13 +00:00
Riccardo Magliocchetti b1f714ee0f
botocore: send choice events for bedrock chat completion (#3275)
* botocore: send choice events for bedrock chat completion

* Please pylint

* Add CHANGELOG

* Always call done stream callback

* Move choice event creation to _Choice and add types
2025-02-24 10:34:00 +00:00
Riccardo Magliocchetti 3c2599c761
opentelemetry-docker-tests: bump grpcio to 1.63.2 (#3290)
To match the baseline added to opencensus exporter.
2025-02-24 11:16:57 +01:00
Aaron Abbott f8bb30ef67
Updating workflows and RELEASING.md to allow vertexai individual release (#3284) 2025-02-21 17:12:14 -03:00
Emídio Neto 72490eafcd
Fix uv setup when using tox (#3282)
* Update core_contrib_test_0.yml

* add tox-uv.toml to ignore sources

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* revert workflows change

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* add aws xray propagator to show it works

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* add genai

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

---------

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>
2025-02-21 16:26:46 +00:00
Aaron Abbott 638c57f7a4
Fix opentelemetry-instrumentation-vertexai version pre 2.0b0 release (#3281)
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-02-21 10:07:12 -05:00
Riccardo Magliocchetti e4a5b54135
scripts/generate_instrumentation_bootstrap: don't force genai instrumentations versions (#3278)
* scripts/generate_instrumentation_bootstrap: don't force genai instrumentations versions

Since genai instrumentations are released on their own we cannot have a
fixed required version on this side.
While at it add vertexai to the list of excluded packages since:
- it has not been released yet
- the name is already claimed by openllmetry

* Regenerate bootstrap_gen

* Please spellcheck

---------

Co-authored-by: Leighton Chen <lechen@microsoft.com>
2025-02-21 09:55:10 +00:00
Riccardo Magliocchetti b5a0ee526c
opentelemetry-instrumentation-system-metrics: add process metrics (#3250)
* opentelemetry-instrumentation-system-metrics: add process metrics

Add process metrics as of 1.30.0 semconv to the system metrics instrumentation.
We still keep around the old process.runtime metrics because the semconv
suggest to not break current users. Still discourage their use in the
doc and state explicitly they are deprecated.

* Add Changelog

* Please pylint

* Apply suggestions from code review

* Remove print

* Remove process.count and fix system metrics enumeration in tests

* Cleanup metrics presence assertions

* Don't touch system metrics descriptions

* Add default for num_cpu in case it returns None to avoid division error
2025-02-21 09:04:15 +00:00
Emídio Neto 17a57bf6d3
Fix openaiv2 example readme (#3276)
* Fix openaiv2 example readme

* update manual as well

---------

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-02-21 08:46:28 +00:00
Aaron Abbott 2f5b0bf1fc
Vertex capture tool requests and responses (#3255)
* Vertex capture tool requests and responses

* Update to use tracking bug in contrib repo
2025-02-20 23:32:19 +00:00
Marcelo Trylesinski 6245fb833c
Use UV to install all needed packages locally (#3124)
* Use UV to install all needed packages locally

* Add opentelemetry-test-utils

* Add asgi and fastapi

* Add more projects, since it helped me

* add urllib

* Add system metrics

* Add dbapi and sqlite3

* Add sqlalchemy

* add pyramid

* Add pymongo

* Add jinja2

* add lock file

* add falcon as well

* Add uv lock to the pre-commit

* Update uv.lock

* Update lockfile

* remove xray test dependencies

* Add otel-sdk to xray

* Update uv version

* Drop xray from the list of packages

---------

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
2025-02-20 17:04:31 -05:00
Riccardo Magliocchetti 8644630e7f
opentelemetry-instrumentation-system-metrics: add support for psutil 7 (#3277) 2025-02-20 15:33:00 +01:00
OpenTelemetry Bot 52bbcd6001
Add FOSSA scanning workflow (#3270)
Co-authored-by: Trask Stalnaker <trask.stalnaker@gmail.com>
Co-authored-by: Leighton Chen <lechen@microsoft.com>
2025-02-20 10:21:51 +01:00
dependabot[bot] 8e3cd65f28
build(deps): bump certifi in /tests/opentelemetry-docker-tests/tests (#3262)
Bumps [certifi](https://github.com/certifi/python-certifi) from 2024.2.2 to 2024.7.4.
- [Commits](https://github.com/certifi/python-certifi/compare/2024.02.02...2024.07.04)

---
updated-dependencies:
- dependency-name: certifi
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-02-19 15:45:40 +00:00
Michael Safyan 0cb9ba55e8
[chore] Replace '-0' and '-1' with semantically meaningful suffixes. Other minor fixes in 'instrumentation-genai' test structure. (#3268)
* Replace '-0' and '-1' with semantically meaningful suffixes.

* Act on feedback in PR 3268.

* Fix typos.
2025-02-19 16:25:07 +01:00
Guspan Tanadi 96f4a039c5
docs(readme): current section links (#3269)
Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
2025-02-17 11:22:15 +00:00
Riccardo Magliocchetti 789bf866e3
botocore: handle system messages events (#3266)
* botocore: handle system event messages

* Add CHANGELOG

* Please pylint
2025-02-14 10:17:08 +00:00
Stephan Klein 1623dc0e71
fixed: asyncpg connection params are a namedtuple (#3253)
Follow-up on the apparently abbandonned https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2114.

The asyncpg instrumentation attempts to fall back on using the database
name as the span name in case the first argument to the instrumented
method is falsey.

This has probably never worked since asyncpg defines the `_params`
attribute as an instance of `ConnectionParams`
(https://github.com/MagicStack/asyncpg/blob/master/asyncpg/connection.py#L62)
which is a NamedTuple instance and thus don't define `get`. The proper
way of safely accessing properties on a NamedTuple is using `getattr`.

The only case that I've actually found which triggers this branch is if
the supplied query is an empty string. This is something that causes an
`AttributeError` for `Connection.execute` but is fine for `fetch()`,
`fetchval()`, `fetchrow()` and `executemany()`.

The tests have been expanded to check these cases. Also, more status
code validation has been added where it was missing.

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-02-14 08:59:21 +00:00
Marcelo Trylesinski 63e43d5222
[threading] Remove ellipsis from type hints (#3245)
Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-02-13 09:38:12 +00:00
Riccardo Magliocchetti 95873604ab
botocore: add bedrock genai user events and lazy initialize tracers and event loggers (#3258)
* Create per-extension tracers if there's an extension available

* botocore: add user events for bedrock

* Remove pass of AWS env vars from tox.ini

* Remove handling for other types of messages

* Please pylint

* Add changelog

* Update CHANGELOG.md

Co-authored-by: Adrian Cole <64215+codefromthecrypt@users.noreply.github.com>

---------

Co-authored-by: Adrian Cole <64215+codefromthecrypt@users.noreply.github.com>
2025-02-13 10:08:24 +01:00
Emídio Neto 34368612f4
Update .readthedocs.yml (#3264) 2025-02-12 14:54:01 +01:00
dependabot[bot] bf3c0be507
build(deps): bump cryptography (#3259)
Bumps [cryptography](https://github.com/pyca/cryptography) from 42.0.5 to 44.0.1.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/42.0.5...44.0.1)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
2025-02-12 12:28:50 +01:00
Michael Schuett 42e8b0a451
upgrade opentelemetry-exporter-prometheus-remote-write to use protobuf 5.26 (#3219)
* Allow protobuf version above 4 and under 6 for opentelemetry_exporter_prometheus_remote_write

* update version

* fix tests

* regenerate protobufs

* with newer protoc

* format

* actually support 5.26 protobuf

* changelog

* Update CHANGELOG.md

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>

---------

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
Co-authored-by: Aaron Abbott <aaronabbott@google.com>
2025-02-11 21:32:27 +00:00
Aaron Abbott 6e61ff0c32
VertexAI stop serializing unset fields into event (#3236) 2025-02-10 15:36:23 -05:00
Liudmila Molkova 231d26c4be
Provide advisory histogram boundaries when creating OpenAI metrics (#3225)
* small fixes in OpenAI examples

* up

* add comment

* leverage histogram bucket advice in 1.30

* Update instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/test_chat_metrics.py

* Update instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/test_chat_metrics.py

* up

---------

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-02-10 09:09:52 -08:00
Aaron Abbott c0bc2c9797
Add Vertex gen AI response attributes and `gen_ai.choice` events (#3227)
* Add Vertex gen AI response span attributes

* Vertex response gen_ai.choice events

* Add todo comment

* Update _map_finish_reason() and use it in span attribute as well

* ruff
2025-02-07 23:05:07 +00:00
Maciej Nachtygal 64f28ca279
docs: add request_hook parameter description to RedisInstrumentor (#3247)
* docs: add request_hook parameter description to RedisInstrumentor

* changelog: add missing entry in doc string for _instrument in opentelemetry-instrumentation-redis

---------

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
2025-02-07 11:29:28 -05:00
XlKsyt d7bc137c60
openai: fix broken link (#3248) 2025-02-07 11:10:00 +00:00
Liudmila Molkova cca571ab72
Record content events regardless of span sampling decision (#3226)
* Record content events regardless of span sampling decision

* changelog

* feedback

* ruff

---------

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-02-06 13:28:02 +00:00
Anuraag (Rag) Agrawal 6b3a11beb2
Render strings in bedrock test cassettes for readability (#3243) 2025-02-06 10:06:05 +01:00
Emídio Neto 9d8a6c6420
infra: fix workflows (#3240) 2025-02-04 13:24:34 -08:00
OpenTelemetry Bot 85e21a9e22
Update version to 1.31.0.dev/0.52b0.dev (#3233) 2025-02-04 12:55:11 -08:00
Leighton Chen d18c5fe19c
add vertexai to eachdist (#3230) 2025-02-03 13:01:37 -08:00
Tammy Baylis 65a2713d9f
Add mysql-connector instrumentor support for sqlcommenting (#3163) 2025-01-30 09:43:17 -08:00
Aaron Abbott 748c92592d
VertexAI emit user, system, and assistant events (#3203)
* VertexAI emit user events

* Emit system and assistant events

* Fix for python 3.8

* Record events regardless of span recording

* fix tests

* Apply suggestions from code review

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>

---------

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
2025-01-29 22:24:39 +00:00
Riccardo Magliocchetti 7af1918b89
botocore: remove amazon copyright from bedrock_utils (#3215)
These code has been written from scratch
2025-01-28 20:22:56 +00:00
Riccardo Magliocchetti 44754e2a50
botocore: handle exceptions when consuming EventStream in bedrock extension (#3211) 2025-01-28 19:55:40 +00:00
Aaron Abbott 731054f736
Add server attributes to Vertex AI spans (#3208) 2025-01-28 16:46:13 +00:00
Emídio Neto dd68241907
fix pymssql entry_point for auto-instrumentation (#3214)
Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-01-28 14:05:19 +00:00
Riccardo Magliocchetti eabab7d0ad
Fix changelog (#3213) 2025-01-28 14:31:11 +01:00
Riccardo Magliocchetti 93e6fcfa26
botocore: add basic tracing for Bedrock InvokeModelWithStreamResponse (#3206)
* Add basic tracing for InvokeModelWithResponseStream

* Add changelog and please pylint
2025-01-28 09:55:28 +01:00
guillaumep 5478a0b77a
Add pymssql instrumentation (#394)
* Add pymssql instrumentation

* Run tox -e generate

* tox -e generate-workflows

---------

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-01-27 16:12:21 +01:00
Riccardo Magliocchetti 0bb1c42a78
botocore: add basic tracing for bedrock ConverseStream (#3204)
* Add tracing for ConverseStream

* Add converse stream example
2025-01-27 10:01:07 +01:00
Riccardo Magliocchetti 2756c1edff
botocore: add basic handling for bedrock invoke.model (#3200)
* Add basic handling for invoke.model

* Add changelog a please pylint

* Record converse cassettes against us-east-1

* Avoid double copy of streaming body

---------

Co-authored-by: Adrian Cole <64215+codefromthecrypt@users.noreply.github.com>
2025-01-23 17:14:49 +01:00
Aaron Abbott ec3c51dcd1
Added Vertex AI spans for request parameters (#3192)
* Added Vertex AI spans for request parameters

* small fixes, get CI passing

* Use standard OTel tracing error handling

* move nested util

* Actually use GAPIC client since thats what we use under the hood

Also this is what LangChain uses

* Comment out seed for now

* Remove unnecessary dict.get() calls

* Typing improvements to check that we support both v1 and v1beta1

* Add more teest cases for error conditions and fix span name bug

* fix typing

* Add todos for error.type
2025-01-22 13:32:34 -05:00
Josh Owen 3f50c08580
psycopg2-binary support (#3186)
* psycopg2-binary support

* changelog

* Update CHANGELOG.md

* Update pyproject.toml

* fix

* lint

* added test config

* Update bootstrap_gen.py

* update tox

* Update tox.ini

* regenerate workflows

* workflows

---------

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-01-21 15:41:56 -05:00
Riccardo Magliocchetti 37f85bf8cc
instrumentation/aws-lambda: don't print warnings outside of AWS Lambda (#3183)
If we are not running inside AWS Lambda don't print warnings on missing
OTel lambda extension layer.
The instrumentation is installed by the OTel k8s operator and so this
warning may confuse users.
2025-01-21 13:57:53 +00:00
OpenTelemetry Bot 20413ef7d7
Copy changelog updates from package-release/opentelemetry-instrumentation-openai-v2/v2.1bx (#3197)
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-01-21 09:10:48 +01:00
Riccardo Magliocchetti 9460773e5c
Basic instrumentation for Bedrock runtime Converse api (#3161)
* botocore: add extension for bedrock runtime api

* Add tests and handle only non streaming responses

* Make it explicit we are handling only the converse operation

* Simplify test since all models behaves the same

* Add test for error case and rework things a bit

* Add converse example

* Generate workflows

* Add changelog
2025-01-20 09:56:09 +01:00
OpenTelemetry Bot 86a7f6bab3
Update opentelemetry-instrumentation-openai-v2 version to v2.2b0 (#3194) 2025-01-17 20:12:12 -08:00
Emídio Neto 9b217bb4ff
introducing tox-uv for real (#3185)
Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>
2025-01-17 17:33:52 +01:00
Aaron Abbott 9d9353d4c6
Run pyright on Vertex AI instrumentation (#3184) 2025-01-16 14:25:35 -05:00
Drew Robbins a716949d1c
Add metrics to the Python OpenAI instrumentation (#3180) 2025-01-15 14:24:35 -08:00
Marcelo Trylesinski 07c97eac38
Add type hints to `psycopg` (#3067)
* Add type hints to Psycopg

* fix tests

* fix

* Add psycopg.Connection to nitpick

* Add py.typed

* add psycopg to nitpick again

* add psycopg to nitpick again

* move py.typed to the right folder

---------

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-01-15 16:30:01 +00:00
Marcelo Trylesinski 52871b82b6
Add type hints to HTTPX (#3098) 2025-01-14 09:27:35 -08:00
Marcelo Trylesinski e54256ddb7
Support PEP 561 to `opentelemetry-instrumentation-urllib` (#3131)
* Support PEP 561 to `opentelemetry-instrumentation-urllib`

* add future

---------

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2025-01-14 16:28:11 +00:00
Josh Soref c59b514cda
Fix component owner workflow permissions (#3165) 2025-01-13 15:42:32 -08:00
Marcelo Trylesinski 5219242eaf
Support PEP 561 to `opentelemetry-instrumentation-wsgi` (#3129) 2025-01-13 13:32:16 -08:00
Filip Nikolovski b7e7d0cbe5
Implement new HTTP semantic convention opt-in for Falcon (#2790) 2025-01-13 11:49:22 -08:00
Marcelo Trylesinski 406707b2bd
Add type checker (#3116) 2025-01-13 09:20:33 -08:00
Tammy Baylis 8406e2e789
DB drivers: db.statement inclusion of sqlcomment as opt-in (#3121)
* db-api opt-in for enable_attribute_commenter

* Refactor db-api traced_execution

* Changelog

* Update comment

* psycopg(2), mysqlclient, pymysql support enable_attribute_commenter

* Changelog
2025-01-13 10:40:43 +01:00
Marcelo Trylesinski 29ef6a9455
Add type hints to dbapi (#3068) 2025-01-10 10:03:09 -08:00
Marcelo Trylesinski 3ebdb6344b
Support PEP 561 to `opentelemetry-instrumentation-pymongo` (#3136) 2025-01-10 09:20:28 -08:00
Marcelo Trylesinski a606fab849
Support PEP 561 to `opentelemetry-instrumentation-requests` (#3135) 2025-01-10 09:00:10 -08:00
Marcelo Trylesinski 0ad779a5b3
Support PEP 561 to `opentelemetry-instrumentation-jinja2` (#3137) 2025-01-09 17:42:12 -08:00
Will Li 962a3aecdb
fix #991 audit asyncpg instrumentation with nooptracerprovider (#3144) 2025-01-09 14:51:23 -08:00
Guspan Tanadi 41e670aeee
docs(README): semantic convention migration links (#3160) 2025-01-09 13:58:53 -08:00
Marcelo Trylesinski 9af3136e7f
Support PEP 561 to `opentelemetry-util-http` (#3127) 2025-01-09 13:21:19 -08:00
Tammy Baylis cf6d45e96c
DB-API: db.statement inclusion of sqlcomment as opt-in (#3115) 2025-01-09 13:08:46 -08:00
Tammy Baylis 26bcc9347b
SQLAlchemy: db.statement inclusion of sqlcomment as opt-in (#3112) 2025-01-09 12:56:14 -08:00
Riccardo Magliocchetti 908437db5d
click: ignore click based servers (#3174)
* click: ignore click based servers

We don't want to create a root span for long running processes like servers
otherwise all requests would have the same trace id which is unfortunate.
---------

Co-authored-by: Tammy Baylis <96076570+tammy-baylis-swi@users.noreply.github.com>
2025-01-09 11:29:31 +01:00
Tammy Baylis 147e3f754e
Add check before iterating over dist.requires at load_instrumentor (#3168)
* Add check before iterate over dist.requires

* Changelog

* Add test
2025-01-08 10:02:55 +01:00
Marcelo Trylesinski 3d5935f4f6
docs: add missing import to aws-lambda (#3154) 2025-01-02 12:18:07 -08:00
GonzaloGuasch 95f14cd8df
wsgi: always record span status code to have it available in metrics (#3148) 2025-01-02 11:58:17 -08:00
Marcelo Trylesinski e5eb524e89
Improve type hints in `opentelemetry.instrumentation.utils` (#3128) 2025-01-02 11:44:58 -08:00
Marcelo Trylesinski 3e394a4814
Support PEP 561 to `opentelemetry-instrumentation-system-metrics` (#3132) 2025-01-02 11:30:41 -08:00
Marcelo Trylesinski 16c041e22b
Support PEP 561 to `opentelemetry-instrumentation-sqlite3` (#3133) 2025-01-02 11:15:01 -08:00
Emídio Neto 54882871b9
add official support to Python 3.13 (#3134)
* add py313 to tox

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* fix wrong identation troveclassifiers

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* fix pyramid, django

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* fix httpx

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* fix httpx, grpc and add vertex

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* generate-workflows

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* fix generate-workflows

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* fix celery and psycopg

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* add changelog

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* Update CHANGELOG.md

* Update tox.ini

---------

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2024-12-31 16:08:20 +00:00
Cyrille Le Clerc c084ca8fa5
Update README.rst - Fix Markdown (#3156)
Fix broken Markdown.

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
2024-12-31 16:31:33 +01:00
Riccardo Magliocchetti 8db1479e0d
RELEASING: Document what package prepare release workflows will create (#3153)
While at it fix formatting
2024-12-30 13:13:07 +00:00
Emídio Neto 72dc1cf1f6
prometheus-remote-write: bump cramjam to 2.8.4 in test-requirements (#3157)
Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>
2024-12-30 09:26:54 +01:00
Emídio Neto 16eaec8d03
cassandra: fix tests for py313 (#3152)
* cassandra: fix tests to make CI happy for py313

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* ruff

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

---------

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>
2024-12-24 16:14:05 +01:00
OpenTelemetry Bot d116ae39d6
Update opentelemetry-sdk-extension-aws version to v2.2.0 (#3149) 2024-12-24 15:59:31 +01:00
Emídio Neto 396aad9c24
celery: remove deprecated import of ContextManager from typing (#3145)
* celery: remove deprecated import of ContextManager from typing

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* add type checking

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* ruff

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

---------

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>
2024-12-24 13:55:33 +00:00
Emídio Neto 375eb6f2cc
psycopg: bump versions in test-requirements to support py313 (#3147)
Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2024-12-24 13:47:18 +00:00
Aaron Abbott 5fd648eac4
Remove unnecessary configuration of logs exporter in Gen AI samples (#3141)
It is no longer necessary since we now set up the logging pipeline by
default with OTLP exporter.
2024-12-23 19:29:50 +00:00
Emídio Neto b03bf0037f
asyncpg: bump version in test-requirements (#3146)
Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>
2024-12-23 17:47:09 +00:00
YR Chen 2176e3e43e
opentelemetry-instrumentation-falcon: expand supported version to v4 (#3086)
* opentelemetry-instrumentation-falcon: expand supported version to v4

Falcon v4 has a mostly identical interface to v3, and is proved to be fully compatible with `opentelemetry-instrumentation-falcon`. Loose the version check to `<5.0.0` to avoid false `DependencyConflict` alarm.

* opentelemetry-instrumentation-falcon: generate tests for v4

* opentelemetry-instrumentation-falcon: prepare tests for v4

* opentelemetry-instrumentation-falcon: add test preset for `~=3.1.2`

* docs: add changelog for Falcon v4 instrumentation

* opentelemetry-instrumentation-falcon: adjust pylint mark for v4

* _has_fixed_http_target property

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* move changelog to the correct section

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* fix test and bootstrap_gen

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

---------

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>
Co-authored-by: emdneto <9735060+emdneto@users.noreply.github.com>
2024-12-23 17:34:48 +00:00
Guangya Liu 59894979ef
[chore] Removed $ from command for contribution guidance (#3114)
The copy in markdown file always copy the $ as well when copying the command,
I need to remove the $ manually each time.

Co-authored-by: Leighton Chen <lechen@microsoft.com>
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2024-12-23 14:02:02 +00:00
Emídio Neto 77708cd7dd
grpc: bump grpcio version in test-requirements (#3140)
* grpc: bump grpcio version in test-requirements

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* keep 1.62.0 test

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* fix toxini

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

---------

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>
2024-12-23 13:36:12 +01:00
Emídio Neto 73ecf39517
sqlalchemy: bump greenlet version in test requirements and use last requirement file for lint (#3139)
Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2024-12-23 10:09:27 +00:00
Riccardo Magliocchetti 7eead8f1ae
opentelemetry-sdk-extension-aws: make ec2 resource detector silent when loaded outside AWS (#3120)
* opentelemetry-sdk-extension-aws: make ec2 resource detector silent when loaded outside AWS

Assume that if we fail to get the token quickly we are not on AWS.
2024-12-23 09:43:09 +00:00
Aaron Abbott 72576f65e0
Vertex AI instrumentation boilerplate (#3123)
* Vertex AI boilerplate copied from openai-v2

* tox.ini boilerplate

* tox -e generate,generate-workflows
2024-12-21 23:45:53 +00:00
Beijie Zhang 1092344918
Add docstring for instrument_connection() and tests for database drivers (#3108) 2024-12-20 12:24:46 -08:00
Andrea Galbusera 54cbf59aae
Update package metadata adding "Repository" to project urls (#3119)
Add "Repository" label to project urls pointing to the
opentelemetry-python repo root url.

Having within project urls one entry with the same value for all
packages released by the project will help tools for automatic
dependency management to suggest coherent upgrades for related packages.
2024-12-19 10:15:58 +00:00
Emídio Neto 1ddba1b518
contributing: add guidance on how to update package versions support (#3090)
* contributing: add guidance for update package versions support

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* update the guide

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* Update CONTRIBUTING.md

* Update CONTRIBUTING.md

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>

* Update CONTRIBUTING.md

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>

* Update CONTRIBUTING.md to add docs instructions

* Update CONTRIBUTING.md

* Update CONTRIBUTING.md

---------

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2024-12-18 18:05:29 +01:00
RJ Duffner 52ff7bdd4b
feat: Update opentelemetry-instrumentation-confluent-kafka to support confluent-kafka <=2.7.0 (#3100) 2024-12-17 12:33:39 -08:00
Marcelo Trylesinski 6fcaa0a104
Add type hints to Redis (#3110) 2024-12-17 10:40:40 -08:00
Emídio Neto cc62d1f05e
prepare semconv utilities to support database stability opt-in (#3111) 2024-12-17 09:58:04 -08:00
Marcelo Trylesinski d155540038
httpx: update type hints to `RequestInfo`/`ResponseInfo` (#3105) 2024-12-17 09:43:22 -08:00
Adrian Cole f8b0f726ce
opentelemetry-instrumentation-openai-v2: updates versions in examples (#3102) 2024-12-17 09:23:08 -08:00
Emídio Neto 59ecd4d608
infra: improve tox for local development (#2999)
* move pip install from command to deps

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* add docker-test-requirements.txt

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* fix celery and docs

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* fix

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* fix tox.ini

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* update docs

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* Update tox.ini

---------

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>
Co-authored-by: Leighton Chen <lechen@microsoft.com>
2024-12-17 14:24:50 +01:00
Riccardo Magliocchetti 770003dd17
opentelemetry-sdk-extension-aws: make ecs and beanstalk resource detector silent when loaded outside AWS (#3076)
* opentelemetry-sdk-extension-aws: make ecs detector less chatty

Don't print warnings if we are not running inside an ecs instance so we can load the
resource detector more generally and avoid warnings in stderr.

* opentelemetry-sdk-extension-aws: make beanstalk detector less chatty

Don't print warnings if we are not running inside beanstalk so we can load the
resource detector more generally and avoid warnings in stderr.

* Add changelog
2024-12-16 10:28:18 +00:00
Riccardo Magliocchetti 38f0e33641
opentelemetry-sdk-extension-aws: make eks detector less chatty (#3074)
* opentelemetry-sdk-extension-aws: make eks detector less chatty

Don't print warnings if we are not running inside an eks instance so we can load the
resource detector more generally and avoid warnings in stderr.

* Update CHANGELOG

---------

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
2024-12-13 15:39:07 +00:00
Marcelo Trylesinski 37e05aff86
Move starlette's py.typed to the right place (#3103) 2024-12-13 14:53:17 +01:00
OpenTelemetry Bot 490580d6f3
Update version to 1.30.0.dev/0.51b0.dev (#3092) 2024-12-12 11:17:53 +00:00
Marcelo Trylesinski d2a51b95e5
docs: move `AwsLambdaInstrumentor().instrument()` to after the lambda function (#3085)
Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
2024-12-11 16:02:37 +01:00
Diego Amaral eb03dac1f0
NoOpTracerProvider test case for botocore instrumentation (#3091)
Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
2024-12-11 13:35:50 +00:00
Tammy Baylis 830231092d
Update sqlite3 instrumentor doc about explicit cursors (#3088)
* Update sqlite3 instrumentor doc about explicit cursors

* Changelog

---------

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2024-12-11 11:59:21 +00:00
Marcelo Trylesinski e32aac7b18
Improve SQLite3 example (#3083)
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2024-12-11 11:25:01 +00:00
Marcelo Trylesinski 7804e0a4e8
Add type hints to BaseInstrumentor (#3084) 2024-12-11 10:37:51 +01:00
Riccardo Magliocchetti ecf5529f99
opentelemetry-instrumentation-django: bump to 4.2.17 in test requirements (#3077)
Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
2024-12-09 17:08:17 +00:00
Riccardo Magliocchetti c530f0d98f
instrumentation: Bump Werkzeug to 3.0.6 (#3078)
Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
2024-12-09 14:46:44 +01:00
Riccardo Magliocchetti eb394c0b21
opentelemetry-instrumentation-tornado: bump tornado in test requirements (#3079) 2024-12-09 14:31:31 +01:00
Adrian Cole 6134d5a2f9
opentelemetry-instrumentation-openai-v2: coerce openai response_format to semconv format (#3073)
* opentelemetry-instrumentation-openai-v2: coerce openai response_format to semconv format

Signed-off-by: Adrian Cole <adrian.cole@elastic.co>

* changelog

Signed-off-by: Adrian Cole <adrian.cole@elastic.co>

---------

Signed-off-by: Adrian Cole <adrian.cole@elastic.co>
2024-12-09 10:46:13 +01:00
Leonid Bugaev 6c92f387aa
Fix doc formatting issues (#3062)
Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
2024-12-05 13:53:21 +01:00
Marcelo Trylesinski f393546d4a
Add type hints to SQLite3 (#3057)
* Add type hints to SQLite3

* Apply suggestions from code review

* Update instrumentation/opentelemetry-instrumentation-sqlite3/src/opentelemetry/instrumentation/sqlite3/package.py

* This is a type alias, pylint is dumb

---------

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
Co-authored-by: Aaron Abbott <aaronabbott@google.com>
2024-12-04 14:14:12 +00:00
Riccardo Magliocchetti 9cf26836bd
CONTRIBUTING: notes abount adding doc for new instrumentation (#3064)
* CONTRIBUTING: notes abount adding doc for new instrumentation

While at it revise the versioning paragraph to take into account the
openai instrumentation.

* Reword doc paragraph

* Update CONTRIBUTING.md

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>

* Add autodoc template

* Add notes about tox

---------

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
2024-12-04 08:27:56 +00:00
Pete Hodgson 76170313f1
Fix instrumentation of SQLAlchemy when using sqlalchemy.engine_from_config (#2816)
* wrap sqlalchemy.engine.create.create_engine

sqlalchemy.engine_from_config directly calls create_engine imported from that path; if we don't
wrap that copy of the `create_engine` call then engines created via engine_from_config are not
instrumented.

* add changelog entry

* Update CHANGELOG.md

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>

* Update instrumentation/opentelemetry-instrumentation-sqlalchemy/tests/test_sqlalchemy.py

Co-authored-by: Tammy Baylis <96076570+tammy-baylis-swi@users.noreply.github.com>

* make some monkey-patching conditional on the version of SQLAlchemy

* lint

* fix changelog

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* Update CHANGELOG.md

---------

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>
Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
Co-authored-by: Leighton Chen <lechen@microsoft.com>
Co-authored-by: Shalev Roda <65566801+shalevr@users.noreply.github.com>
Co-authored-by: Tammy Baylis <96076570+tammy-baylis-swi@users.noreply.github.com>
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2024-12-04 10:13:07 +02:00
Emídio Neto 9e83e25441
test two requirements files for docs and rtd (#3039) 2024-12-03 10:03:23 -08:00
Rytis Bagdziunas b6541f0bad
Remove references to disposed SQLAlchemy engines from instrumentation singleton (#3053)
* Remove references to SQLAlchemy engines which are disposed of

EngineTracer in SQLAlchemy keeps weak references to a traced engine forever which
can cause a noticeable memory leak if engines are constantly getting creating.

* Updated changelog

---------

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2024-12-03 09:31:08 +00:00
Emídio Neto 668cb75f24
docs: add missing autodoc for click and aiohttp-server (#3060)
* add missing docs for click and aiohttp-server

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* fix click readme

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* add nitpick

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

---------

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2024-12-03 09:19:43 +00:00
Marcelo Trylesinski 0da62aa532
Add type hints to Starlette instrumentation (#3045)
* Add type hints to Starlette instrumentation

* format

* Add changelog

* Add changelog

* Remove pyright ignore

---------

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
2024-12-02 22:28:45 -05:00
Liudmila Molkova 142b86c1bf
OpenAI instrumentation docs fixes (#2988)
* Add openai docs config and improve readme

* up

* Add manual sample, add no-content tests

* update headers

* lint

* use grpc endpoint in openai samples, add extra env vars to readme

* move distro fix to another PR

* nits

* Ignore examples for pylint

* Update .pylintrc

* ignroe lint for example

* Fix README docs

* Update openai.rst

* Update conf.py

* Update docs-requirements.txt

* docs

---------

Co-authored-by: Leighton Chen <lechen@microsoft.com>
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2024-12-02 10:23:11 +01:00
Emídio Neto 8656a06f88
try update misc workflows to py311 (#3055)
Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2024-11-28 17:07:52 +00:00
Riccardo Magliocchetti af8d0930ca
opentelemetry-instrumentation-openai-v2: pin httpx dependency (#3056)
As 0.28.0 broke compat with old openai client.
2024-11-28 13:40:15 -03:00
Riccardo Magliocchetti d330ab3dd0
Add click instrumentation (#2994)
* Add instrumentation for click based CLI apps

Co-authored-by: Anuraag (Rag) Agrawal <anuraaga@gmail.com>

* Add tox

* Add Changelog

* Silence pylint

* Update tox.ini

Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>

* Update instrumentation/opentelemetry-instrumentation-click/pyproject.toml

* Add baseline version

* Adhere to new cli span semconv

* Update workflows

---------

Co-authored-by: Anuraag (Rag) Agrawal <anuraaga@gmail.com>
Co-authored-by: Emídio Neto <9735060+emdneto@users.noreply.github.com>
2024-11-27 08:38:38 +00:00
Marcelo Trylesinski 16ebf2519b
starlette: Replace `_meter_provider` by `meter_provider` on `_instrument` (#3048)
* starlette: Replace `_meter_provider` by `meter_provider` on `_instrument`

* Add PR on the changelog

---------

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2024-11-26 21:46:47 +00:00
Emídio Neto 97d1514b65
fix missing contrib_repo_sha in workflow (#3049)
Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>
2024-11-26 15:03:42 +01:00
Emídio Neto 41bd34f6e1
infra: configure generate-workflows to generate core-contrib-tests (#3035)
* test call workflow

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* fix name

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

---------

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2024-11-26 12:16:45 +00:00
Liudmila Molkova 1737ee6940
Use OTLP log exporter by default in otel-distro (#3042)
* Use OTLP log exporter by default in otel-distro

* changelog

* sort imports
2024-11-26 09:43:11 +01:00
Tammy Baylis 5c5fc732fb
Replace assertEqualSpanInstrumentationInfo with assertEqualSpanInstrumentationScope (#3037)
* Replace assertInstInfo with assertInstScope

* Update Changelog

* Fix order of other changelog entries
2024-11-22 09:32:04 +01:00
Riccardo Magliocchetti d9e14487b2
opentelemetry-instrumentation-system-metrics: fix typo in metrics configs (#3025) 2024-11-21 14:12:51 -08:00
Riccardo Magliocchetti 116f98df72
opentelemetry-instrumentation-httpx: drop unused private classes (#3036) 2024-11-21 08:52:22 -08:00
Tammy Baylis 7b1554bddc
Add PyMySQL instrumentor support for sqlcommenting (#2942)
* WIP

* Add _DB_DRIVER_ALIASES

* Add mysql_client_version to sqlcomment

* lint

* Fix existing tests

* lint test

* Add PyMySQL dbapi commenter case

* Add test

* Add test

* Add test

* Add tests

* Changelog

* calculate_commenter_data at init of DatabaseApiIntegration

* try-except if NoneType module

* Add pymysql sqlcomment support

* Add unit tests

* Update docstring

* Changelog

* pymysql instrument_connection specifies connect_module

* lint

* Add tests

* Fix doc

---------

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2024-11-21 16:21:12 +00:00
Tammy Baylis beff723389
Add mysqlclient instrumentor support for sqlcommenting (#2941)
* WIP

* Add _DB_DRIVER_ALIASES

* Add mysql_client_version to sqlcomment

* lint

* Fix existing tests

* lint test

* Add PyMySQL dbapi commenter case

* Add test

* Add test

* Add test

* Add tests

* Changelog

* calculate_commenter_data at init of DatabaseApiIntegration

* Add mysqlclient sqlcomment support

* Fix typo

* try-except if NoneType module

* Add unit test

* CHangelog

* mysqlclient instrument_connection with connect_module

* add tests

* more tests

* more tests 2

* lint

* Redesign tests

* Rm unnecessary mocks
2024-11-21 10:37:08 -05:00
Tammy Baylis 4e992dd60a
DB-API instrument_connection accepts optional connect_module (#3027)
* DbApi instrument_connection accepts optional connect_module

* Changelog

* Add test

* Adjust tests
2024-11-20 14:44:56 -05:00
Adrian Cole d0cbf8e1a5
Correct formatting of CHANGELOG (#3029)
Signed-off-by: Adrian Cole <adrian.cole@elastic.co>
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
2024-11-20 12:54:06 +00:00
Leighton Chen 0032e68161
Update RELEASING.md (#3001) 2024-11-20 10:01:12 +01:00
Adrian Cole ae13079df8
Add OpenAI example (#3006) 2024-11-19 22:48:27 -08:00
Emídio Neto 19a59e4be7
fix(httpx): check if mount transport is None before wrap (#3022) 2024-11-19 11:40:06 -08:00
Tammy Baylis 1c820ea96e
SQLAlchemy instrumentor populates span after sqlcomment creation, not before (#2937) 2024-11-19 09:30:26 -08:00
Tammy Baylis 53b87145b3
DB-API instrumentor populates span after sqlcomment creation, not before (#2935) 2024-11-19 09:13:31 -08:00
Anton Pirker a29ad8a6a3
Fix link to confluent_kafka docs (#3024) 2024-11-19 09:26:10 +01:00
Aaron Abbott 23f67eb77b
Cherry pick eachdist.py changes to main from release/v1.28.x-0.49bx branch (#3018)
* Fix prepare patch release workflow (#3013)

* Fix eachdist.py patch release to respect "all" and "excluded" (#3016)
2024-11-18 12:29:35 -05:00
Riccardo Magliocchetti 803bb322ba
opentelemetry-instrumentation-httpx: make instrument_client a staticmethod again (#3003)
* opentelemetry-instrumentation-httpx: make instrument_client a staticmethod again

* ADd changelog

* Can be a classmethod

---------

Co-authored-by: Leighton Chen <lechen@microsoft.com>
2024-11-14 19:08:03 +01:00
Leighton Chen c32cc7a3e2
Remove updating CHANGELOG step in release workflow (#3000) 2024-11-14 09:52:32 -08:00
Ali Waleed a6e4a0ca43
Add Support for `Async` openai instrumentation (#2984) 2024-11-14 08:53:27 -08:00
Leighton Chen e3ba54b95c
Add openai instrumentation to opentelemetry-bootstrap (#2996) 2024-11-12 15:13:42 -08:00
Adrian Cole 89a0b28a09
opentelemetry-instrumentation-openai-v2: scrub cookie from tests (#2993) 2024-11-12 13:01:49 -08:00
Leighton Chen c28f7c978e
re-add testpypi publish step (#2991) 2024-11-12 09:18:09 -08:00
Liudmila Molkova b6a6f75834
publish to pypi (#2980) (#2987) 2024-11-11 11:02:20 -08:00
Tammy Baylis 66a6780721
Add generate-workflows usage to CONTRIBUTING (#2977) 2024-11-11 10:53:42 -08:00
Adrian Cole bf8e2814ea
opentelemetry-instrumentation-openai-v2: add codefromthecrypt and fix yaml fixture (#2989) 2024-11-11 08:12:26 -08:00
OpenTelemetry Bot 4606cf2c10
Copy changelog updates from package-release/opentelemetry-instrumentation-openai-v2/v2.0bx (#2982) 2024-11-07 17:03:39 -08:00
Guangya Liu 46b14662f8
adding gyliu513 as genai reviewer (#2972) 2024-11-07 16:07:33 -08:00
Emídio Neto 1d6968b672
fix: teach instrument version constraint for sqlalchemy (#2971) 2024-11-07 15:39:16 -08:00
Tammy Baylis 1d8286c08a
Update tests to work with SQLAlchemy 2 (#2976) 2024-11-07 15:18:05 -08:00
Emídio Neto ca4d5170d0
fix: remove opentelemetry-instrumentation-test package from bootstrap_gen (#2969) 2024-11-07 11:18:51 -08:00
Nir Gazit 4a5bf9bd7e
add nirga to GenAI component owners (#2962) 2024-11-07 10:59:17 -08:00
Liudmila Molkova 499548ebbb
Test packages that are released individually with lowest versions they support (#2961) 2024-11-07 10:47:19 -08:00
Riccardo Magliocchetti 77613da396
Drop selective enabled for windows and regenerate workflows (#2964) 2024-11-06 17:36:33 +01:00
OpenTelemetry Bot 226258e457
Update version to 1.29.0.dev/0.50b0.dev (#2954) 2024-11-05 14:22:03 -08:00
OpenTelemetry Bot 6c88f01f0c
Update opentelemetry-instrumentation-openai-v2 version to v2.1b0 (#2960) 2024-11-05 13:28:54 -08:00
Liudmila Molkova d341ef5062
prepare before preparing release (#2958) 2024-11-05 12:30:58 -08:00
673 changed files with 61162 additions and 9333 deletions

View File

@ -18,7 +18,7 @@ body:
Please describe any aspect of your environment relevant to the problem, including your Python version, [platform](https://docs.python.org/3/library/platform.html), version numbers of installed dependencies, information about your cloud hosting provider, etc. If you're reporting a problem with a specific version of a library in this repo, please check whether the problem has been fixed on main.
value: |
OS: (e.g, Ubuntu)
Python version: (e.g., Python 3.8.10)
Python version: (e.g., Python 3.9.10)
Package version: (e.g., 0.46.0)
- type: textarea

View File

@ -11,6 +11,9 @@ components:
- oxeye-nikolay
- nikosokolik
instrumentation/opentelemetry-instrumentation-asyncclick:
- jomcgi
instrumentation/opentelemetry-instrumentation-kafka-python:
- nozik
@ -61,6 +64,9 @@ components:
instrumentation/opentelemetry-instrumentation-psycopg:
- federicobond
instrumentation/opentelemetry-instrumentation-pymssql:
- guillaumep
instrumentation/opentelemetry-instrumentation-aiokafka:
- dimastbk
@ -71,3 +77,7 @@ components:
- karthikscale3
- lmolkova
- lzchen
- gyliu513
- nirga
- alizenhom
- codefromthecrypt

11
.github/scripts/update-version-patch.sh vendored Executable file
View File

@ -0,0 +1,11 @@
#!/bin/bash -e
sed -i "/\[stable\]/{n;s/version=.*/version=$1/}" eachdist.ini
sed -i "/\[prerelease\]/{n;s/version=.*/version=$2/}" eachdist.ini
./scripts/eachdist.py update_patch_versions \
--stable_version=$1 \
--unstable_version=$2 \
--stable_version_prev=$3 \
--unstable_version_prev=$4

View File

@ -10,6 +10,10 @@ jobs:
run_self:
runs-on: ubuntu-latest
name: Auto Assign Owners
permissions:
contents: read # to read changed files
issues: write # to read/write issue assignees
pull-requests: write # to read/write PR reviewers
# Don't fail tests if this workflow fails. Some pending issues:
# - https://github.com/dyladan/component-owners/issues/8
continue-on-error: true

2252
.github/workflows/core_contrib_test_0.yml vendored Normal file

File diff suppressed because it is too large Load Diff

20
.github/workflows/fossa.yml vendored Normal file
View File

@ -0,0 +1,20 @@
name: FOSSA scanning
on:
push:
branches:
- main
permissions:
contents: read
jobs:
fossa:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: fossas/fossa-action@93a52ecf7c3ac7eb40f5de77fd69b1a19524de94 # v1.5.0
with:
api-key: ${{secrets.FOSSA_API_KEY}}
team: OpenTelemetry

View File

@ -1,6 +1,7 @@
from pathlib import Path
from generate_workflows_lib import (
generate_contrib_workflow,
generate_lint_workflow,
generate_misc_workflow,
generate_test_workflow,
@ -9,8 +10,7 @@ from generate_workflows_lib import (
tox_ini_path = Path(__file__).parent.parent.parent.joinpath("tox.ini")
workflows_directory_path = Path(__file__).parent
generate_test_workflow(
tox_ini_path, workflows_directory_path, "ubuntu-latest", "windows-latest"
)
generate_test_workflow(tox_ini_path, workflows_directory_path, "ubuntu-latest")
generate_lint_workflow(tox_ini_path, workflows_directory_path)
generate_misc_workflow(tox_ini_path, workflows_directory_path)
generate_contrib_workflow(workflows_directory_path)

View File

@ -7,7 +7,7 @@ name = "generate-workflows-lib"
dynamic = ["version"]
description = "A library to generate workflows"
license = "Apache-2.0"
requires-python = ">=3.8"
requires-python = ">=3.9"
authors = [
{ name = "OpenTelemetry Authors", email = "cncf-opentelemetry-contributors@lists.cncf.io" },
]
@ -17,11 +17,11 @@ classifiers = [
"License :: OSI Approved :: Apache Software License",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Typing :: Typed",
]
dependencies = ["Jinja2", "tox"]

View File

@ -14,7 +14,7 @@ _tox_test_env_regex = re_compile(
)
_tox_lint_env_regex = re_compile(r"lint-(?P<name>[-\w]+)")
_tox_contrib_env_regex = re_compile(
r"py38-test-(?P<name>[-\w]+\w)-?(?P<contrib_requirements>\d+)?"
r"py39-test-(?P<name>[-\w]+\w)-?(?P<contrib_requirements>\d+)?"
)
@ -47,20 +47,13 @@ def get_test_job_datas(tox_envs: list, operating_systems: list) -> list:
os_alias = {"ubuntu-latest": "Ubuntu", "windows-latest": "Windows"}
python_version_alias = {
"pypy3": "pypy-3.8",
"py38": "3.8",
"pypy3": "pypy-3.9",
"pypy310": "pypy-3.10",
"py39": "3.9",
"py310": "3.10",
"py311": "3.11",
"py312": "3.12",
}
# we enable windows testing only for packages with windows specific code paths
per_tox_env_os_enablement = {
"windows-latest": {
"py312-test-instrumentation-botocore",
"py312-test-instrumentation-system-metrics",
},
"py313": "3.13",
}
test_job_datas = []
@ -79,14 +72,6 @@ def get_test_job_datas(tox_envs: list, operating_systems: list) -> list:
]
tox_env = tox_test_env_match.string
# if we have an entry for the os add only jobs for tox env manually configured
packages_manually_enabled = per_tox_env_os_enablement.get(
operating_system
)
if packages_manually_enabled:
if tox_env not in packages_manually_enabled:
continue
test_requirements = groups["test_requirements"]
if test_requirements is None:
@ -186,14 +171,14 @@ def get_misc_job_datas(tox_envs: list) -> list:
def _generate_workflow(
job_datas: list, name: str, workflow_directory_path: Path
job_datas: list, name: str, workflow_directory_path: Path, max_jobs=250
):
# Github seems to limit the amount of jobs in a workflow file, that is why
# they are split in groups of 250 per workflow file.
for file_number, job_datas in enumerate(
[
job_datas[index : index + 250]
for index in range(0, len(job_datas), 250)
job_datas[index : index + max_jobs]
for index in range(0, len(job_datas), max_jobs)
]
):
with open(
@ -235,7 +220,7 @@ def generate_contrib_workflow(
get_contrib_job_datas(
get_tox_envs(Path(__file__).parent.joinpath("tox.ini"))
),
"contrib",
"core_contrib_test",
workflow_directory_path,
)

View File

@ -1,17 +1,21 @@
# Do not edit this file.
# This file is generated automatically by executing tox -e generate-workflows
name: Contrib {{ file_number }}
name: Core Contrib Test {{ file_number }}
on:
push:
branches-ignore:
- 'release/*'
pull_request:
workflow_call:
inputs:
CORE_REPO_SHA:
required: true
type: string
CONTRIB_REPO_SHA:
required: true
type: string
env:
CORE_REPO_SHA: ${% raw %}{{ github.sha }}{% endraw %}
CONTRIB_REPO_SHA: main
CORE_REPO_SHA: ${% raw %}{{ inputs.CORE_REPO_SHA }}{% endraw %}
CONTRIB_REPO_SHA: ${% raw %}{{ inputs.CONTRIB_REPO_SHA }}{% endraw %}
PIP_EXISTS_ACTION: w
jobs:
@ -20,6 +24,7 @@ jobs:
{{ job_data.tox_env }}:
name: {{ job_data.ui_name }}
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout contrib repo @ SHA - ${% raw %}{{ env.CONTRIB_REPO_SHA }}{% endraw %}
uses: actions/checkout@v4
@ -27,20 +32,14 @@ jobs:
repository: open-telemetry/opentelemetry-python-contrib
ref: ${% raw %}{{ env.CONTRIB_REPO_SHA }}{% endraw %}
- name: Checkout core repo @ SHA - ${% raw %}{{ github.sha }}{% endraw %}
uses: actions/checkout@v4
with:
repository: open-telemetry/opentelemetry-python
path: opentelemetry-python-core
- name: Set up Python 3.8
- name: Set up Python 3.9
uses: actions/setup-python@v5
with:
python-version: "3.8"
python-version: "3.9"
architecture: "x64"
- name: Install tox
run: pip install tox
run: pip install tox-uv
- name: Run tests
run: tox -e {{ job_data.tox_env }} -- -ra

View File

@ -9,8 +9,20 @@ on:
- 'release/*'
pull_request:
concurrency:
group: ${% raw %}{{ github.workflow }}-${{ github.head_ref || github.run_id }}{% endraw %}
cancel-in-progress: true
env:
CORE_REPO_SHA: main
# Set the SHA to the branch name if the PR has a label 'prepare-release' or 'backport' otherwise, set it to 'main'
# For PRs you can change the inner fallback ('main')
# For pushes you change the outer fallback ('main')
# The logic below is used during releases and depends on having an equivalent branch name in the core repo.
CORE_REPO_SHA: {% raw %}${{ github.event_name == 'pull_request' && (
contains(github.event.pull_request.labels.*.name, 'prepare-release') && github.event.pull_request.head.ref ||
contains(github.event.pull_request.labels.*.name, 'backport') && github.event.pull_request.base.ref ||
'main'
) || 'main' }}{% endraw %}
CONTRIB_REPO_SHA: main
PIP_EXISTS_ACTION: w
@ -20,17 +32,18 @@ jobs:
{{ job_data.name }}:
name: {{ job_data.ui_name }}
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${% raw %}{{ github.sha }}{% endraw %}
uses: actions/checkout@v4
- name: Set up Python 3.12
- name: Set up Python 3.13
uses: actions/setup-python@v5
with:
python-version: "3.12"
python-version: "3.13"
- name: Install tox
run: pip install tox
run: pip install tox-uv
- name: Run tests
run: tox -e {{ job_data.tox_env }}

View File

@ -9,8 +9,20 @@ on:
- 'release/*'
pull_request:
concurrency:
group: ${% raw %}{{ github.workflow }}-${{ github.head_ref || github.run_id }}{% endraw %}
cancel-in-progress: true
env:
CORE_REPO_SHA: main
# Set the SHA to the branch name if the PR has a label 'prepare-release' or 'backport' otherwise, set it to 'main'
# For PRs you can change the inner fallback ('main')
# For pushes you change the outer fallback ('main')
# The logic below is used during releases and depends on having an equivalent branch name in the core repo.
CORE_REPO_SHA: {% raw %}${{ github.event_name == 'pull_request' && (
contains(github.event.pull_request.labels.*.name, 'prepare-release') && github.event.pull_request.head.ref ||
contains(github.event.pull_request.labels.*.name, 'backport') && github.event.pull_request.base.ref ||
'main'
) || 'main' }}{% endraw %}
CONTRIB_REPO_SHA: main
PIP_EXISTS_ACTION: w
@ -20,16 +32,21 @@ jobs:
{{ job_data }}:
name: {{ job_data }}
runs-on: ubuntu-latest
timeout-minutes: 30
{%- if job_data == "generate-workflows" %}
if: |
!contains(github.event.pull_request.labels.*.name, 'Skip generate-workflows')
&& github.actor != 'opentelemetrybot' && github.event_name == 'pull_request'
&& github.event.pull_request.user.login != 'opentelemetrybot' && github.event_name == 'pull_request'
{%- endif %}
{%- if job_data == "public-symbols-check" %}
if: |
!contains(github.event.pull_request.labels.*.name, 'Approve Public API check')
&& github.actor != 'opentelemetrybot' && github.event_name == 'pull_request'
{%- endif %}
{%- if job_data == "docs" %}
if: |
github.event.pull_request.user.login != 'opentelemetrybot' && github.event_name == 'pull_request'
{%- endif %}
steps:
- name: Checkout repo @ SHA - ${% raw %}{{ github.sha }}{% endraw %}
uses: actions/checkout@v4
@ -47,13 +64,13 @@ jobs:
run: git checkout ${% raw %}{{ github.event.pull_request.head.sha }}{% endraw %}
{%- endif %}
- name: Set up Python 3.10
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: "3.10"
python-version: "3.11"
- name: Install tox
run: pip install tox
run: pip install tox-uv
- name: Run tests
run: tox -e {{ job_data }}

View File

@ -9,8 +9,20 @@ on:
- 'release/*'
pull_request:
concurrency:
group: ${% raw %}{{ github.workflow }}-${{ github.head_ref || github.run_id }}{% endraw %}
cancel-in-progress: true
env:
CORE_REPO_SHA: main
# Set the SHA to the branch name if the PR has a label 'prepare-release' or 'backport' otherwise, set it to 'main'
# For PRs you can change the inner fallback ('main')
# For pushes you change the outer fallback ('main')
# The logic below is used during releases and depends on having an equivalent branch name in the core repo.
CORE_REPO_SHA: {% raw %}${{ github.event_name == 'pull_request' && (
contains(github.event.pull_request.labels.*.name, 'prepare-release') && github.event.pull_request.head.ref ||
contains(github.event.pull_request.labels.*.name, 'backport') && github.event.pull_request.base.ref ||
'main'
) || 'main' }}{% endraw %}
CONTRIB_REPO_SHA: main
PIP_EXISTS_ACTION: w
@ -20,6 +32,7 @@ jobs:
{{ job_data.name }}:
name: {{ job_data.ui_name }}
runs-on: {{ job_data.os }}
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${% raw %}{{ github.sha }}{% endraw %}
uses: actions/checkout@v4
@ -30,7 +43,7 @@ jobs:
python-version: "{{ job_data.python_version }}"
- name: Install tox
run: pip install tox
run: pip install tox-uv
{%- if job_data.os == "windows-latest" %}
- name: Configure git to support long filenames

File diff suppressed because it is too large Load Diff

View File

@ -9,8 +9,20 @@ on:
- 'release/*'
pull_request:
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
env:
CORE_REPO_SHA: main
# Set the SHA to the branch name if the PR has a label 'prepare-release' or 'backport' otherwise, set it to 'main'
# For PRs you can change the inner fallback ('main')
# For pushes you change the outer fallback ('main')
# The logic below is used during releases and depends on having an equivalent branch name in the core repo.
CORE_REPO_SHA: ${{ github.event_name == 'pull_request' && (
contains(github.event.pull_request.labels.*.name, 'prepare-release') && github.event.pull_request.head.ref ||
contains(github.event.pull_request.labels.*.name, 'backport') && github.event.pull_request.base.ref ||
'main'
) || 'main' }}
CONTRIB_REPO_SHA: main
PIP_EXISTS_ACTION: w
@ -19,17 +31,18 @@ jobs:
spellcheck:
name: spellcheck
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.10
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: "3.10"
python-version: "3.11"
- name: Install tox
run: pip install tox
run: pip install tox-uv
- name: Run tests
run: tox -e spellcheck
@ -37,17 +50,18 @@ jobs:
docker-tests:
name: docker-tests
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.10
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: "3.10"
python-version: "3.11"
- name: Install tox
run: pip install tox
run: pip install tox-uv
- name: Run tests
run: tox -e docker-tests
@ -55,17 +69,20 @@ jobs:
docs:
name: docs
runs-on: ubuntu-latest
timeout-minutes: 30
if: |
github.event.pull_request.user.login != 'opentelemetrybot' && github.event_name == 'pull_request'
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.10
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: "3.10"
python-version: "3.11"
- name: Install tox
run: pip install tox
run: pip install tox-uv
- name: Run tests
run: tox -e docs
@ -73,17 +90,18 @@ jobs:
generate:
name: generate
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.10
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: "3.10"
python-version: "3.11"
- name: Install tox
run: pip install tox
run: pip install tox-uv
- name: Run tests
run: tox -e generate
@ -94,20 +112,21 @@ jobs:
generate-workflows:
name: generate-workflows
runs-on: ubuntu-latest
timeout-minutes: 30
if: |
!contains(github.event.pull_request.labels.*.name, 'Skip generate-workflows')
&& github.actor != 'opentelemetrybot' && github.event_name == 'pull_request'
&& github.event.pull_request.user.login != 'opentelemetrybot' && github.event_name == 'pull_request'
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.10
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: "3.10"
python-version: "3.11"
- name: Install tox
run: pip install tox
run: pip install tox-uv
- name: Run tests
run: tox -e generate-workflows
@ -118,17 +137,18 @@ jobs:
shellcheck:
name: shellcheck
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.10
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: "3.10"
python-version: "3.11"
- name: Install tox
run: pip install tox
run: pip install tox-uv
- name: Run tests
run: tox -e shellcheck
@ -136,17 +156,37 @@ jobs:
ruff:
name: ruff
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.10
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: "3.10"
python-version: "3.11"
- name: Install tox
run: pip install tox
run: pip install tox-uv
- name: Run tests
run: tox -e ruff
typecheck:
name: typecheck
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e typecheck

47
.github/workflows/ossf-scorecard.yml vendored Normal file
View File

@ -0,0 +1,47 @@
name: OSSF Scorecard
on:
push:
branches:
- main
schedule:
- cron: "10 6 * * 1" # once a week
workflow_dispatch:
permissions: read-all
jobs:
analysis:
runs-on: ubuntu-latest
permissions:
# Needed for Code scanning upload
security-events: write
# Needed for GitHub OIDC token if publish_results is true
id-token: write
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1
with:
results_file: results.sarif
results_format: sarif
publish_results: true
# Upload the results as artifacts (optional). Commenting out will disable
# uploads of run results in SARIF format to the repository Actions tab.
# https://docs.github.com/en/actions/advanced-guides/storing-workflow-data-as-artifacts
- name: "Upload artifact"
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: SARIF file
path: results.sarif
retention-days: 5
# Upload the results to GitHub's code scanning dashboard (optional).
# Commenting out will disable upload of results to your repo's Code Scanning dashboard
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@5f8171a638ada777af81d42b55959a643bb29017 # v3.28.12
with:
sarif_file: results.sarif

View File

@ -8,8 +8,13 @@ on:
- opentelemetry-propagator-aws-xray
- opentelemetry-resource-detector-azure
- opentelemetry-sdk-extension-aws
- opentelemetry-instrumentation-openai-v2
- opentelemetry-instrumentation-vertexai
- opentelemetry-instrumentation-google-genai
description: 'Package to be released'
required: true
run-name: "[Package][${{ inputs.package }}] Prepare patch release"
jobs:
prepare-patch-release:
runs-on: ubuntu-latest

View File

@ -8,9 +8,13 @@ on:
- opentelemetry-propagator-aws-xray
- opentelemetry-resource-detector-azure
- opentelemetry-sdk-extension-aws
- opentelemetry-instrumentation-openai-v2
- opentelemetry-instrumentation-vertexai
- opentelemetry-instrumentation-google-genai
description: 'Package to be released'
required: true
run-name: "[Package][${{ inputs.package }}] Prepare release"
jobs:
prereqs:
runs-on: ubuntu-latest

View File

@ -8,8 +8,12 @@ on:
- opentelemetry-propagator-aws-xray
- opentelemetry-resource-detector-azure
- opentelemetry-sdk-extension-aws
- opentelemetry-instrumentation-openai-v2
- opentelemetry-instrumentation-vertexai
- opentelemetry-instrumentation-google-genai
description: 'Package to be released'
required: true
run-name: "[Package][${{ inputs.package }}] Release"
jobs:
release:
runs-on: ubuntu-latest
@ -74,7 +78,7 @@ jobs:
# next few steps publish to pypi
- uses: actions/setup-python@v5
with:
python-version: '3.8'
python-version: '3.9'
- name: Build wheels
run: ./scripts/build_a_package.sh
@ -101,9 +105,9 @@ jobs:
- name: Publish to PyPI
env:
TWINE_USERNAME: '__token__'
TWINE_PASSWORD: ${{ secrets.test_pypi_token }}
TWINE_PASSWORD: ${{ secrets.pypi_password }}
run: |
twine upload --repository testpypi --skip-existing --verbose dist/*
twine upload --skip-existing --verbose dist/*
- name: Generate release notes
env:

View File

@ -40,14 +40,18 @@ jobs:
exit 1
fi
stable_version_prev="$stable_major_minor.$((stable_patch))"
unstable_version_prev="0.${unstable_minor}b$((unstable_patch))"
stable_version="$stable_major_minor.$((stable_patch + 1))"
unstable_version="0.${unstable_minor}b$((unstable_patch + 1))"
echo "STABLE_VERSION=$stable_version" >> $GITHUB_ENV
echo "UNSTABLE_VERSION=$unstable_version" >> $GITHUB_ENV
echo "STABLE_VERSION_PREV=$stable_version_prev" >> $GITHUB_ENV
echo "UNSTABLE_VERSION_PREV=$unstable_version_prev" >> $GITHUB_ENV
- name: Update version
run: .github/scripts/update-version.sh $STABLE_VERSION $UNSTABLE_VERSION
run: .github/scripts/update-version-patch.sh $STABLE_VERSION $UNSTABLE_VERSION $STABLE_VERSION_PREV $UNSTABLE_VERSION_PREV
- name: Set up Python 3.9
uses: actions/setup-python@v5
@ -67,6 +71,7 @@ jobs:
run: .github/scripts/use-cla-approved-github-bot.sh
- name: Create pull request
id: create_pr
env:
# not using secrets.GITHUB_TOKEN since pull requests from that token do not run workflows
GITHUB_TOKEN: ${{ secrets.OPENTELEMETRYBOT_GITHUB_TOKEN }}
@ -76,7 +81,15 @@ jobs:
git commit -a -m "$message"
git push origin HEAD:$branch
gh pr create --title "[$GITHUB_REF_NAME] $message" \
pr_url=$(gh pr create --title "[$GITHUB_REF_NAME] $message" \
--body "$message." \
--head $branch \
--base $GITHUB_REF_NAME
--base $GITHUB_REF_NAME)
echo "pr_url=$pr_url" >> $GITHUB_OUTPUT
- name: Add prepare-release label to PR
if: steps.create_pr.outputs.pr_url != ''
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh pr edit ${{ steps.create_pr.outputs.pr_url }} --add-label "prepare-release"

View File

@ -94,6 +94,7 @@ jobs:
run: .github/scripts/use-cla-approved-github-bot.sh
- name: Create pull request against the release branch
id: create_release_branch_pr
env:
# not using secrets.GITHUB_TOKEN since pull requests from that token do not run workflows
GITHUB_TOKEN: ${{ secrets.OPENTELEMETRYBOT_GITHUB_TOKEN }}
@ -103,10 +104,18 @@ jobs:
git commit -a -m "$message"
git push origin HEAD:$branch
gh pr create --title "[$RELEASE_BRANCH_NAME] $message" \
pr_url=$(gh pr create --title "[$RELEASE_BRANCH_NAME] $message" \
--body "$message." \
--head $branch \
--base $RELEASE_BRANCH_NAME
--base $RELEASE_BRANCH_NAME)
echo "pr_url=$pr_url" >> $GITHUB_OUTPUT
- name: Add prepare-release label to PR
if: steps.create_release_branch_pr.outputs.pr_url != ''
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh pr edit ${{ steps.create_release_branch_pr.outputs.pr_url }} --add-label "prepare-release"
create-pull-request-against-main:
runs-on: ubuntu-latest
@ -179,6 +188,7 @@ jobs:
run: .github/scripts/use-cla-approved-github-bot.sh
- name: Create pull request against main
id: create_main_pr
env:
# not using secrets.GITHUB_TOKEN since pull requests from that token do not run workflows
GITHUB_TOKEN: ${{ secrets.OPENTELEMETRYBOT_GITHUB_TOKEN }}
@ -189,7 +199,15 @@ jobs:
git commit -a -m "$message"
git push origin HEAD:$branch
gh pr create --title "$message" \
pr_url=$(gh pr create --title "$message" \
--body "$body" \
--head $branch \
--base main
--base main)
echo "pr_url=$pr_url" >> $GITHUB_OUTPUT
- name: Add prepare-release label to PR
if: steps.create_main_pr.outputs.pr_url != ''
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh pr edit ${{ steps.create_main_pr.outputs.pr_url }} --add-label "prepare-release"

View File

@ -66,7 +66,7 @@ jobs:
# next few steps publish to pypi
- uses: actions/setup-python@v5
with:
python-version: '3.8'
python-version: '3.9'
- name: Build wheels
run: ./scripts/build.sh
@ -81,14 +81,13 @@ jobs:
# rejected by pypi (e.g "3 - Beta"). This would cause a failure during the
# middle of the package upload causing the action to fail, and certain packages
# might have already been updated, this would be bad.
# EDIT: 5/31/2024 - TestPypi now requires a verified email. Commenting out as a temporary measure
# until we found TestPypi credentials.
# - name: Publish to TestPyPI
# env:
# TWINE_USERNAME: '__token__'
# TWINE_PASSWORD: ${{ secrets.test_pypi_token }}
# run: |
# twine upload --repository testpypi --skip-existing --verbose dist/*
- name: Publish to TestPyPI
env:
TWINE_USERNAME: '__token__'
TWINE_PASSWORD: ${{ secrets.test_pypi_token }}
run: |
twine upload --repository testpypi --skip-existing --verbose dist/*
- name: Publish to PyPI
env:
@ -119,36 +118,3 @@ jobs:
# the step below is creating a pull request against main
ref: main
- name: Copy change log updates to main
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
echo "VERSION=${STABLE_VERSION}\/${UNSTABLE_VERSION}" >> $GITHUB_ENV
echo "RELEASE_TAG=$STABLE_VERSION" >> $GITHUB_ENV
./scripts/merge_changelog_to_main.sh
- name: Use CLA approved github bot
run: .github/scripts/use-cla-approved-github-bot.sh
- name: Create pull request against main
env:
# not using secrets.GITHUB_TOKEN since pull requests from that token do not run workflows
GITHUB_TOKEN: ${{ secrets.OPENTELEMETRYBOT_GITHUB_TOKEN }}
run: |
message="Copy change log updates from $GITHUB_REF_NAME"
body="Copy log updates from \`$GITHUB_REF_NAME\`."
branch="opentelemetrybot/copy-change-log-updates-from-${GITHUB_REF_NAME//\//-}"
if [[ -z $PRIOR_VERSION_WHEN_PATCH ]]; then
if git diff --quiet; then
echo there are no updates needed to the change log on main, not creating pull request
exit 0 # success
fi
fi
git commit -a -m "$message"
git push origin HEAD:$branch
gh pr create --title "$message" \
--body "$body" \
--head $branch \
--base main

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

960
.github/workflows/test_2.yml vendored Normal file
View File

@ -0,0 +1,960 @@
# Do not edit this file.
# This file is generated automatically by executing tox -e generate-workflows
name: Test 2
on:
push:
branches-ignore:
- 'release/*'
pull_request:
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
env:
# Set the SHA to the branch name if the PR has a label 'prepare-release' or 'backport' otherwise, set it to 'main'
# For PRs you can change the inner fallback ('main')
# For pushes you change the outer fallback ('main')
# The logic below is used during releases and depends on having an equivalent branch name in the core repo.
CORE_REPO_SHA: ${{ github.event_name == 'pull_request' && (
contains(github.event.pull_request.labels.*.name, 'prepare-release') && github.event.pull_request.head.ref ||
contains(github.event.pull_request.labels.*.name, 'backport') && github.event.pull_request.base.ref ||
'main'
) || 'main' }}
CONTRIB_REPO_SHA: main
PIP_EXISTS_ACTION: w
jobs:
py312-test-instrumentation-aio-pika-1_ubuntu-latest:
name: instrumentation-aio-pika-1 3.12 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e py312-test-instrumentation-aio-pika-1 -- -ra
py312-test-instrumentation-aio-pika-2_ubuntu-latest:
name: instrumentation-aio-pika-2 3.12 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e py312-test-instrumentation-aio-pika-2 -- -ra
py312-test-instrumentation-aio-pika-3_ubuntu-latest:
name: instrumentation-aio-pika-3 3.12 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e py312-test-instrumentation-aio-pika-3 -- -ra
py313-test-instrumentation-aio-pika-0_ubuntu-latest:
name: instrumentation-aio-pika-0 3.13 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.13
uses: actions/setup-python@v5
with:
python-version: "3.13"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e py313-test-instrumentation-aio-pika-0 -- -ra
py313-test-instrumentation-aio-pika-1_ubuntu-latest:
name: instrumentation-aio-pika-1 3.13 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.13
uses: actions/setup-python@v5
with:
python-version: "3.13"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e py313-test-instrumentation-aio-pika-1 -- -ra
py313-test-instrumentation-aio-pika-2_ubuntu-latest:
name: instrumentation-aio-pika-2 3.13 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.13
uses: actions/setup-python@v5
with:
python-version: "3.13"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e py313-test-instrumentation-aio-pika-2 -- -ra
py313-test-instrumentation-aio-pika-3_ubuntu-latest:
name: instrumentation-aio-pika-3 3.13 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.13
uses: actions/setup-python@v5
with:
python-version: "3.13"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e py313-test-instrumentation-aio-pika-3 -- -ra
pypy3-test-instrumentation-aio-pika-0_ubuntu-latest:
name: instrumentation-aio-pika-0 pypy-3.9 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python pypy-3.9
uses: actions/setup-python@v5
with:
python-version: "pypy-3.9"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e pypy3-test-instrumentation-aio-pika-0 -- -ra
pypy3-test-instrumentation-aio-pika-1_ubuntu-latest:
name: instrumentation-aio-pika-1 pypy-3.9 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python pypy-3.9
uses: actions/setup-python@v5
with:
python-version: "pypy-3.9"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e pypy3-test-instrumentation-aio-pika-1 -- -ra
pypy3-test-instrumentation-aio-pika-2_ubuntu-latest:
name: instrumentation-aio-pika-2 pypy-3.9 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python pypy-3.9
uses: actions/setup-python@v5
with:
python-version: "pypy-3.9"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e pypy3-test-instrumentation-aio-pika-2 -- -ra
pypy3-test-instrumentation-aio-pika-3_ubuntu-latest:
name: instrumentation-aio-pika-3 pypy-3.9 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python pypy-3.9
uses: actions/setup-python@v5
with:
python-version: "pypy-3.9"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e pypy3-test-instrumentation-aio-pika-3 -- -ra
py39-test-instrumentation-aiokafka_ubuntu-latest:
name: instrumentation-aiokafka 3.9 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.9
uses: actions/setup-python@v5
with:
python-version: "3.9"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e py39-test-instrumentation-aiokafka -- -ra
py310-test-instrumentation-aiokafka_ubuntu-latest:
name: instrumentation-aiokafka 3.10 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e py310-test-instrumentation-aiokafka -- -ra
py311-test-instrumentation-aiokafka_ubuntu-latest:
name: instrumentation-aiokafka 3.11 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e py311-test-instrumentation-aiokafka -- -ra
py312-test-instrumentation-aiokafka_ubuntu-latest:
name: instrumentation-aiokafka 3.12 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e py312-test-instrumentation-aiokafka -- -ra
py313-test-instrumentation-aiokafka_ubuntu-latest:
name: instrumentation-aiokafka 3.13 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.13
uses: actions/setup-python@v5
with:
python-version: "3.13"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e py313-test-instrumentation-aiokafka -- -ra
pypy3-test-instrumentation-aiokafka_ubuntu-latest:
name: instrumentation-aiokafka pypy-3.9 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python pypy-3.9
uses: actions/setup-python@v5
with:
python-version: "pypy-3.9"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e pypy3-test-instrumentation-aiokafka -- -ra
py39-test-instrumentation-kafka-python_ubuntu-latest:
name: instrumentation-kafka-python 3.9 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.9
uses: actions/setup-python@v5
with:
python-version: "3.9"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e py39-test-instrumentation-kafka-python -- -ra
py310-test-instrumentation-kafka-python_ubuntu-latest:
name: instrumentation-kafka-python 3.10 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e py310-test-instrumentation-kafka-python -- -ra
py311-test-instrumentation-kafka-python_ubuntu-latest:
name: instrumentation-kafka-python 3.11 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e py311-test-instrumentation-kafka-python -- -ra
py39-test-instrumentation-kafka-pythonng_ubuntu-latest:
name: instrumentation-kafka-pythonng 3.9 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.9
uses: actions/setup-python@v5
with:
python-version: "3.9"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e py39-test-instrumentation-kafka-pythonng -- -ra
py310-test-instrumentation-kafka-pythonng_ubuntu-latest:
name: instrumentation-kafka-pythonng 3.10 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e py310-test-instrumentation-kafka-pythonng -- -ra
py311-test-instrumentation-kafka-pythonng_ubuntu-latest:
name: instrumentation-kafka-pythonng 3.11 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e py311-test-instrumentation-kafka-pythonng -- -ra
py312-test-instrumentation-kafka-pythonng_ubuntu-latest:
name: instrumentation-kafka-pythonng 3.12 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e py312-test-instrumentation-kafka-pythonng -- -ra
py313-test-instrumentation-kafka-pythonng_ubuntu-latest:
name: instrumentation-kafka-pythonng 3.13 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.13
uses: actions/setup-python@v5
with:
python-version: "3.13"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e py313-test-instrumentation-kafka-pythonng -- -ra
pypy3-test-instrumentation-kafka-python_ubuntu-latest:
name: instrumentation-kafka-python pypy-3.9 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python pypy-3.9
uses: actions/setup-python@v5
with:
python-version: "pypy-3.9"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e pypy3-test-instrumentation-kafka-python -- -ra
pypy3-test-instrumentation-kafka-pythonng_ubuntu-latest:
name: instrumentation-kafka-pythonng pypy-3.9 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python pypy-3.9
uses: actions/setup-python@v5
with:
python-version: "pypy-3.9"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e pypy3-test-instrumentation-kafka-pythonng -- -ra
py39-test-instrumentation-confluent-kafka_ubuntu-latest:
name: instrumentation-confluent-kafka 3.9 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.9
uses: actions/setup-python@v5
with:
python-version: "3.9"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e py39-test-instrumentation-confluent-kafka -- -ra
py310-test-instrumentation-confluent-kafka_ubuntu-latest:
name: instrumentation-confluent-kafka 3.10 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e py310-test-instrumentation-confluent-kafka -- -ra
py311-test-instrumentation-confluent-kafka_ubuntu-latest:
name: instrumentation-confluent-kafka 3.11 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e py311-test-instrumentation-confluent-kafka -- -ra
py312-test-instrumentation-confluent-kafka_ubuntu-latest:
name: instrumentation-confluent-kafka 3.12 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e py312-test-instrumentation-confluent-kafka -- -ra
py313-test-instrumentation-confluent-kafka_ubuntu-latest:
name: instrumentation-confluent-kafka 3.13 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.13
uses: actions/setup-python@v5
with:
python-version: "3.13"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e py313-test-instrumentation-confluent-kafka -- -ra
py39-test-instrumentation-asyncio_ubuntu-latest:
name: instrumentation-asyncio 3.9 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.9
uses: actions/setup-python@v5
with:
python-version: "3.9"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e py39-test-instrumentation-asyncio -- -ra
py310-test-instrumentation-asyncio_ubuntu-latest:
name: instrumentation-asyncio 3.10 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e py310-test-instrumentation-asyncio -- -ra
py311-test-instrumentation-asyncio_ubuntu-latest:
name: instrumentation-asyncio 3.11 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e py311-test-instrumentation-asyncio -- -ra
py312-test-instrumentation-asyncio_ubuntu-latest:
name: instrumentation-asyncio 3.12 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e py312-test-instrumentation-asyncio -- -ra
py313-test-instrumentation-asyncio_ubuntu-latest:
name: instrumentation-asyncio 3.13 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.13
uses: actions/setup-python@v5
with:
python-version: "3.13"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e py313-test-instrumentation-asyncio -- -ra
py39-test-instrumentation-cassandra_ubuntu-latest:
name: instrumentation-cassandra 3.9 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.9
uses: actions/setup-python@v5
with:
python-version: "3.9"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e py39-test-instrumentation-cassandra -- -ra
py310-test-instrumentation-cassandra_ubuntu-latest:
name: instrumentation-cassandra 3.10 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e py310-test-instrumentation-cassandra -- -ra
py311-test-instrumentation-cassandra_ubuntu-latest:
name: instrumentation-cassandra 3.11 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e py311-test-instrumentation-cassandra -- -ra
py312-test-instrumentation-cassandra_ubuntu-latest:
name: instrumentation-cassandra 3.12 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e py312-test-instrumentation-cassandra -- -ra
py313-test-instrumentation-cassandra_ubuntu-latest:
name: instrumentation-cassandra 3.13 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.13
uses: actions/setup-python@v5
with:
python-version: "3.13"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e py313-test-instrumentation-cassandra -- -ra
pypy3-test-instrumentation-cassandra_ubuntu-latest:
name: instrumentation-cassandra pypy-3.9 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python pypy-3.9
uses: actions/setup-python@v5
with:
python-version: "pypy-3.9"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e pypy3-test-instrumentation-cassandra -- -ra
py39-test-processor-baggage_ubuntu-latest:
name: processor-baggage 3.9 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.9
uses: actions/setup-python@v5
with:
python-version: "3.9"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e py39-test-processor-baggage -- -ra
py310-test-processor-baggage_ubuntu-latest:
name: processor-baggage 3.10 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e py310-test-processor-baggage -- -ra
py311-test-processor-baggage_ubuntu-latest:
name: processor-baggage 3.11 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e py311-test-processor-baggage -- -ra
py312-test-processor-baggage_ubuntu-latest:
name: processor-baggage 3.12 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e py312-test-processor-baggage -- -ra
py313-test-processor-baggage_ubuntu-latest:
name: processor-baggage 3.13 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python 3.13
uses: actions/setup-python@v5
with:
python-version: "3.13"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e py313-test-processor-baggage -- -ra
pypy3-test-processor-baggage_ubuntu-latest:
name: processor-baggage pypy-3.9 Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo @ SHA - ${{ github.sha }}
uses: actions/checkout@v4
- name: Set up Python pypy-3.9
uses: actions/setup-python@v5
with:
python-version: "pypy-3.9"
- name: Install tox
run: pip install tox-uv
- name: Run tests
run: tox -e pypy3-test-processor-baggage -- -ra

View File

@ -1,5 +1,5 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.6.9
hooks:
@ -8,3 +8,8 @@ repos:
args: ["--fix", "--show-fixes"]
# Run the formatter.
- id: ruff-format
- repo: https://github.com/astral-sh/uv-pre-commit
# uv version.
rev: 0.6.0
hooks:
- id: uv-lock

View File

@ -7,7 +7,7 @@ extension-pkg-whitelist=cassandra
# Add list of files or directories to be excluded. They should be base names, not
# paths.
ignore=CVS,gen,Dockerfile,docker-compose.yml,README.md,requirements.txt,docs
ignore=CVS,gen,Dockerfile,docker-compose.yml,README.md,requirements.txt,docs,.venv,site-packages,.tox
# Add files or directories matching the regex patterns to be excluded. The
# regex matches against base names, not paths.
@ -46,7 +46,7 @@ suggestion-mode=yes
unsafe-load-any-extension=no
# Run python dependant checks considering the baseline version
py-version=3.8
py-version=3.9
[MESSAGES CONTROL]

View File

@ -6,10 +6,10 @@ sphinx:
configuration: docs/conf.py
build:
os: "ubuntu-22.04"
os: "ubuntu-24.04"
tools:
python: "3.8"
python: "3.11"
python:
install:
- requirements: docs-requirements.txt
- requirements: rtd-requirements.txt

View File

@ -11,6 +11,306 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased
## Version 1.35.0/0.56b0 (2025-07-11)
### Added
- `opentelemetry-instrumentation-pika` Added instrumentation for All `SelectConnection` adapters
([#3584](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3584))
- `opentelemetry-instrumentation-tornado` Add support for `WebSocketHandler` instrumentation
([#3498](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3498))
- `opentelemetry-util-http` Added support for redacting specific url query string values and url credentials in instrumentations
([#3508](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3508))
- `opentelemetry-instrumentation-pymongo` `aggregate` and `getMore` capture statements support
([#3601](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3601))
### Fixed
- `opentelemetry-instrumentation-asgi`: fix excluded_urls in instrumentation-asgi
([#3567](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3567))
- `opentelemetry-resource-detector-containerid`: make it more quiet on platforms without cgroups
([#3579](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3579))
## Version 1.34.0/0.55b0 (2025-06-04)
### Fixed
- `opentelemetry-instrumentation-system-metrics`: fix loading on Google Cloud Run
([#3533](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3533))
- `opentelemetry-instrumentation-fastapi`: fix wrapping of middlewares
([#3012](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3012))
- `opentelemetry-instrumentation-starlette` Remove max version constraint on starlette
([#3456](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3456))
- `opentelemetry-instrumentation-starlette` Fix memory leak and double middleware
([#3529](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3529))
- `opentelemetry-instrumentation-urllib3`: proper bucket boundaries in stable semconv http duration metrics
([#3518](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3518))
- `opentelemetry-instrumentation-urllib`: proper bucket boundaries in stable semconv http duration metrics
([#3519](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3519))
- `opentelemetry-instrumentation-falcon`: proper bucket boundaries in stable semconv http duration
([#3525](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3525))
- `opentelemetry-instrumentation-wsgi`: add explicit http duration buckets for stable semconv
([#3527](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3527))
- `opentelemetry-instrumentation-asgi`: add explicit http duration buckets for stable semconv
([#3526](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3526))
- `opentelemetry-instrumentation-flask`: proper bucket boundaries in stable semconv http duration
([#3523](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3523))
- `opentelemetry-instrumentation-django`: proper bucket boundaries in stable semconv http duration
([#3524](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3524))
- `opentelemetry-instrumentation-grpc`: support non-list interceptors
([#3520](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3520))
- `opentelemetry-instrumentation-botocore` Ensure spans end on early stream closure for Bedrock Streaming APIs
([#3481](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3481))
- `opentelemetry-instrumentation-sqlalchemy` Respect suppress_instrumentation functionality
([#3477](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3477))
- `opentelemetry-instrumentation-botocore`: fix handling of tool input in Bedrock ConverseStream
([#3544](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3544))
- `opentelemetry-instrumentation-botocore` Add type check when extracting tool use from Bedrock request message content
([#3548](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3548))
- `opentelemetry-instrumentation-dbapi` Respect suppress_instrumentation functionality ([#3460](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3460))
- `opentelemetry-resource-detector-container` Correctly parse container id when using systemd and cgroupsv1
([#3429](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3429))
### Breaking changes
- `opentelemetry-instrumentation-botocore` Use `cloud.region` instead of `aws.region` span attribute as per semantic conventions.
([#3474](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3474))
- `opentelemetry-instrumentation-fastapi`: Drop support for FastAPI versions earlier than `0.92`
([#3012](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3012))
- `opentelemetry-resource-detector-container`: rename package name to `opentelemetry-resource-detector-containerid`
([#3536](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3536))
### Added
- `opentelemetry-instrumentation-aiohttp-client` Add support for HTTP metrics
([#3517](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3517))
- `opentelemetry-instrumentation-httpx` Add support for HTTP metrics
([#3513](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3513))
- `opentelemetry-instrumentation` Allow re-raising exception when instrumentation fails
([#3545](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3545))
- `opentelemetry-instrumentation-aiokafka` Add instrumentation of `consumer.getmany` (batch)
([#3257](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3257))
### Deprecated
- Drop support for Python 3.8, bump baseline to Python 3.9.
([#3399](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3399))
## Version 1.33.0/0.54b0 (2025-05-09)
### Added
- `opentelemetry-instrumentation-requests` Support explicit_bucket_boundaries_advisory in duration metrics
([#3464](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3464))
- `opentelemetry-instrumentation-redis` Add support for redis client-specific instrumentation.
([#3143](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3143))
### Fixed
- `opentelemetry-instrumentation` Catch `ModuleNotFoundError` when the library is not installed
and log as debug instead of exception
([#3423](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3423))
- `opentelemetry-instrumentation-asyncio` Fix duplicate instrumentation
([#3383](https://github.com/open-telemetry/opentelemetry-python-contrib/issues/3383))
- `opentelemetry-instrumentation-botocore` Add GenAI instrumentation for additional Bedrock models for InvokeModel API
([#3419](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3419))
- `opentelemetry-instrumentation` don't print duplicated conflict log error message
([#3432](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3432))
- `opentelemetry-instrumentation-grpc` Check for None result in gRPC
([#3380](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3381))
- `opentelemetry-instrumentation-[asynclick/click]` Add missing opentelemetry-instrumentation dep
([#3447](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3447))
- `opentelemetry-instrumentation-botocore` Capture server attributes for botocore API calls
([#3448](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3448))
## Version 1.32.0/0.53b0 (2025-04-10)
### Added
- `opentelemetry-instrumentation-asyncclick`: new instrumentation to trace asyncclick commands
([#3319](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3319))
- `opentelemetry-instrumentation-botocore` Add support for GenAI tool events using Amazon Nova models and `InvokeModel*` APIs
([#3385](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3385))
- `opentelemetry-instrumentation` Make auto instrumentation use the same dependency resolver as manual instrumentation does
([#3202](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3202))
### Fixed
- `opentelemetry-instrumentation` Fix client address is set to server address in new semconv
([#3354](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3354))
- `opentelemetry-instrumentation-dbapi`, `opentelemetry-instrumentation-django`,
`opentelemetry-instrumentation-sqlalchemy`: Fix sqlcomment for non string query and composable object.
([#3113](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3113))
- `opentelemetry-instrumentation-grpc` Fix error when using gprc versions <= 1.50.0 with unix sockets.
([[#3393](https://github.com/open-telemetry/opentelemetry-python-contrib/issues/3393)])
- `opentelemetry-instrumentation-asyncio` Fix duplicate instrumentation.
([[#3383](https://github.com/open-telemetry/opentelemetry-python-contrib/issues/3383)])
- `opentelemetry-instrumentation-aiokafka` Fix send_and_wait method no headers kwargs error.
([[#3332](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3332)])
## Version 1.31.0/0.52b0 (2025-03-12)
### Added
- `opentelemetry-instrumentation-openai-v2` Update doc for OpenAI Instrumentation to support OpenAI Compatible Platforms
([#3279](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3279))
- `opentelemetry-instrumentation-system-metrics` Add `process` metrics and deprecated `process.runtime` prefixed ones
([#3250](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3250))
- `opentelemetry-instrumentation-botocore` Add support for GenAI user events and lazy initialize tracer
([#3258](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3258))
- `opentelemetry-instrumentation-botocore` Add support for GenAI system events
([#3266](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3266))
- `opentelemetry-instrumentation-botocore` Add support for GenAI choice events
([#3275](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3275))
- `opentelemetry-instrumentation-botocore` Add support for GenAI tool events
([#3302](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3302))
- `opentelemetry-instrumentation-botocore` Add support for GenAI metrics
([#3326](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3326))
- `opentelemetry-instrumentation` make it simpler to initialize auto-instrumentation programmatically
([#3273](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3273))
- Add `opentelemetry-instrumentation-vertexai>=2.0b0` to `opentelemetry-bootstrap`
([#3307](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3307))
- Loosen `opentelemetry-instrumentation-starlette[instruments]` specifier
([#3304](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3304))
### Fixed
- `opentelemetry-instrumentation-redis` Add missing entry in doc string for `def _instrument`
([#3247](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3247))
- `opentelemetry-instrumentation-botocore` sns-extension: Change destination name attribute
to match topic ARN and redact phone number from attributes
([#3249](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3249))
- `opentelemetry-instrumentation-asyncpg` Fix fallback for empty queries.
([#3253](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3253))
- `opentelemetry-instrumentation` Fix a traceback in sqlcommenter when psycopg connection pooling is enabled.
([#3309](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3309))
- `opentelemetry-instrumentation-threading` Fix broken context typehints
([#3322](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3322))
- `opentelemetry-instrumentation-requests` always record span status code in duration metric
([#3323](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3323))
## Version 1.30.0/0.51b0 (2025-02-03)
### Added
- `opentelemetry-instrumentation-confluent-kafka` Add support for confluent-kafka <=2.7.0
([#3100](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3100))
- Add support to database stability opt-in in `_semconv` utilities and add tests
([#3111](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3111))
- `opentelemetry-instrumentation-urllib` Add `py.typed` file to enable PEP 561
([#3131](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3131))
- `opentelemetry-opentelemetry-pymongo` Add `py.typed` file to enable PEP 561
([#3136](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3136))
- `opentelemetry-opentelemetry-requests` Add `py.typed` file to enable PEP 561
([#3135](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3135))
- `opentelemetry-instrumentation-system-metrics` Add `py.typed` file to enable PEP 561
([#3132](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3132))
- `opentelemetry-opentelemetry-sqlite3` Add `py.typed` file to enable PEP 561
([#3133](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3133))
- `opentelemetry-instrumentation-falcon` add support version to v4
([#3086](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3086))
- `opentelemetry-instrumentation-falcon` Implement new HTTP semantic convention opt-in for Falcon
([#2790](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2790))
- `opentelemetry-instrumentation-wsgi` always record span status code to have it available in metrics
([#3148](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3148))
- add support to Python 3.13
([#3134](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3134))
- `opentelemetry-opentelemetry-wsgi` Add `py.typed` file to enable PEP 561
([#3129](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3129))
- `opentelemetry-util-http` Add `py.typed` file to enable PEP 561
([#3127](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3127))
- `opentelemetry-instrumentation-psycopg2` Add support for psycopg2-binary
([#3186](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3186))
- `opentelemetry-opentelemetry-botocore` Add basic support for GenAI attributes for AWS Bedrock Converse API
([#3161](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3161))
- `opentelemetry-opentelemetry-botocore` Add basic support for GenAI attributes for AWS Bedrock InvokeModel API
([#3200](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3200))
- `opentelemetry-opentelemetry-botocore` Add basic support for GenAI attributes for AWS Bedrock ConverseStream API
([#3204](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3204))
- `opentelemetry-opentelemetry-botocore` Add basic support for GenAI attributes for AWS Bedrock InvokeModelWithStreamResponse API
([#3206](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3206))
- `opentelemetry-instrumentation-pymssql` Add pymssql instrumentation
([#394](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/394))
- `opentelemetry-instrumentation-mysql` Add sqlcommenter support
([#3163](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3163))
### Fixed
- `opentelemetry-instrumentation-httpx` Fix `RequestInfo`/`ResponseInfo` type hints
([#3105](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3105))
- `opentelemetry-instrumentation-dbapi` Move `TracedCursorProxy` and `TracedConnectionProxy` to the module level
([#3068](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3068))
- `opentelemetry-instrumentation-click` Disable tracing of well-known server click commands
([#3174](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3174))
- `opentelemetry-instrumentation` Fix `get_dist_dependency_conflicts` if no distribution requires
([#3168](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3168))
### Breaking changes
- `opentelemetry-exporter-prometheus-remote-write` updated protobuf required version from 4.21 to 5.26 and regenerated protobufs
([#3219](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3219))
- `opentelemetry-instrumentation-sqlalchemy` including sqlcomment in `db.statement` span attribute value is now opt-in
([#3112](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3112))
- `opentelemetry-instrumentation-dbapi` including sqlcomment in `db.statement` span attribute value is now opt-in
([#3115](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3115))
- `opentelemetry-instrumentation-psycopg2`, `opentelemetry-instrumentation-psycopg`, `opentelemetry-instrumentation-mysqlclient`, `opentelemetry-instrumentation-pymysql`: including sqlcomment in `db.statement` span attribute value is now opt-in
([#3121](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3121))
## Version 1.29.0/0.50b0 (2024-12-11)
### Added
- `opentelemetry-instrumentation-starlette` Add type hints to the instrumentation
([#3045](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3045))
- `opentelemetry-distro` default to OTLP log exporter.
([#3042](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3042))
- `opentelemetry-instrumentation-sqlalchemy` Update unit tests to run with SQLALchemy 2
([#2976](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2976))
- Add `opentelemetry-instrumentation-openai-v2` to `opentelemetry-bootstrap`
([#2996](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2996))
- `opentelemetry-instrumentation-sqlalchemy` Add sqlcomment to `db.statement` attribute
([#2937](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2937))
- `opentelemetry-instrumentation-dbapi` Add sqlcomment to `db.statement` attribute
([#2935](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2935))
- `opentelemetry-instrumentation-dbapi` instrument_connection accepts optional connect_module
([#3027](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3027))
- `opentelemetry-instrumentation-mysqlclient` Add sqlcommenter support
([#2941](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2941))
- `opentelemetry-instrumentation-pymysql` Add sqlcommenter support
([#2942](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2942))
- `opentelemetry-instrumentation-click`: new instrumentation to trace click commands
([#2994](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2994))
### Fixed
- `opentelemetry-instrumentation-starlette`: Retrieve `meter_provider` key instead of `_meter_provider` on `_instrument`
([#3048](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3048))
- `opentelemetry-instrumentation-httpx`: instrument_client is a static method again
([#3003](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3003))
- `opentelemetry-instrumentation-system_metrics`: fix callbacks reading wrong config
([#3025](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3025))
- `opentelemetry-instrumentation-httpx`: Check if mount transport is none before wrap it
([#3022](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3022))
- Replace all instrumentor unit test `assertEqualSpanInstrumentationInfo` calls with `assertEqualSpanInstrumentationScope` calls
([#3037](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3037))
- `opentelemetry-instrumentation-sqlalchemy` Fixes engines from `sqlalchemy.engine_from_config` not being fully instrumented
([#2816](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2816))
- `opentelemetry-instrumentation-sqlalchemy`: Fix a remaining memory leak in EngineTracer
([#3053](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3053))
- `opentelemetry-instrumentation-sqlite3`: Update documentation on explicit cursor support of tracing
([#3088](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3088))
### Breaking changes
- `opentelemetry-instrumentation-sqlalchemy` teach instruments version
([#2971](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2971))
- Drop `opentelemetry-instrumentation-test` package from default instrumentation list
([#2969](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2969))
- `opentelemetry-instrumentation-httpx`: remove private unused `_InstrumentedClient` and `_InstrumentedAsyncClient` classes
([#3036](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3036))
## Version 1.28.0/0.49b0 (2024-11-05)
### Added
- `opentelemetry-instrumentation-openai-v2` Instrumentation for OpenAI >= 0.27.0

View File

@ -19,23 +19,31 @@ Please also read the [OpenTelemetry Contributor Guide](https://github.com/open-t
## Index
* [Find a Buddy and get Started Quickly](#find-a-buddy-and-get-started-quickly)
* [Development](#development)
* [Troubleshooting](#troubleshooting)
* [Benchmarks](#benchmarks)
* [Pull requests](#pull-requests)
* [How to Send Pull Requests](#how-to-send-pull-requests)
* [How to Receive Comments](#how-to-receive-comments)
* [How to Get PRs Reviewed](#how-to-get-prs-reviewed)
* [How to Get PRs Merged](#how-to-get-prs-merged)
* [Design Choices](#design-choices)
* [Focus on Capabilities, Not Structure Compliance](#focus-on-capabilities-not-structure-compliance)
* [Running Tests Locally](#running-tests-locally)
* [Testing against a different Core repo branch/commit](#testing-against-a-different-core-repo-branchcommit)
* [Style Guide](#style-guide)
* [Guideline for instrumentations](#guideline-for-instrumentations)
* [Guidance for GenAI instrumentations](#guideline-for-genai-instrumentations)
* [Expectations from contributors](#expectations-from-contributors)
- [Contributing to opentelemetry-python-contrib](#contributing-to-opentelemetry-python-contrib)
- [Index](#index)
- [Find a Buddy and get Started Quickly](#find-a-buddy-and-get-started-quickly)
- [Development](#development)
- [Virtual Environment](#virtual-environment)
- [Troubleshooting](#troubleshooting)
- [Benchmarks](#benchmarks)
- [Pull Requests](#pull-requests)
- [How to Send Pull Requests](#how-to-send-pull-requests)
- [How to Receive Comments](#how-to-receive-comments)
- [How to Get PRs Reviewed](#how-to-get-prs-reviewed)
- [How to Get PRs Merged](#how-to-get-prs-merged)
- [Design Choices](#design-choices)
- [Focus on Capabilities, Not Structure Compliance](#focus-on-capabilities-not-structure-compliance)
- [Running Tests Locally](#running-tests-locally)
- [Testing against a different Core repo branch/commit](#testing-against-a-different-core-repo-branchcommit)
- [Style Guide](#style-guide)
- [Guideline for instrumentations](#guideline-for-instrumentations)
- [Update supported instrumentation package versions](#update-supported-instrumentation-package-versions)
- [Guideline for GenAI instrumentations](#guideline-for-genai-instrumentations)
- [Get Involved](#get-involved)
- [Expectations from contributors](#expectations-from-contributors)
- [Updating supported Python versions](#updating-supported-python-versions)
- [Bumping the Python baseline](#bumping-the-python-baseline)
- [Adding support for a new Python release](#adding-support-for-a-new-python-release)
## Find a Buddy and get Started Quickly
@ -56,39 +64,62 @@ some aspects of development, including testing against multiple Python versions.
To install `tox`, run:
```sh
$ pip install tox
pip install tox
```
You can also run tox with `uv` support. By default [tox.ini](./tox.ini) will automatically create a provisioned tox environment with `tox-uv`, but you can install it at host level:
```sh
pip install tox-uv
```
You can run `tox` with the following arguments:
* `tox` to run all existing tox commands, including unit tests for all packages
under multiple Python versions
* `tox -e docs` to regenerate the API docs
* `tox -e docs` to regenerate all docs
* `tox -e py312-test-instrumentation-aiopg` to e.g. run the aiopg instrumentation unit tests under a specific
Python version
* `tox -e spellcheck` to run a spellcheck on all the code
* `tox -e lint-some-package` to run lint checks on `some-package`
* `tox -e generate-workflows` to run creation of new CI workflows if tox environments have been updated
* `tox -e ruff` to run ruff linter and formatter checks against the entire codebase
`ruff check` and `ruff format` are executed when `tox -e ruff` is run. We strongly recommend you to configure [pre-commit](https://pre-commit.com/) locally to run `ruff` automatically before each commit by installing it as git hooks. You just need to [install pre-commit](https://pre-commit.com/#install) in your environment:
```console
$ pip install pre-commit -c dev-requirements.txt
pip install pre-commit -c dev-requirements.txt
```
and run this command inside the git repository:
```console
$ pre-commit install
pre-commit install
```
See
[`tox.ini`](https://github.com/open-telemetry/opentelemetry-python-contrib/blob/main/tox.ini)
for more detail on available tox commands.
### Virtual Environment
You can also create a single virtual environment to make it easier to run local tests.
For that, you'll need to install [`uv`](https://docs.astral.sh/uv/getting-started/installation/).
After installing `uv`, you can run the following command:
```sh
uv sync
```
This will create a virtual environment in the `.venv` directory and install all the necessary dependencies.
### Troubleshooting
> Some packages may require additional system wide dependencies to be installed. For example, you may need to install `libpq-dev` to run the postgresql client libraries instrumentation tests. or `libsnappy-dev` to run the prometheus exporter tests. If you encounter a build error, please check the installation instructions for the package you are trying to run tests for.
Some packages may require additional system-wide dependencies to be installed. For example, you may need to install `libpq-dev` to run the postgresql client libraries instrumentation tests or `libsnappy-dev` to run the prometheus exporter tests. If you encounter a build error, please check the installation instructions for the package you are trying to run tests for.
For `docs` building, you may need to install `mysql-client` and other required dependencies as necessary. Ensure the Python version used in your local setup matches the version used in the [CI](./.github/workflows/) to maintain compatibility when building the documentation.
### Benchmarks
@ -123,31 +154,45 @@ pull requests (PRs).
To create a new PR, fork the project in GitHub and clone the upstream repo:
```sh
$ git clone https://github.com/open-telemetry/opentelemetry-python-contrib.git
$ cd opentelemetry-python-contrib
git clone https://github.com/open-telemetry/opentelemetry-python-contrib.git
cd opentelemetry-python-contrib
```
Add your fork as an origin:
```sh
$ git remote add fork https://github.com/YOUR_GITHUB_USERNAME/opentelemetry-python-contrib.git
git remote add fork https://github.com/YOUR_GITHUB_USERNAME/opentelemetry-python-contrib.git
```
Run tests:
make sure you have all supported versions of Python installed, install `tox` only for the first time:
```sh
# make sure you have all supported versions of Python installed
$ pip install tox # only first time.
$ tox # execute in the root of the repository
pip install tox tox-uv
```
Run tests in the root of the repository (this will run all tox environments and may take some time):
```sh
tox
```
Check out a new branch, make modifications and push the branch to your fork:
```sh
$ git checkout -b feature
# edit files
$ git commit
$ git push fork feature
git checkout -b feature
```
After you edit the files, stage changes in the current directory:
```sh
git add .
```
Then run the following to commit the changes:
```sh
git commit
git push fork feature
```
Open a pull request against the main `opentelemetry-python-contrib` repo.
@ -271,15 +316,33 @@ Below is a checklist of things to be mindful of when implementing a new instrume
- Isolate sync and async test
- For synchronous tests, the typical test case class is inherited from `opentelemetry.test.test_base.TestBase`. However, if you want to write asynchronous tests, the test case class should inherit also from `IsolatedAsyncioTestCase`. Adding asynchronous tests to a common test class can lead to tests passing without actually running, which can be misleading.
- ex. <https://github.com/open-telemetry/opentelemetry-python-contrib/blob/60fb936b7e5371b3e5587074906c49fb873cbd76/instrumentation/opentelemetry-instrumentation-grpc/tests/test_aio_server_interceptor.py#L84>
- All instrumentations have the same version. If you are going to develop a new instrumentation it would probably have `X.Y.dev` version and depends on `opentelemetry-instrumentation` and `opentelemetry-semantic-conventions` for the same version. That means that if you want to install your instrumentation you need to install its dependencies from this repo and the core repo also from git.
- Most of the instrumentations have the same version. If you are going to develop a new instrumentation it would probably have `X.Y.dev` version and depends on `opentelemetry-instrumentation` and `opentelemetry-semantic-conventions` for a [compatible version](https://peps.python.org/pep-0440/#compatible-release). That means that you may need to install the instrumentation dependencies from this repo and the core repo from git.
- Documentation
- When adding a new instrumentation remember to add an entry in `docs/instrumentation/` named `<instrumentation>/<instrumentation>.rst` to have the instrumentation documentation referenced from the index. You can use the entry template available [here](./_template/autodoc_entry.rst)
- Testing
- When adding a new instrumentation remember to update `tox.ini` adding appropriate rules in `envlist`, `command_pre` and `commands` sections
## Guidance for GenAI instrumentations
### Update supported instrumentation package versions
Instrumentations that relate to [Generative AI](https://opentelemetry.io/docs/specs/semconv/gen-ai/) systems will be placed in the [genai](./instrumentation/genai) folder. This section covers contributions related to those instrumentations. Please note that the [guidelines for instrumentations](#guideline-for-instrumentations) and [expectations from contributors](#expectations-from-contributors) still apply.
- Navigate to the **instrumentation package directory:**
- Update **`pyproject.toml`** file by modifying _instruments_ entry in the `[project.optional-dependencies]` section with the new version constraint
- Update `_instruments` variable in instrumentation **`package.py`** file with the new version constraint
- At the **root of the project directory**, run `tox -e generate` to regenerate necessary files
If you're adding support for a new version of the instrumentation package, follow these additional steps:
- At the **instrumentation package directory:** Add new test-requirements.txt file with the respective package version required for testing
- At the **root of the project directory**: Add a new test environment entry for the package version in [tox.ini](./tox.ini) and run `tox -e generate-workflows` to regenerate new workflows accordingly. In the same [tox.ini](./tox.ini) file, search for `opentelemetry-instrumentation-{package}/test-requirements` and add a new line to point to the new test-requirements.txt you created in the previous step so tox can install the correct requirements.
Example PRs: [#2976](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2976), [#2845](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2845)
## Guideline for GenAI instrumentations
Instrumentations that relate to [Generative AI](https://opentelemetry.io/docs/specs/semconv/gen-ai/) systems will be placed in the [instrumentation-genai](./instrumentation-genai) folder. This section covers contributions related to those instrumentations. Please note that the [guidelines for instrumentations](#guideline-for-instrumentations) and [expectations from contributors](#expectations-from-contributors) still apply.
### Get Involved
* Reviewing PRs: If you would like to be tagged as reviewer in new PRs related to these instrumentations, please submit a PR to add your GitHub handle to [component_owners.yml](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2944/.github/component_owners.yml) under the corresponding instrumentation folder(s).
* Reviewing PRs: If you would like to be tagged as reviewer in new PRs related to these instrumentations, please submit a PR to add your GitHub handle to [component_owners.yml](https://github.com/open-telemetry/opentelemetry-python-contrib/blob/main/.github/component_owners.yml) under the corresponding instrumentation folder(s).
* Approving PRs: If you would like to be able to approve PRs related to these instrumentations, you must join [opentelemetry-python-contrib-approvers](https://github.com/orgs/open-telemetry/teams/opentelemetry-python-contrib-approvers) team. Please ask one of the [Python contrib maintainers](https://github.com/orgs/open-telemetry/teams/opentelemetry-python-contrib-maintainers) to be accepted into the team.
@ -297,6 +360,7 @@ When updating the minimum supported Python version remember to:
- Remove the version in `pyproject.toml` trove classifiers
- Remove the version from `tox.ini`
- Update github workflows accordingly with `tox -e generate-workflows`
- Search for `sys.version_info` usage and remove code for unsupported versions
- Bump `py-version` in `.pylintrc` for Python version dependent checks
@ -306,6 +370,6 @@ When adding support for a new Python release remember to:
- Add the version in `tox.ini`
- Add the version in `pyproject.toml` trove classifiers
- Update github workflows accordingly; lint and benchmarks use the latest supported version
- Update github workflows accordingly with `tox -e generate-workflows`; lint and benchmarks use the latest supported version
- Update `.pre-commit-config.yaml`
- Update tox examples in the documentation

View File

@ -33,7 +33,7 @@
<strong>
<a href="CONTRIBUTING.md">Contributing<a/>
&nbsp;&nbsp;&bull;&nbsp;&nbsp;
<a href="https://opentelemetry-python-contrib.readthedocs.io/en/stable/#examples">Examples<a/>
<a href="https://opentelemetry-python-contrib.readthedocs.io/en/latest/#instrumentations">Instrumentations<a/>
</strong>
</p>
@ -48,6 +48,7 @@ The Python auto-instrumentation libraries for [OpenTelemetry](https://openteleme
* [Installation](#installation)
* [Releasing](#releasing)
* [Releasing a package as `1.0` stable](#releasing-a-package-as-10-stable)
* [Semantic Convention status of instrumentations](#semantic-convention-status-of-instrumentations)
* [Contributing](#contributing)
* [Thanks to all the people who already contributed](#thanks-to-all-the-people-who-already-contributed)
@ -100,7 +101,7 @@ To release a package as `1.0` stable, the package:
## Semantic Convention status of instrumentations
In our efforts to maintain optimal user experience and prevent breaking changes for transitioning into stable semantic conventions, OpenTelemetry Python is adopting the [semantic convention migration plan](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/http/migration-guide.md) for several instrumentations. Currently this plan is only being adopted for HTTP-related instrumentations, but will eventually cover all types. Please refer to the `semconv status` column of the [instrumentation README](instrumentation/README.md) of the current status of instrumentations' semantic conventions. The possible values are `experimental`, `stable` and `migration` referring to [status](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.31.0/specification/document-status.md#lifecycle-status) of that particular semantic convention. `Migration` refers to an instrumentation that currently supports the migration plan.
In our efforts to maintain optimal user experience and prevent breaking changes for transitioning into stable semantic conventions, OpenTelemetry Python is adopting the semantic convention migration plan for several instrumentations. Currently this plan is only being adopted for [HTTP-related instrumentations](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/non-normative/http-migration.md), but will eventually cover all types. Please refer to the `semconv status` column of the [instrumentation README](instrumentation/README.md) of the current status of instrumentations' semantic conventions. The possible values are `development`, `stable` and `migration` referring to [status](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.31.0/specification/document-status.md#lifecycle-status) of that particular semantic convention. `Migration` refers to an instrumentation that currently supports the migration plan.
## Contributing
@ -110,9 +111,18 @@ We meet weekly on Thursday at 9AM PT. The meeting is subject to change depending
Meeting notes are available as a public [Google doc](https://docs.google.com/document/d/1CIMGoIOZ-c3-igzbd6_Pnxx1SjAkjwqoYSUWxPY8XIs/edit). For edit access, get in touch on [GitHub Discussions](https://github.com/open-telemetry/opentelemetry-python/discussions).
Approvers ([@open-telemetry/python-approvers](https://github.com/orgs/open-telemetry/teams/python-approvers)):
### Maintainers
- [Emídio Neto](https://github.com/emdneto), Zenvia
- [Aaron Abbott](https://github.com/aabmass), Google
- [Leighton Chen](https://github.com/lzchen), Microsoft
- [Riccardo Magliocchetti](https://github.com/xrmx), Elastic
- [Shalev Roda](https://github.com/shalevr), Cisco
For more information about the maintainer role, see the [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#maintainer).
### Approvers
- [Emídio Neto](https://github.com/emdneto), PicPay
- [Jeremy Voss](https://github.com/jeremydvoss), Microsoft
- [Owais Lone](https://github.com/owais), Splunk
- [Pablo Collins](https://github.com/pmcollins), Splunk
@ -120,34 +130,29 @@ Approvers ([@open-telemetry/python-approvers](https://github.com/orgs/open-telem
- [Srikanth Chekuri](https://github.com/srikanthccv), signoz.io
- [Tammy Baylis](https://github.com/tammy-baylis-swi), SolarWinds
Emeritus Approvers:
For more information about the approver role, see the [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#approver).
- [Ashutosh Goel](https://github.com/ashu658), Cisco
- [Héctor Hernández](https://github.com/hectorhdzg), Microsoft
- [Nikolay Sokolik](https://github.com/oxeye-nikolay), Oxeye
- [Nikolay Sokolik](https://github.com/nikosokolik), Oxeye
- [Nathaniel Ruiz Nowell](https://github.com/NathanielRN), AWS
### Emeritus Maintainers
*Find more about the approver role in [community repository](https://github.com/open-telemetry/community/blob/main/community-membership.md#approver).*
- [Alex Boten](https://github.com/codeboten)
- [Diego Hurtado](https://github.com/ocelotl)
- [Owais Lone](https://github.com/owais)
- [Yusuke Tsutsumi](https://github.com/toumorokoshi)
Maintainers ([@open-telemetry/python-maintainers](https://github.com/orgs/open-telemetry/teams/python-maintainers)):
For more information about the emeritus role, see the [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#emeritus-maintainerapprovertriager).
- [Aaron Abbott](https://github.com/aabmass), Google
- [Leighton Chen](https://github.com/lzchen), Microsoft
- [Riccardo Magliocchetti](https://github.com/xrmx), Elastic
- [Shalev Roda](https://github.com/shalevr), Cisco
### Emeritus Approvers
Emeritus Maintainers:
- [Ashutosh Goel](https://github.com/ashu658)
- [Héctor Hernández](https://github.com/hectorhdzg)
- [Nathaniel Ruiz Nowell](https://github.com/NathanielRN)
- [Nikolay Sokolik](https://github.com/nikosokolik)
- [Nikolay Sokolik](https://github.com/oxeye-nikolay)
- [Alex Boten](https://github.com/codeboten), Lightstep
- [Diego Hurtado](https://github.com/ocelotl), Lightstep
- [Owais Lone](https://github.com/owais), Splunk
- [Yusuke Tsutsumi](https://github.com/toumorokoshi), Google
For more information about the emeritus role, see the [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#emeritus-maintainerapprovertriager).
*Find more about the maintainer role in [community repository](https://github.com/open-telemetry/community/blob/main/community-membership.md#maintainer).*
### Thanks to all the people who already contributed
### Thanks to all of our contributors!
<a href="https://github.com/open-telemetry/opentelemetry-python-contrib/graphs/contributors">
<img src="https://contributors-img.web.app/image?repo=open-telemetry/opentelemetry-python-contrib" />
<img alt="Repo contributors" src="https://contrib.rocks/image?repo=open-telemetry/opentelemetry-python-contrib" />
</a>

View File

@ -9,8 +9,10 @@
(otherwise the workflow will pick up the version from `main` and just remove the `.dev` suffix).
* Review the two pull requests that it creates.
(one is targeted to the release branch and one is targeted to `main`).
* Merge the one targeted towards the release branch.
* The builds will fail for the `main` pr because of validation rules. Follow the [release workflow](https://github.com/open-telemetry/opentelemetry-python/blob/main/RELEASING.md) for the core repo up until this same point. Change the SHAs of each PR to point at each other to get the `main` builds to pass.
* The builds will fail for the release PR because of validation rules. Follow the [release workflow](https://github.com/open-telemetry/opentelemetry-python/blob/main/RELEASING.md) for the core repo up until this same point.
* Close and reopen the PR so that the workflow will take into account the label automation we have in place
* Merge the release PR.
* Merge the PR to main (this can be done separately from [making the release](#making-the-release))
### Preparing a major or minor release for individual package
@ -19,6 +21,9 @@
> - opentelemetry-propagator-aws-xray
> - opentelemetry-resource-detector-azure
> - opentelemetry-sdk-extension-aws
> - opentelemetry-instrumentation-openai-v2
> - opentelemetry-instrumentation-vertexai
> - opentelemetry-instrumentation-google-genai
>
> These libraries are also excluded from the general release.
@ -27,6 +32,8 @@ to pick a specific package to release. It follows the same versioning strategy a
Long-term package release branch follows `package-release/{package-name}/v{major}.{minor}.x` (or `package-release/{package-name}/v{major}.{minor}bx`) naming pattern.
The workflow will create two pull requests, one against the `main` and one against the `package-release/` branch; both should be merged in order to proceed with the release.
## Preparing a new patch release
* Backport pull request(s) to the release branch.
@ -34,6 +41,8 @@ Long-term package release branch follows `package-release/{package-name}/v{major
* Press the "Run workflow" button, then select the release branch from the dropdown list,
e.g. `release/v1.9.x`, then enter the pull request number that you want to backport,
then click the "Run workflow" button below that.
* Add the label `backport` to the generated pull request.
* In case label automation doesn't work, just close and reopen the PR so that the workflow will take into account the label automation we have in place.
* Review and merge the backport pull request that it generates.
* Merge a pull request to the release branch updating the `CHANGELOG.md`.
* The heading for the unreleased entries should be `## Unreleased`.
@ -41,6 +50,7 @@ Long-term package release branch follows `package-release/{package-name}/v{major
* Press the "Run workflow" button, then select the release branch from the dropdown list,
e.g. `release/v1.9.x`, and click the "Run workflow" button below that.
* Review and merge the pull request that it creates for updating the version.
* Note: If you are doing a patch release in `-contrib` repo, you should also do an equivalent patch release in `-core` repo (even if there's no fix to release), otherwise tests in CI will fail.
### Preparing a patch release for individual package
@ -53,6 +63,8 @@ to pick a specific package to release.
The workflow can only be run against long-term release branch such as `package-release/{package-name}/v{major}.{minor}.x` or `package-release/{package-name}/v{major}.{minor}bx`.
The workflow will create a pull request that should be merged in order to proceed with the release.
## Making the release
* Run the [Release workflow](https://github.com/open-telemetry/opentelemetry-python-contrib/actions/workflows/release.yml).
@ -62,6 +74,7 @@ The workflow can only be run against long-term release branch such as `package-r
* Review and merge the pull request that it creates for updating the change log in main
(note that if this is not a patch release then the change log on main may already be up-to-date,
in which case no pull request will be created).
* Verify that a new [Github release](https://github.com/open-telemetry/opentelemetry-python-contrib/releases) has been created and that the CHANGELOGs look correct.
### Releasing individual package
@ -70,6 +83,9 @@ The workflow can only be run against long-term release branch such as `package-r
> - opentelemetry-propagator-aws-xray
> - opentelemetry-resource-detector-azure
> - opentelemetry-sdk-extension-aws
> - opentelemetry-instrumentation-openai-v2
> - opentelemetry-instrumentation-vertexai
> - opentelemetry-instrumentation-google-genai
>
> These libraries are also excluded from the general patch release.
@ -78,6 +94,14 @@ to pick a specific package to release.
The workflow can only be run against long-term release branch such as `package-release/{package-name}/v{major}.{minor}.x` or `package-release/{package-name}/v{major}.{minor}bx`.
## After the release
* Check PyPI
* This should be handled automatically on release by the [publish action](https://github.com/open-telemetry/opentelemetry-python-contrib/blob/main/.github/workflows/release.yml).
* Check the [action logs](https://github.com/open-telemetry/opentelemetry-python-contrib/actions/workflows/release.yml) to make sure packages have been uploaded to PyPI
* Check the release history (e.g. https://pypi.org/project/opentelemetry-instrumentation/#history) on PyPI
* If for some reason the action failed, see [Publish failed](#publish-failed) below
## Notes about version numbering for stable components
* The version number for stable components in the `main` branch is always `X.Y.0.dev`,
@ -109,28 +133,6 @@ The workflow can only be run against long-term release branch such as `package-r
* The version number for unstable components in the `main` branch will be bumped to the next version,
e.g. `0.{Y+1}b0.dev`.
## After the release
* Check PyPI
* This should be handled automatically on release by the [publish action](https://github.com/open-telemetry/opentelemetry-python-contrib/blob/main/.github/workflows/release.yml).
* Check the [action logs](https://github.com/open-telemetry/opentelemetry-python-contrib/actions/workflows/release.yml) to make sure packages have been uploaded to PyPI
* Check the release history (e.g. https://pypi.org/project/opentelemetry-instrumentation/#history) on PyPI
* If for some reason the action failed, see [Publish failed](#publish-failed) below
* Move stable tag
* Run the following (TODO automate):
```bash
git tag -d stable
git tag stable
git push --delete origin tagname
git push origin stable
```
* This will ensure the docs are pointing at the stable release.
* To validate this worked, ensure the stable build has run successfully:
<https://readthedocs.org/projects/opentelemetry-python/builds/>.
If the build has not run automatically, it can be manually trigger via the readthedocs interface.
## Releasing dev version of new packages to claim namespace
When a contribution introduces a new package, in order to mitigate name-squatting incidents, release the current development version of the new package under the `opentelemetry` user to simply claim the namespace. This should be done shortly after the PR that introduced this package has been merged into `main`.

View File

@ -0,0 +1,7 @@
.. include:: ../../../instrumentation/opentelemetry-instrumentation-<REPLACE ME>/README.rst
:end-before: References
.. automodule:: opentelemetry.instrumentation.<REPLACE ME>
:members:
:undoc-members:
:show-inheritance:

View File

@ -12,7 +12,7 @@ dynamic = ["version"]
description = "<REPLACE ME>"
readme = "README.rst"
license = "Apache-2.0"
requires-python = ">=3.8"
requires-python = ">=3.9"
authors = [
{ name = "OpenTelemetry Authors", email = "cncf-opentelemetry-contributors@lists.cncf.io" },
]
@ -22,11 +22,11 @@ classifiers = [
"License :: OSI Approved :: Apache Software License",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
]
dependencies = [
"opentelemetry-api ~= 1.12",
@ -41,6 +41,7 @@ REPLACE_ME = "opentelemetry.instrumentation.<REPLACE>"
# url of the instrumentation e.g
# Homepage = "https://github.com/open-telemetry/opentelemetry-python-contrib/instrumentation/opentelemetry-instrumentation-sqlalchemy"
Homepage = "<REPLACE ME>"
Repository = "https://github.com/open-telemetry/opentelemetry-python-contrib"
[tool.hatch.version]
# REPLACE ME: the path to the version file e.g

View File

@ -12,4 +12,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
__version__ = "0.49b0.dev"
__version__ = "0.57b0.dev"

View File

@ -1,6 +1,6 @@
pylint==3.0.2
httpretty==1.1.4
mypy==0.931
pyright==v1.1.396
sphinx==7.1.2
sphinx-rtd-theme==2.0.0rc4
sphinx-autodoc-typehints==1.25.2
@ -8,7 +8,6 @@ pytest==7.4.4
pytest-cov==4.1.0
readme-renderer==42.0
bleach==4.1.0 # transient dependency for readme-renderer
protobuf~=3.13
markupsafe>=2.0.1
codespell==2.1.0
requests==2.32.3

View File

@ -2,14 +2,6 @@ sphinx==7.1.2
sphinx-rtd-theme==2.0.0rc4
sphinx-autodoc-typehints==1.25.2
# Need to install the api/sdk in the venv for autodoc. Modifying sys.path
# doesn't work for pkg_resources.
-e "git+https://github.com/open-telemetry/opentelemetry-python.git#egg=opentelemetry-api&subdirectory=opentelemetry-api"
-e "git+https://github.com/open-telemetry/opentelemetry-python.git#egg=opentelemetry-semantic-conventions&subdirectory=opentelemetry-semantic-conventions"
-e "git+https://github.com/open-telemetry/opentelemetry-python.git#egg=opentelemetry-sdk&subdirectory=opentelemetry-sdk"
-e "git+https://github.com/open-telemetry/opentelemetry-python-contrib.git#egg=opentelemetry-util-http&subdirectory=util/opentelemetry-util-http"
./opentelemetry-instrumentation
# Required by opentelemetry-instrumentation
fastapi>=0.65.2
pymemcache~=1.3
@ -23,6 +15,7 @@ aiohttp~=3.0
aiokafka~=0.11.0
aiopg>=0.13.0,<1.3.0
asyncpg>=0.12.0
asyncclick~=8.0
boto~=2.0
botocore~=1.0
boto3~=1.0
@ -33,21 +26,23 @@ elasticsearch>=6.0,<9.0
flask~=2.0
falcon~=2.0
grpcio~=1.27
httpx>=0.18.0
kafka-python>=2.0,<3.0
mysql-connector-python~=8.0
mysqlclient~=2.1.1
openai >= 1.26.0
psutil>=5
psycopg~=3.1.17
pika>=0.12.0
pymongo~=4.6.3
PyMySQL~=1.1.1
pymssql~=2.3.2
pyramid>=1.7
redis>=2.6
remoulade>=0.50
sqlalchemy>=1.0
tornado>=5.1.1
tortoise-orm>=0.17.0
httpx>=0.18.0
# indirect dependency pins
markupsafe==2.0.1

View File

@ -40,6 +40,13 @@ instr_dirs = [
if isdir(join(instr, f))
]
instr_genai = "../instrumentation-genai"
instr_genai_dirs = [
os.path.abspath("/".join(["../instrumentation-genai", f, "src"]))
for f in listdir(instr_genai)
if isdir(join(instr_genai, f))
]
prop = "../propagator"
prop_dirs = [
os.path.abspath("/".join([prop, f, "src"]))
@ -60,7 +67,14 @@ resource_dirs = [
for f in listdir(resource)
if isdir(join(resource, f))
]
sys.path[:0] = exp_dirs + instr_dirs + sdk_ext_dirs + prop_dirs + resource_dirs
sys.path[:0] = (
exp_dirs
+ instr_dirs
+ instr_genai_dirs
+ sdk_ext_dirs
+ prop_dirs
+ resource_dirs
)
# -- Project information -----------------------------------------------------
@ -108,6 +122,7 @@ intersphinx_mapping = {
"https://opentelemetry-python.readthedocs.io/en/latest/",
None,
),
"redis": ("https://redis.readthedocs.io/en/latest/", None),
}
# http://www.sphinx-doc.org/en/master/config.html#confval-nitpicky

View File

@ -50,8 +50,9 @@ install <https://pip.pypa.io/en/stable/reference/pip_install/#editable-installs>
cd opentelemetry-python-contrib
pip install -e ./instrumentation/opentelemetry-instrumentation-flask
pip install -e ./instrumentation/opentelemetry-instrumentation-botocore
pip install -e ./instrumentation-genai/opentelemetry-instrumentation-openai-v2
pip install -e ./sdk-extension/opentelemetry-sdk-extension-aws
pip install -e ./resource/opentelemetry-resource-detector-container
pip install -e ./resource/opentelemetry-resource-detector-containerid
.. toctree::
@ -62,6 +63,14 @@ install <https://pip.pypa.io/en/stable/reference/pip_install/#editable-installs>
instrumentation/**
.. toctree::
:maxdepth: 2
:caption: OpenTelemetry Generative AI Instrumentations
:name: Generative AI Instrumentations
:glob:
instrumentation-genai/**
.. toctree::
:maxdepth: 2
:caption: OpenTelemetry Propagators

View File

@ -0,0 +1,7 @@
OpenTelemetry Python - OpenAI Instrumentation
=============================================
.. automodule:: opentelemetry.instrumentation.openai_v2
:members:
:undoc-members:
:show-inheritance:

View File

@ -0,0 +1,7 @@
.. include:: ../../../instrumentation/opentelemetry-instrumentation-aiohttp-server/README.rst
:end-before: References
.. automodule:: opentelemetry.instrumentation.aiohttp_server
:members:
:undoc-members:
:show-inheritance:

View File

@ -0,0 +1,7 @@
.. include:: ../../../instrumentation/opentelemetry-instrumentation-asyncclick/README.rst
:end-before: References
.. automodule:: opentelemetry.instrumentation.asyncclick
:members:
:undoc-members:
:show-inheritance:

View File

@ -0,0 +1,7 @@
.. include:: ../../../instrumentation/opentelemetry-instrumentation-click/README.rst
:end-before: References
.. automodule:: opentelemetry.instrumentation.click
:members:
:undoc-members:
:show-inheritance:

View File

@ -0,0 +1,7 @@
OpenTelemetry pymssql Instrumentation
=====================================
.. automodule:: opentelemetry.instrumentation.pymssql
:members:
:undoc-members:
:show-inheritance:

View File

@ -1,5 +1,8 @@
OpenTelemetry Redis Instrumentation
===================================
.. include:: ../../../instrumentation/opentelemetry-instrumentation-redis/README.rst
:end-before: References
Usage
-----
.. automodule:: opentelemetry.instrumentation.redis
:members:

View File

@ -24,10 +24,14 @@ py-class=
httpx.Client
httpx.AsyncClient
httpx.BaseTransport
openai.BaseTransport
httpx.AsyncBaseTransport
httpx.SyncByteStream
httpx.AsyncByteStream
httpx.Response
httpx.URL
httpx.Headers
aiohttp.web_request.Request
yarl.URL
cimpl.Producer
cimpl.Consumer
@ -37,6 +41,10 @@ py-class=
callable
Consumer
confluent_kafka.Message
psycopg.Connection
psycopg.AsyncConnection
ObjectProxy
fastapi.applications.FastAPI
any=
; API
@ -64,6 +72,8 @@ any=
py-obj=
opentelemetry.propagators.textmap.CarrierT
opentelemetry.instrumentation.dbapi.ConnectionT
opentelemetry.instrumentation.dbapi.CursorT
py-func=
poll

View File

@ -1,7 +1,7 @@
OpenTelemetry Python - Resource Detector for Containers
=======================================================
.. automodule:: opentelemetry.resource.detector.container
.. automodule:: opentelemetry.resource.detector.containerid
:members:
:undoc-members:
:show-inheritance:

View File

@ -16,7 +16,7 @@ sortfirst=
ext/*
[stable]
version=1.28.0.dev
version=1.36.0.dev
packages=
opentelemetry-sdk
@ -34,7 +34,7 @@ packages=
opentelemetry-api
[prerelease]
version=0.49b0.dev
version=0.57b0.dev
packages=
all
@ -43,13 +43,15 @@ packages=
opentelemetry-instrumentation
opentelemetry-contrib-instrumentations
opentelemetry-distro
opentelemetry-resource-detector-container
opentelemetry-resource-detector-containerid
[exclude_release]
packages=
opentelemetry-resource-detector-azure
opentelemetry-sdk-extension-aws
opentelemetry-propagator-aws-xray
opentelemetry-instrumentation-google-genai
opentelemetry-instrumentation-vertexai
opentelemetry-instrumentation-openai-v2
opentelemetry-instrumentation-test

View File

@ -1,4 +1,4 @@
FROM python:3.8
FROM python:3.9
RUN apt-get update -y && apt-get install libsnappy-dev -y

View File

@ -1,3 +1,3 @@
## Instructions
1. Install protobuf tools. Can use your package manager or download from [GitHub](https://github.com/protocolbuffers/protobuf/releases/tag/v21.7)
1. Install protobuf tools. Can use your package manager or download from [GitHub](https://github.com/protocolbuffers/protobuf/releases/tag/v26.0)
2. Run `generate-proto-py.sh` from inside the `proto/` directory

View File

@ -49,7 +49,7 @@ sed -i 's/import "gogoproto\/gogo.proto";/import "opentelemetry\/exporter\/prome
echo "Removing clones..."
rm -rf protobuf prometheus
# Used libprotoc 3.21.1 & protoc 21.7
# Used libprotoc 26
echo "Compiling proto files to Python"
protoc -I . --python_out=../src ${SRC_DIR}/gogoproto/gogo.proto ${SRC_DIR}/remote.proto ${SRC_DIR}/types.proto

View File

@ -9,7 +9,7 @@ dynamic = ["version"]
description = "Prometheus Remote Write Metrics Exporter for OpenTelemetry"
readme = "README.rst"
license = "Apache-2.0"
requires-python = ">=3.8"
requires-python = ">=3.9"
authors = [
{ name = "OpenTelemetry Authors", email = "cncf-opentelemetry-contributors@lists.cncf.io" },
]
@ -19,14 +19,14 @@ classifiers = [
"License :: OSI Approved :: Apache Software License",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
]
dependencies = [
"protobuf ~= 4.21",
"protobuf ~= 5.26",
"requests ~= 2.28",
"opentelemetry-api ~= 1.12",
"opentelemetry-sdk ~= 1.12",
@ -35,6 +35,7 @@ dependencies = [
[project.urls]
Homepage = "https://github.com/open-telemetry/opentelemetry-python-contrib/tree/main/exporter/opentelemetry-exporter-prometheus-remote-write"
Repository = "https://github.com/open-telemetry/opentelemetry-python-contrib"
[tool.hatch.version]
path = "src/opentelemetry/exporter/prometheus_remote_write/version.py"

View File

@ -1,58 +1,45 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: opentelemetry/exporter/prometheus_remote_write/gen/remote.proto
# Protobuf Python Version: 5.26.0
"""Generated protocol buffer code."""
from google.protobuf.internal import builder as _builder
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
from opentelemetry.exporter.prometheus_remote_write.gen import (
types_pb2 as opentelemetry_dot_exporter_dot_prometheus__remote__write_dot_gen_dot_types__pb2,
)
from opentelemetry.exporter.prometheus_remote_write.gen.gogoproto import (
gogo_pb2 as opentelemetry_dot_exporter_dot_prometheus__remote__write_dot_gen_dot_gogoproto_dot_gogo__pb2,
)
from opentelemetry.exporter.prometheus_remote_write.gen import types_pb2 as opentelemetry_dot_exporter_dot_prometheus__remote__write_dot_gen_dot_types__pb2
from opentelemetry.exporter.prometheus_remote_write.gen.gogoproto import gogo_pb2 as opentelemetry_dot_exporter_dot_prometheus__remote__write_dot_gen_dot_gogoproto_dot_gogo__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(
b'\n?opentelemetry/exporter/prometheus_remote_write/gen/remote.proto\x12\nprometheus\x1a>opentelemetry/exporter/prometheus_remote_write/gen/types.proto\x1aGopentelemetry/exporter/prometheus_remote_write/gen/gogoproto/gogo.proto"z\n\x0cWriteRequest\x12\x30\n\ntimeseries\x18\x01 \x03(\x0b\x32\x16.prometheus.TimeSeriesB\x04\xc8\xde\x1f\x00\x12\x32\n\x08metadata\x18\x03 \x03(\x0b\x32\x1a.prometheus.MetricMetadataB\x04\xc8\xde\x1f\x00J\x04\x08\x02\x10\x03"\xae\x01\n\x0bReadRequest\x12"\n\x07queries\x18\x01 \x03(\x0b\x32\x11.prometheus.Query\x12\x45\n\x17\x61\x63\x63\x65pted_response_types\x18\x02 \x03(\x0e\x32$.prometheus.ReadRequest.ResponseType"4\n\x0cResponseType\x12\x0b\n\x07SAMPLES\x10\x00\x12\x17\n\x13STREAMED_XOR_CHUNKS\x10\x01"8\n\x0cReadResponse\x12(\n\x07results\x18\x01 \x03(\x0b\x32\x17.prometheus.QueryResult"\x8f\x01\n\x05Query\x12\x1a\n\x12start_timestamp_ms\x18\x01 \x01(\x03\x12\x18\n\x10\x65nd_timestamp_ms\x18\x02 \x01(\x03\x12*\n\x08matchers\x18\x03 \x03(\x0b\x32\x18.prometheus.LabelMatcher\x12$\n\x05hints\x18\x04 \x01(\x0b\x32\x15.prometheus.ReadHints"9\n\x0bQueryResult\x12*\n\ntimeseries\x18\x01 \x03(\x0b\x32\x16.prometheus.TimeSeries"]\n\x13\x43hunkedReadResponse\x12\x31\n\x0e\x63hunked_series\x18\x01 \x03(\x0b\x32\x19.prometheus.ChunkedSeries\x12\x13\n\x0bquery_index\x18\x02 \x01(\x03\x42\x08Z\x06prompbb\x06proto3'
)
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n?opentelemetry/exporter/prometheus_remote_write/gen/remote.proto\x12\nprometheus\x1a>opentelemetry/exporter/prometheus_remote_write/gen/types.proto\x1aGopentelemetry/exporter/prometheus_remote_write/gen/gogoproto/gogo.proto\"z\n\x0cWriteRequest\x12\x30\n\ntimeseries\x18\x01 \x03(\x0b\x32\x16.prometheus.TimeSeriesB\x04\xc8\xde\x1f\x00\x12\x32\n\x08metadata\x18\x03 \x03(\x0b\x32\x1a.prometheus.MetricMetadataB\x04\xc8\xde\x1f\x00J\x04\x08\x02\x10\x03\"\xae\x01\n\x0bReadRequest\x12\"\n\x07queries\x18\x01 \x03(\x0b\x32\x11.prometheus.Query\x12\x45\n\x17\x61\x63\x63\x65pted_response_types\x18\x02 \x03(\x0e\x32$.prometheus.ReadRequest.ResponseType\"4\n\x0cResponseType\x12\x0b\n\x07SAMPLES\x10\x00\x12\x17\n\x13STREAMED_XOR_CHUNKS\x10\x01\"8\n\x0cReadResponse\x12(\n\x07results\x18\x01 \x03(\x0b\x32\x17.prometheus.QueryResult\"\x8f\x01\n\x05Query\x12\x1a\n\x12start_timestamp_ms\x18\x01 \x01(\x03\x12\x18\n\x10\x65nd_timestamp_ms\x18\x02 \x01(\x03\x12*\n\x08matchers\x18\x03 \x03(\x0b\x32\x18.prometheus.LabelMatcher\x12$\n\x05hints\x18\x04 \x01(\x0b\x32\x15.prometheus.ReadHints\"9\n\x0bQueryResult\x12*\n\ntimeseries\x18\x01 \x03(\x0b\x32\x16.prometheus.TimeSeries\"]\n\x13\x43hunkedReadResponse\x12\x31\n\x0e\x63hunked_series\x18\x01 \x03(\x0b\x32\x19.prometheus.ChunkedSeries\x12\x13\n\x0bquery_index\x18\x02 \x01(\x03\x42\x08Z\x06prompbb\x06proto3')
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(
DESCRIPTOR,
"opentelemetry.exporter.prometheus_remote_write.gen.remote_pb2",
globals(),
)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b"Z\006prompb"
_WRITEREQUEST.fields_by_name["timeseries"]._options = None
_WRITEREQUEST.fields_by_name["timeseries"]._serialized_options = (
b"\310\336\037\000"
)
_WRITEREQUEST.fields_by_name["metadata"]._options = None
_WRITEREQUEST.fields_by_name["metadata"]._serialized_options = (
b"\310\336\037\000"
)
_WRITEREQUEST._serialized_start = 216
_WRITEREQUEST._serialized_end = 338
_READREQUEST._serialized_start = 341
_READREQUEST._serialized_end = 515
_READREQUEST_RESPONSETYPE._serialized_start = 463
_READREQUEST_RESPONSETYPE._serialized_end = 515
_READRESPONSE._serialized_start = 517
_READRESPONSE._serialized_end = 573
_QUERY._serialized_start = 576
_QUERY._serialized_end = 719
_QUERYRESULT._serialized_start = 721
_QUERYRESULT._serialized_end = 778
_CHUNKEDREADRESPONSE._serialized_start = 780
_CHUNKEDREADRESPONSE._serialized_end = 873
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'opentelemetry.exporter.prometheus_remote_write.gen.remote_pb2', _globals)
if not _descriptor._USE_C_DESCRIPTORS:
_globals['DESCRIPTOR']._loaded_options = None
_globals['DESCRIPTOR']._serialized_options = b'Z\006prompb'
_globals['_WRITEREQUEST'].fields_by_name['timeseries']._loaded_options = None
_globals['_WRITEREQUEST'].fields_by_name['timeseries']._serialized_options = b'\310\336\037\000'
_globals['_WRITEREQUEST'].fields_by_name['metadata']._loaded_options = None
_globals['_WRITEREQUEST'].fields_by_name['metadata']._serialized_options = b'\310\336\037\000'
_globals['_WRITEREQUEST']._serialized_start=216
_globals['_WRITEREQUEST']._serialized_end=338
_globals['_READREQUEST']._serialized_start=341
_globals['_READREQUEST']._serialized_end=515
_globals['_READREQUEST_RESPONSETYPE']._serialized_start=463
_globals['_READREQUEST_RESPONSETYPE']._serialized_end=515
_globals['_READRESPONSE']._serialized_start=517
_globals['_READRESPONSE']._serialized_end=573
_globals['_QUERY']._serialized_start=576
_globals['_QUERY']._serialized_end=719
_globals['_QUERYRESULT']._serialized_start=721
_globals['_QUERYRESULT']._serialized_end=778
_globals['_CHUNKEDREADRESPONSE']._serialized_start=780
_globals['_CHUNKEDREADRESPONSE']._serialized_end=873
# @@protoc_insertion_point(module_scope)

View File

@ -1,85 +1,66 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: opentelemetry/exporter/prometheus_remote_write/gen/types.proto
# Protobuf Python Version: 5.26.0
"""Generated protocol buffer code."""
from google.protobuf.internal import builder as _builder
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
from opentelemetry.exporter.prometheus_remote_write.gen.gogoproto import (
gogo_pb2 as opentelemetry_dot_exporter_dot_prometheus__remote__write_dot_gen_dot_gogoproto_dot_gogo__pb2,
)
from opentelemetry.exporter.prometheus_remote_write.gen.gogoproto import gogo_pb2 as opentelemetry_dot_exporter_dot_prometheus__remote__write_dot_gen_dot_gogoproto_dot_gogo__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(
b'\n>opentelemetry/exporter/prometheus_remote_write/gen/types.proto\x12\nprometheus\x1aGopentelemetry/exporter/prometheus_remote_write/gen/gogoproto/gogo.proto"\xf8\x01\n\x0eMetricMetadata\x12\x33\n\x04type\x18\x01 \x01(\x0e\x32%.prometheus.MetricMetadata.MetricType\x12\x1a\n\x12metric_family_name\x18\x02 \x01(\t\x12\x0c\n\x04help\x18\x04 \x01(\t\x12\x0c\n\x04unit\x18\x05 \x01(\t"y\n\nMetricType\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x0b\n\x07\x43OUNTER\x10\x01\x12\t\n\x05GAUGE\x10\x02\x12\r\n\tHISTOGRAM\x10\x03\x12\x12\n\x0eGAUGEHISTOGRAM\x10\x04\x12\x0b\n\x07SUMMARY\x10\x05\x12\x08\n\x04INFO\x10\x06\x12\x0c\n\x08STATESET\x10\x07"*\n\x06Sample\x12\r\n\x05value\x18\x01 \x01(\x01\x12\x11\n\ttimestamp\x18\x02 \x01(\x03"U\n\x08\x45xemplar\x12\'\n\x06labels\x18\x01 \x03(\x0b\x32\x11.prometheus.LabelB\x04\xc8\xde\x1f\x00\x12\r\n\x05value\x18\x02 \x01(\x01\x12\x11\n\ttimestamp\x18\x03 \x01(\x03"\x8f\x01\n\nTimeSeries\x12\'\n\x06labels\x18\x01 \x03(\x0b\x32\x11.prometheus.LabelB\x04\xc8\xde\x1f\x00\x12)\n\x07samples\x18\x02 \x03(\x0b\x32\x12.prometheus.SampleB\x04\xc8\xde\x1f\x00\x12-\n\texemplars\x18\x03 \x03(\x0b\x32\x14.prometheus.ExemplarB\x04\xc8\xde\x1f\x00"$\n\x05Label\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t"1\n\x06Labels\x12\'\n\x06labels\x18\x01 \x03(\x0b\x32\x11.prometheus.LabelB\x04\xc8\xde\x1f\x00"\x82\x01\n\x0cLabelMatcher\x12+\n\x04type\x18\x01 \x01(\x0e\x32\x1d.prometheus.LabelMatcher.Type\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\r\n\x05value\x18\x03 \x01(\t"(\n\x04Type\x12\x06\n\x02\x45Q\x10\x00\x12\x07\n\x03NEQ\x10\x01\x12\x06\n\x02RE\x10\x02\x12\x07\n\x03NRE\x10\x03"|\n\tReadHints\x12\x0f\n\x07step_ms\x18\x01 \x01(\x03\x12\x0c\n\x04\x66unc\x18\x02 \x01(\t\x12\x10\n\x08start_ms\x18\x03 \x01(\x03\x12\x0e\n\x06\x65nd_ms\x18\x04 \x01(\x03\x12\x10\n\x08grouping\x18\x05 \x03(\t\x12\n\n\x02\x62y\x18\x06 \x01(\x08\x12\x10\n\x08range_ms\x18\x07 \x01(\x03"\x8b\x01\n\x05\x43hunk\x12\x13\n\x0bmin_time_ms\x18\x01 \x01(\x03\x12\x13\n\x0bmax_time_ms\x18\x02 \x01(\x03\x12(\n\x04type\x18\x03 \x01(\x0e\x32\x1a.prometheus.Chunk.Encoding\x12\x0c\n\x04\x64\x61ta\x18\x04 \x01(\x0c" \n\x08\x45ncoding\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x07\n\x03XOR\x10\x01"a\n\rChunkedSeries\x12\'\n\x06labels\x18\x01 \x03(\x0b\x32\x11.prometheus.LabelB\x04\xc8\xde\x1f\x00\x12\'\n\x06\x63hunks\x18\x02 \x03(\x0b\x32\x11.prometheus.ChunkB\x04\xc8\xde\x1f\x00\x42\x08Z\x06prompbb\x06proto3'
)
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n>opentelemetry/exporter/prometheus_remote_write/gen/types.proto\x12\nprometheus\x1aGopentelemetry/exporter/prometheus_remote_write/gen/gogoproto/gogo.proto\"\xf8\x01\n\x0eMetricMetadata\x12\x33\n\x04type\x18\x01 \x01(\x0e\x32%.prometheus.MetricMetadata.MetricType\x12\x1a\n\x12metric_family_name\x18\x02 \x01(\t\x12\x0c\n\x04help\x18\x04 \x01(\t\x12\x0c\n\x04unit\x18\x05 \x01(\t\"y\n\nMetricType\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x0b\n\x07\x43OUNTER\x10\x01\x12\t\n\x05GAUGE\x10\x02\x12\r\n\tHISTOGRAM\x10\x03\x12\x12\n\x0eGAUGEHISTOGRAM\x10\x04\x12\x0b\n\x07SUMMARY\x10\x05\x12\x08\n\x04INFO\x10\x06\x12\x0c\n\x08STATESET\x10\x07\"*\n\x06Sample\x12\r\n\x05value\x18\x01 \x01(\x01\x12\x11\n\ttimestamp\x18\x02 \x01(\x03\"U\n\x08\x45xemplar\x12\'\n\x06labels\x18\x01 \x03(\x0b\x32\x11.prometheus.LabelB\x04\xc8\xde\x1f\x00\x12\r\n\x05value\x18\x02 \x01(\x01\x12\x11\n\ttimestamp\x18\x03 \x01(\x03\"\x8f\x01\n\nTimeSeries\x12\'\n\x06labels\x18\x01 \x03(\x0b\x32\x11.prometheus.LabelB\x04\xc8\xde\x1f\x00\x12)\n\x07samples\x18\x02 \x03(\x0b\x32\x12.prometheus.SampleB\x04\xc8\xde\x1f\x00\x12-\n\texemplars\x18\x03 \x03(\x0b\x32\x14.prometheus.ExemplarB\x04\xc8\xde\x1f\x00\"$\n\x05Label\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t\"1\n\x06Labels\x12\'\n\x06labels\x18\x01 \x03(\x0b\x32\x11.prometheus.LabelB\x04\xc8\xde\x1f\x00\"\x82\x01\n\x0cLabelMatcher\x12+\n\x04type\x18\x01 \x01(\x0e\x32\x1d.prometheus.LabelMatcher.Type\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\r\n\x05value\x18\x03 \x01(\t\"(\n\x04Type\x12\x06\n\x02\x45Q\x10\x00\x12\x07\n\x03NEQ\x10\x01\x12\x06\n\x02RE\x10\x02\x12\x07\n\x03NRE\x10\x03\"|\n\tReadHints\x12\x0f\n\x07step_ms\x18\x01 \x01(\x03\x12\x0c\n\x04\x66unc\x18\x02 \x01(\t\x12\x10\n\x08start_ms\x18\x03 \x01(\x03\x12\x0e\n\x06\x65nd_ms\x18\x04 \x01(\x03\x12\x10\n\x08grouping\x18\x05 \x03(\t\x12\n\n\x02\x62y\x18\x06 \x01(\x08\x12\x10\n\x08range_ms\x18\x07 \x01(\x03\"\x8b\x01\n\x05\x43hunk\x12\x13\n\x0bmin_time_ms\x18\x01 \x01(\x03\x12\x13\n\x0bmax_time_ms\x18\x02 \x01(\x03\x12(\n\x04type\x18\x03 \x01(\x0e\x32\x1a.prometheus.Chunk.Encoding\x12\x0c\n\x04\x64\x61ta\x18\x04 \x01(\x0c\" \n\x08\x45ncoding\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x07\n\x03XOR\x10\x01\"a\n\rChunkedSeries\x12\'\n\x06labels\x18\x01 \x03(\x0b\x32\x11.prometheus.LabelB\x04\xc8\xde\x1f\x00\x12\'\n\x06\x63hunks\x18\x02 \x03(\x0b\x32\x11.prometheus.ChunkB\x04\xc8\xde\x1f\x00\x42\x08Z\x06prompbb\x06proto3')
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(
DESCRIPTOR,
"opentelemetry.exporter.prometheus_remote_write.gen.types_pb2",
globals(),
)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b"Z\006prompb"
_EXEMPLAR.fields_by_name["labels"]._options = None
_EXEMPLAR.fields_by_name["labels"]._serialized_options = (
b"\310\336\037\000"
)
_TIMESERIES.fields_by_name["labels"]._options = None
_TIMESERIES.fields_by_name["labels"]._serialized_options = (
b"\310\336\037\000"
)
_TIMESERIES.fields_by_name["samples"]._options = None
_TIMESERIES.fields_by_name["samples"]._serialized_options = (
b"\310\336\037\000"
)
_TIMESERIES.fields_by_name["exemplars"]._options = None
_TIMESERIES.fields_by_name["exemplars"]._serialized_options = (
b"\310\336\037\000"
)
_LABELS.fields_by_name["labels"]._options = None
_LABELS.fields_by_name["labels"]._serialized_options = b"\310\336\037\000"
_CHUNKEDSERIES.fields_by_name["labels"]._options = None
_CHUNKEDSERIES.fields_by_name["labels"]._serialized_options = (
b"\310\336\037\000"
)
_CHUNKEDSERIES.fields_by_name["chunks"]._options = None
_CHUNKEDSERIES.fields_by_name["chunks"]._serialized_options = (
b"\310\336\037\000"
)
_METRICMETADATA._serialized_start = 152
_METRICMETADATA._serialized_end = 400
_METRICMETADATA_METRICTYPE._serialized_start = 279
_METRICMETADATA_METRICTYPE._serialized_end = 400
_SAMPLE._serialized_start = 402
_SAMPLE._serialized_end = 444
_EXEMPLAR._serialized_start = 446
_EXEMPLAR._serialized_end = 531
_TIMESERIES._serialized_start = 534
_TIMESERIES._serialized_end = 677
_LABEL._serialized_start = 679
_LABEL._serialized_end = 715
_LABELS._serialized_start = 717
_LABELS._serialized_end = 766
_LABELMATCHER._serialized_start = 769
_LABELMATCHER._serialized_end = 899
_LABELMATCHER_TYPE._serialized_start = 859
_LABELMATCHER_TYPE._serialized_end = 899
_READHINTS._serialized_start = 901
_READHINTS._serialized_end = 1025
_CHUNK._serialized_start = 1028
_CHUNK._serialized_end = 1167
_CHUNK_ENCODING._serialized_start = 1135
_CHUNK_ENCODING._serialized_end = 1167
_CHUNKEDSERIES._serialized_start = 1169
_CHUNKEDSERIES._serialized_end = 1266
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'opentelemetry.exporter.prometheus_remote_write.gen.types_pb2', _globals)
if not _descriptor._USE_C_DESCRIPTORS:
_globals['DESCRIPTOR']._loaded_options = None
_globals['DESCRIPTOR']._serialized_options = b'Z\006prompb'
_globals['_EXEMPLAR'].fields_by_name['labels']._loaded_options = None
_globals['_EXEMPLAR'].fields_by_name['labels']._serialized_options = b'\310\336\037\000'
_globals['_TIMESERIES'].fields_by_name['labels']._loaded_options = None
_globals['_TIMESERIES'].fields_by_name['labels']._serialized_options = b'\310\336\037\000'
_globals['_TIMESERIES'].fields_by_name['samples']._loaded_options = None
_globals['_TIMESERIES'].fields_by_name['samples']._serialized_options = b'\310\336\037\000'
_globals['_TIMESERIES'].fields_by_name['exemplars']._loaded_options = None
_globals['_TIMESERIES'].fields_by_name['exemplars']._serialized_options = b'\310\336\037\000'
_globals['_LABELS'].fields_by_name['labels']._loaded_options = None
_globals['_LABELS'].fields_by_name['labels']._serialized_options = b'\310\336\037\000'
_globals['_CHUNKEDSERIES'].fields_by_name['labels']._loaded_options = None
_globals['_CHUNKEDSERIES'].fields_by_name['labels']._serialized_options = b'\310\336\037\000'
_globals['_CHUNKEDSERIES'].fields_by_name['chunks']._loaded_options = None
_globals['_CHUNKEDSERIES'].fields_by_name['chunks']._serialized_options = b'\310\336\037\000'
_globals['_METRICMETADATA']._serialized_start=152
_globals['_METRICMETADATA']._serialized_end=400
_globals['_METRICMETADATA_METRICTYPE']._serialized_start=279
_globals['_METRICMETADATA_METRICTYPE']._serialized_end=400
_globals['_SAMPLE']._serialized_start=402
_globals['_SAMPLE']._serialized_end=444
_globals['_EXEMPLAR']._serialized_start=446
_globals['_EXEMPLAR']._serialized_end=531
_globals['_TIMESERIES']._serialized_start=534
_globals['_TIMESERIES']._serialized_end=677
_globals['_LABEL']._serialized_start=679
_globals['_LABEL']._serialized_end=715
_globals['_LABELS']._serialized_start=717
_globals['_LABELS']._serialized_end=766
_globals['_LABELMATCHER']._serialized_start=769
_globals['_LABELMATCHER']._serialized_end=899
_globals['_LABELMATCHER_TYPE']._serialized_start=859
_globals['_LABELMATCHER_TYPE']._serialized_end=899
_globals['_READHINTS']._serialized_start=901
_globals['_READHINTS']._serialized_end=1025
_globals['_CHUNK']._serialized_start=1028
_globals['_CHUNK']._serialized_end=1167
_globals['_CHUNK_ENCODING']._serialized_start=1135
_globals['_CHUNK_ENCODING']._serialized_end=1167
_globals['_CHUNKEDSERIES']._serialized_start=1169
_globals['_CHUNKEDSERIES']._serialized_end=1266
# @@protoc_insertion_point(module_scope)

View File

@ -12,4 +12,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
__version__ = "0.49b0.dev"
__version__ = "0.57b0.dev"

View File

@ -1,15 +1,13 @@
asgiref==3.8.1
certifi==2024.7.4
charset-normalizer==3.3.2
# We can drop this after bumping baseline to pypy-39
cramjam==2.1.0; platform_python_implementation == "PyPy"
cramjam==2.8.1; platform_python_implementation != "PyPy"
cramjam==2.8.4
Deprecated==1.2.14
idna==3.7
iniconfig==2.0.0
packaging==24.0
pluggy==1.5.0
protobuf==4.25.3
protobuf==5.26
py-cpuinfo==9.0.0
pytest==7.4.4
python-snappy==0.7.1

View File

@ -8,7 +8,7 @@ dynamic = ["version"]
description = "Rich Console Exporter for OpenTelemetry"
readme = "README.rst"
license = "Apache-2.0"
requires-python = ">=3.8"
requires-python = ">=3.9"
authors = [
{ name = "OpenTelemetry Authors", email = "cncf-opentelemetry-contributors@lists.cncf.io" },
]
@ -18,21 +18,22 @@ classifiers = [
"License :: OSI Approved :: Apache Software License",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
]
dependencies = [
"opentelemetry-api ~= 1.12",
"opentelemetry-sdk ~= 1.12",
"opentelemetry-semantic-conventions == 0.49b0.dev",
"opentelemetry-semantic-conventions == 0.57b0.dev",
"rich>=10.0.0",
]
[project.urls]
Homepage = "https://github.com/open-telemetry/opentelemetry-python-contrib/tree/main/exporter/opentelemetry-exporter-richconsole"
Repository = "https://github.com/open-telemetry/opentelemetry-python-contrib"
[tool.hatch.version]
path = "src/opentelemetry/exporter/richconsole/version.py"

View File

@ -64,11 +64,15 @@ from rich.tree import Tree
import opentelemetry.trace
from opentelemetry.sdk.trace import ReadableSpan
from opentelemetry.sdk.trace.export import SpanExporter, SpanExportResult
from opentelemetry.semconv.trace import SpanAttributes
from opentelemetry.semconv._incubating.attributes.db_attributes import (
DB_STATEMENT,
)
def _ns_to_time(nanoseconds):
ts = datetime.datetime.utcfromtimestamp(nanoseconds / 1e9)
ts = datetime.datetime.fromtimestamp(
nanoseconds / 1e9, datetime.timezone.utc
)
return ts.strftime("%H:%M:%S.%f")
@ -118,7 +122,7 @@ def _child_add_optional_attributes(child: Tree, span: ReadableSpan):
label=Text.from_markup("[bold cyan]Attributes :[/bold cyan] ")
)
for attribute in span.attributes:
if attribute == SpanAttributes.DB_STATEMENT:
if attribute == DB_STATEMENT:
attributes.add(
Text.from_markup(f"[bold cyan]{attribute} :[/bold cyan] ")
)

View File

@ -12,4 +12,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
__version__ = "0.49b0.dev"
__version__ = "0.57b0.dev"

View File

@ -1,6 +1,6 @@
-c dev-requirements.txt
astor==0.8.1
jinja2==3.1.4
jinja2==3.1.6
markupsafe==2.0.1
ruff==0.6.9
requests

View File

@ -0,0 +1,6 @@
| Instrumentation | Supported Packages | Metrics support | Semconv status |
| --------------- | ------------------ | --------------- | -------------- |
| [opentelemetry-instrumentation-google-genai](./opentelemetry-instrumentation-google-genai) | google-genai >= 1.0.0 | No | development
| [opentelemetry-instrumentation-openai-v2](./opentelemetry-instrumentation-openai-v2) | openai >= 1.26.0 | Yes | development
| [opentelemetry-instrumentation-vertexai](./opentelemetry-instrumentation-vertexai) | google-cloud-aiplatform >= 1.64 | No | development

View File

@ -0,0 +1,4 @@
.build
.test
dist

View File

@ -0,0 +1,28 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Unreleased
## Version 0.3b0 (2025-07-08)
- Add automatic instrumentation to tool call functions ([#3446](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3446))
## Version 0.2b0 (2025-04-28)
- Add more request configuration options to the span attributes ([#3374](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3374))
- Restructure tests to keep in line with repository conventions ([#3344](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3344))
- Fix [bug](https://github.com/open-telemetry/opentelemetry-python-contrib/issues/3416) where
span attribute `gen_ai.response.finish_reasons` is empty ([#3417](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3417))
## Version 0.1b0 (2025-03-05)
- Add support for async and streaming.
([#3298](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3298))
Create an initial version of Open Telemetry instrumentation for github.com/googleapis/python-genai.
([#3256](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3256))

View File

@ -0,0 +1,203 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -0,0 +1,92 @@
OpenTelemetry Google GenAI SDK Instrumentation
==============================================
|pypi|
.. |pypi| image:: https://badge.fury.io/py/opentelemetry-instrumentation-google-genai.svg
:target: https://pypi.org/project/opentelemetry-instrumentation-google-genai/
This library adds instrumentation to the `Google GenAI SDK library <https://pypi.org/project/google-genai/>`_
to emit telemetry data following `Semantic Conventions for GenAI systems <https://opentelemetry.io/docs/specs/semconv/gen-ai/>`_.
It adds trace spans for GenAI operations, events/logs for recording prompts/responses, and emits metrics that describe the
GenAI operations in aggregate.
Experimental
------------
This package is still experimental. The instrumentation may not be complete or correct just yet.
Please see "TODOS.md" for a list of known defects/TODOs that are blockers to package stability.
Installation
------------
If your application is already instrumented with OpenTelemetry, add this
package to your requirements.
::
pip install opentelemetry-instrumentation-google-genai
If you don't have a Google GenAI SDK application, yet, try our `examples <examples>`_.
Check out `zero-code example <examples/zero-code>`_ for a quick start.
Usage
-----
This section describes how to set up Google GenAI SDK instrumentation if you're setting OpenTelemetry up manually.
Check out the `manual example <examples/manual>`_ for more details.
Instrumenting all clients
*************************
When using the instrumentor, all clients will automatically trace GenAI `generate_content` operations.
You can also optionally capture prompts and responses as log events.
Make sure to configure OpenTelemetry tracing, logging, metrics, and events to capture all telemetry emitted by the instrumentation.
.. code-block:: python
from opentelemetry.instrumentation.google_genai import GoogleGenAiSdkInstrumentor
from google.genai import Client
GoogleGenAiSdkInstrumentor().instrument()
client = Client()
response = client.models.generate_content(
model="gemini-1.5-flash-002",
contents="Write a short poem on OpenTelemetry.")
Enabling message content
*************************
Message content such as the contents of the prompt and response
are not captured by default. To capture message content as log events, set the environment variable
`OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT` to `true`.
Uninstrument
************
To uninstrument clients, call the uninstrument method:
.. code-block:: python
from opentelemetry.instrumentation.google_genai import GoogleGenAiSdkInstrumentor
GoogleGenAiSdkInstrumentor().instrument()
# ...
# Uninstrument all clients
GoogleGenAiSdkInstrumentor().uninstrument()
References
----------
* `Google Gen AI SDK Documentation <https://ai.google.dev/gemini-api/docs/sdks>`_
* `Google Gen AI SDK on GitHub <https://github.com/googleapis/python-genai>`_
* `Using Vertex AI with Google Gen AI SDK <https://cloud.google.com/vertex-ai/generative-ai/docs/sdks/overview>`_
* `OpenTelemetry Project <https://opentelemetry.io/>`_
* `OpenTelemetry Python Examples <https://github.com/open-telemetry/opentelemetry-python/tree/main/docs/examples>`_

View File

@ -0,0 +1,19 @@
# TODOs
## Fundamentals
Here are some TODO items required to achieve stability for this package:
- Add more span-level attributes for response information
- Verify and correct formatting of events:
- Including the 'role' field for message events
- Including tool invocation information
- Emit events for safety ratings when they block responses
- Additional cleanup/improvement tasks such as:
- Adoption of 'wrapt' instead of 'functools.wraps'
- Bolstering test coverage
## Future
Beyond the above TODOs, it would also be desirable to extend the
instrumentation beyond `generate_content` to other API surfaces.

View File

@ -0,0 +1,28 @@
# Copyright The OpenTelemetry Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Uncomment and change to your OTLP endpoint
# OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
# OTEL_EXPORTER_OTLP_PROTOCOL=grpc
# Uncomment to change parameters used to configure 'google.genai'
# GOOGLE_GENAI_USE_VERTEXAI=1
# GOOGLE_API_KEY=<your api key>
# GOOGLE_CLOUD_PROJECT=<your cloud project>
# GOOGLE_CLOUD_LOCATION=<your cloud location>
OTEL_SERVICE_NAME=opentelemetry-python-google-genai
# Change to 'false' to hide prompt and completion content
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=true

View File

@ -0,0 +1,44 @@
OpenTelemetry Google GenAI SDK Manual Instrumentation Example
============================================
This is an example of how to instrument Google GenAI SDK calls when configuring
OpenTelemetry SDK and Instrumentations manually.
When `main.py <main.py>`_ is run, it exports traces, logs, and metrics to an OTLP
compatible endpoint. Traces include details such as the model used and the
duration of the chat request. Logs capture the chat request and the generated
response, providing a comprehensive view of the performance and behavior of
your GenAI SDK requests. Metrics include aggregate statistics such as the aggregate
token usage as well as the latency distribution of the GenAI operations.
Note: `.env <.env>`_ file configures additional environment variables:
- `OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=true`
... configures Google GenAI SDK instrumentation to capture prompt/response content.
Setup
-----
An OTLP compatible endpoint should be listening for traces, logs, and metrics on
http://localhost:4317. If not, update "OTEL_EXPORTER_OTLP_ENDPOINT" as well.
Next, set up a virtual environment like this:
::
python3 -m venv .venv
source .venv/bin/activate
pip install "python-dotenv[cli]"
pip install -r requirements.txt
Run
---
Run the example like this:
::
export PROMPT="Your prompt here"
dotenv run -- python main.py

View File

@ -0,0 +1,101 @@
# Copyright The OpenTelemetry Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# We skip linting this file with pylint, because the linter is not
# configured with the "requirements.txt" dependencies and therefore
# will give multiple "no-name-in-module" errors for the imports.
#
# pylint: skip-file
import os
import google.genai
# NOTE: OpenTelemetry Python Logs and Events APIs are in beta
from opentelemetry import _events as otel_events
from opentelemetry import _logs as otel_logs
from opentelemetry import metrics as otel_metrics
from opentelemetry import trace as otel_trace
from opentelemetry.exporter.otlp.proto.grpc._log_exporter import (
OTLPLogExporter,
)
from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import (
OTLPMetricExporter,
)
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import (
OTLPSpanExporter,
)
from opentelemetry.instrumentation.google_genai import (
GoogleGenAiSdkInstrumentor,
)
from opentelemetry.instrumentation.requests import RequestsInstrumentor
from opentelemetry.sdk._events import EventLoggerProvider
from opentelemetry.sdk._logs import LoggerProvider
from opentelemetry.sdk._logs.export import BatchLogRecordProcessor
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
def setup_otel_tracing():
otel_trace.set_tracer_provider(TracerProvider())
otel_trace.get_tracer_provider().add_span_processor(
BatchSpanProcessor(OTLPSpanExporter())
)
def setup_otel_logs_and_events():
otel_logs.set_logger_provider(LoggerProvider())
otel_logs.get_logger_provider().add_log_record_processor(
BatchLogRecordProcessor(OTLPLogExporter())
)
otel_events.set_event_logger_provider(EventLoggerProvider())
def setup_otel_metrics():
meter_provider = MeterProvider(
metric_readers=[
PeriodicExportingMetricReader(
OTLPMetricExporter(),
),
]
)
otel_metrics.set_meter_provider(meter_provider)
def setup_opentelemetry():
setup_otel_tracing()
setup_otel_logs_and_events()
setup_otel_metrics()
def instrument_google_genai():
GoogleGenAiSdkInstrumentor().instrument()
RequestsInstrumentor().instrument()
def main():
setup_opentelemetry()
instrument_google_genai()
client = google.genai.Client()
response = client.models.generate_content(
model=os.getenv("MODEL", "gemini-2.0-flash-001"),
contents=os.getenv("PROMPT", "Why is the sky blue?"),
)
print(response.text)
if __name__ == "__main__":
main()

View File

@ -0,0 +1,20 @@
# Copyright The OpenTelemetry Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
google-genai ~= 1.0.0
opentelemetry-api ~= 1.30.0
opentelemetry-sdk ~= 1.30.0
opentelemetry-exporter-otlp-proto-grpc ~= 1.30.0
opentelemetry-instrumentation-requests ~= 0.51b0
opentelemetry-instrumentation-google-genai ~= 0.0.1.dev

View File

@ -0,0 +1,30 @@
# Copyright The OpenTelemetry Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Update to change exporter configuration as desired.
# See: https://opentelemetry.io/docs/zero-code/python/configuration/
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
OTEL_EXPORTER_OTLP_PROTOCOL=grpc
# Uncomment to change parameters used to configure 'google.genai'
# GOOGLE_GENAI_USE_VERTEXAI=1
# GOOGLE_API_KEY=<your api key>
# GOOGLE_CLOUD_PROJECT=<your cloud project>
# GOOGLE_CLOUD_LOCATION=<your cloud location>
OTEL_SERVICE_NAME=opentelemetry-python-google-genai
# Change to 'false' to hide prompt and completion content
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=true

View File

@ -0,0 +1,46 @@
OpenTelemetry Google GenAI SDK Manual Instrumentation Example
============================================
This is an example of how to instrument Google GenAI SDK calls with zero code changes,
using `opentelemetryh-instrument`.
When `main.py <main.py>`_ is run, it exports traces, logs, and metrics to an OTLP
compatible endpoint. Traces include details such as the model used and the
duration of the chat request. Logs capture the chat request and the generated
response, providing a comprehensive view of the performance and behavior of
your GenAI SDK requests. Metrics include aggregate statistics such as the aggregate
token usage as well as the latency distribution of the GenAI operations.
Note: `.env <.env>`_ file configures additional environment variables:
- `OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=true`
... configures Google GenAI SDK instrumentation to capture prompt/response content.
Setup
-----
An OTLP compatible endpoint should be listening for traces, logs, and metrics on
http://localhost:4317. If not, update "OTEL_EXPORTER_OTLP_ENDPOINT" as well.
Next, set up a virtual environment like this:
::
python3 -m venv .venv
source .venv/bin/activate
pip install "python-dotenv[cli]"
pip install -r requirements.txt
opentelemetry-bootstrap -a install
Run
---
Run the example like this:
::
export PROMPT="Your prompt here"
dotenv run -- opentelemetry-instrument python main.py

View File

@ -0,0 +1,30 @@
# Copyright The OpenTelemetry Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import google.genai
def main():
client = google.genai.Client()
response = client.models.generate_content(
model=os.getenv("MODEL", "gemini-2.0-flash-001"),
contents=os.getenv("PROMPT", "Why is the sky blue?"),
)
print(response.text)
if __name__ == "__main__":
main()

View File

@ -0,0 +1,23 @@
# Copyright The OpenTelemetry Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
google-genai ~= 1.0.0
opentelemetry-api ~= 1.30.0
opentelemetry-sdk ~= 1.30.0
opentelemetry-exporter-otlp-proto-grpc ~= 1.30.0
opentelemetry-instrumentation ~= 0.51b0
opentelemetry-instrumentation-requests ~= 0.51b0
opentelemetry-instrumentation-google-genai ~= 0.0.1.dev
opentelemetry-contrib-instrumentations ~= 0.51b0
opentelemetry-distro[otlp] ~= 0.51b0

View File

@ -0,0 +1,79 @@
# Copyright The OpenTelemetry Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "opentelemetry-instrumentation-google-genai"
dynamic = ["version"]
description = "OpenTelemetry"
readme = "README.rst"
license = "Apache-2.0"
requires-python = ">=3.9"
authors = [
{ name = "OpenTelemetry Authors", email = "cncf-opentelemetry-contributors@lists.cncf.io" },
]
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"License :: OSI Approved :: Apache Software License",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12"
]
dependencies = [
"opentelemetry-api >=1.31.1, <2",
"opentelemetry-instrumentation >=0.52b1, <2",
"opentelemetry-semantic-conventions >=0.52b1, <2"
]
[project.optional-dependencies]
instruments = [
"google-genai >= 1.0.0"
]
[project.entry-points.opentelemetry_instrumentor]
google-genai = "opentelemetry.instrumentation.google_genai:GoogleGenAiSdkInstrumentor"
[project.urls]
Homepage = "https://github.com/open-telemetry/opentelemetry-python-contrib/tree/main/instrumentation-genai/opentelemetry-instrumentation-google-genai"
Repository = "https://github.com/open-telemetry/opentelemetry-python-contrib"
[tool.hatch.version]
path = "src/opentelemetry/instrumentation/google_genai/version.py"
[tool.hatch.build.targets.sdist]
include = [
"/src",
"/tests",
]
[tool.hatch.build.targets.wheel]
packages = ["src/opentelemetry"]
[tool.pyright]
include = [
"src",
]
exclude = [
"**/__pycache__",
]
stubPath = "types"
reportMissingImports = "error"
reportMissingTypeStubs = false
pythonVersion = "3.9"

View File

@ -0,0 +1,47 @@
# Copyright The OpenTelemetry Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Google Gen AI SDK client instrumentation supporting the `google-genai` package.
It can be enabled using ``GoogleGenAiSdkInstrumentor``.
.. _google-genai: https://pypi.org/project/google-genai/
Usage
-----
.. code:: python
import os
import google.genai
from opentelemetry.instrumentation.google_genai import GoogleGenAiSdkInstrumentor
GoogleGenAiSdkInstrumentor().instrument()
model = os.getenv('MODEL', 'gemini-2.0-flash-001')
client = google.genai.Client()
response = client.models.generate_content(
model=model,
contents='why is the sky blue?'
)
print(response.text)
API
---
"""
from .instrumentor import GoogleGenAiSdkInstrumentor
from .version import __version__
__all__ = ["GoogleGenAiSdkInstrumentor", "__version__"]

View File

@ -0,0 +1,97 @@
# Copyright The OpenTelemetry Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import re
from typing import Iterable, Optional, Set
ALLOWED = True
DENIED = False
def _parse_env_list(s: str) -> Set[str]:
result = set()
for entry in s.split(","):
stripped_entry = entry.strip()
if not stripped_entry:
continue
result.add(stripped_entry)
return result
class _CompoundMatcher:
def __init__(self, entries: Set[str]):
self._match_all = "*" in entries
self._entries = entries
self._regex_matcher = None
regex_entries = []
for entry in entries:
if "*" not in entry:
continue
if entry == "*":
continue
entry = entry.replace("[", "\\[")
entry = entry.replace("]", "\\]")
entry = entry.replace(".", "\\.")
entry = entry.replace("*", ".*")
regex_entries.append(f"({entry})")
if regex_entries:
joined_regex = "|".join(regex_entries)
regex_str = f"^({joined_regex})$"
self._regex_matcher = re.compile(regex_str)
@property
def match_all(self):
return self._match_all
def matches(self, x):
if self._match_all:
return True
if x in self._entries:
return True
if (self._regex_matcher is not None) and (
self._regex_matcher.fullmatch(x)
):
return True
return False
class AllowList:
def __init__(
self,
includes: Optional[Iterable[str]] = None,
excludes: Optional[Iterable[str]] = None,
):
self._includes = _CompoundMatcher(set(includes or []))
self._excludes = _CompoundMatcher(set(excludes or []))
assert (not self._includes.match_all) or (
not self._excludes.match_all
), "Can't have '*' in both includes and excludes."
def allowed(self, x: str):
if self._excludes.match_all:
return self._includes.matches(x)
if self._includes.match_all:
return not self._excludes.matches(x)
return self._includes.matches(x) and not self._excludes.matches(x)
@staticmethod
def from_env(
includes_env_var: str, excludes_env_var: Optional[str] = None
):
includes = _parse_env_list(os.getenv(includes_env_var) or "")
excludes = set()
if excludes_env_var:
excludes = _parse_env_list(os.getenv(excludes_env_var) or "")
return AllowList(includes=includes, excludes=excludes)

View File

@ -0,0 +1,18 @@
# Copyright The OpenTelemetry Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Semantic Convention still being defined in:
# https://github.com/open-telemetry/semantic-conventions/pull/2125
GCP_GENAI_OPERATION_CONFIG = "gcp.gen_ai.operation.config"

View File

@ -0,0 +1,301 @@
# Copyright The OpenTelemetry Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import json
import logging
from typing import (
Any,
Dict,
Optional,
Protocol,
Sequence,
Set,
Tuple,
Union,
)
Primitive = Union[bool, str, int, float]
BoolList = list[bool]
StringList = list[str]
IntList = list[int]
FloatList = list[float]
HomogenousPrimitiveList = Union[BoolList, StringList, IntList, FloatList]
FlattenedValue = Union[Primitive, HomogenousPrimitiveList]
FlattenedDict = Dict[str, FlattenedValue]
class FlattenFunc(Protocol):
def __call__(
self,
key: str,
value: Any,
exclude_keys: Set[str],
rename_keys: Dict[str, str],
flatten_functions: Dict[str, "FlattenFunc"],
**kwargs: Any,
) -> Any:
return None
_logger = logging.getLogger(__name__)
def _concat_key(prefix: Optional[str], suffix: str):
if not prefix:
return suffix
return f"{prefix}.{suffix}"
def _is_primitive(v):
for t in [str, bool, int, float]:
if isinstance(v, t):
return True
return False
def _is_homogenous_primitive_list(v):
if not isinstance(v, list):
return False
if len(v) == 0:
return True
if not _is_primitive(v[0]):
return False
first_entry_value_type = type(v[0])
for entry in v[1:]:
if not isinstance(entry, first_entry_value_type):
return False
return True
def _get_flatten_func(
flatten_functions: Dict[str, FlattenFunc], key_names: set[str]
) -> Optional[FlattenFunc]:
for key in key_names:
flatten_func = flatten_functions.get(key)
if flatten_func is not None:
return flatten_func
return None
def _flatten_with_flatten_func(
key: str,
value: Any,
exclude_keys: Set[str],
rename_keys: Dict[str, str],
flatten_functions: Dict[str, FlattenFunc],
key_names: Set[str],
) -> Tuple[bool, Any]:
flatten_func = _get_flatten_func(flatten_functions, key_names)
if flatten_func is None:
return False, value
func_output = flatten_func(
key,
value,
exclude_keys=exclude_keys,
rename_keys=rename_keys,
flatten_functions=flatten_functions,
)
if func_output is None:
return True, {}
if _is_primitive(func_output) or _is_homogenous_primitive_list(
func_output
):
return True, {key: func_output}
return False, func_output
def _flatten_compound_value_using_json(
key: str,
value: Any,
exclude_keys: Set[str],
rename_keys: Dict[str, str],
flatten_functions: Dict[str, FlattenFunc],
_from_json=False,
) -> FlattenedDict:
if _from_json:
_logger.debug(
"Cannot flatten value with key %s; value: %s", key, value
)
return {}
try:
json_string = json.dumps(value)
except TypeError:
_logger.debug(
"Cannot flatten value with key %s; value: %s. Not JSON serializable.",
key,
value,
)
return {}
json_value = json.loads(json_string)
return _flatten_value(
key,
json_value,
exclude_keys=exclude_keys,
rename_keys=rename_keys,
flatten_functions=flatten_functions,
# Ensure that we don't recurse indefinitely if "json.loads()" somehow returns
# a complex, compound object that does not get handled by the "primitive", "list",
# or "dict" cases. Prevents falling back on the JSON serialization fallback path.
_from_json=True,
)
def _flatten_compound_value(
key: str,
value: Any,
exclude_keys: Set[str],
rename_keys: Dict[str, str],
flatten_functions: Dict[str, FlattenFunc],
key_names: Set[str],
_from_json=False,
) -> FlattenedDict:
fully_flattened_with_flatten_func, value = _flatten_with_flatten_func(
key=key,
value=value,
exclude_keys=exclude_keys,
rename_keys=rename_keys,
flatten_functions=flatten_functions,
key_names=key_names,
)
if fully_flattened_with_flatten_func:
return value
if isinstance(value, dict):
return _flatten_dict(
value,
key_prefix=key,
exclude_keys=exclude_keys,
rename_keys=rename_keys,
flatten_functions=flatten_functions,
)
if isinstance(value, list):
if _is_homogenous_primitive_list(value):
return {key: value}
return _flatten_list(
value,
key_prefix=key,
exclude_keys=exclude_keys,
rename_keys=rename_keys,
flatten_functions=flatten_functions,
)
if hasattr(value, "model_dump"):
return _flatten_dict(
value.model_dump(),
key_prefix=key,
exclude_keys=exclude_keys,
rename_keys=rename_keys,
flatten_functions=flatten_functions,
)
return _flatten_compound_value_using_json(
key,
value,
exclude_keys=exclude_keys,
rename_keys=rename_keys,
flatten_functions=flatten_functions,
_from_json=_from_json,
)
def _flatten_value(
key: str,
value: Any,
exclude_keys: Set[str],
rename_keys: Dict[str, str],
flatten_functions: Dict[str, FlattenFunc],
_from_json=False,
) -> FlattenedDict:
if value is None:
return {}
key_names = set([key])
renamed_key = rename_keys.get(key)
if renamed_key is not None:
key_names.add(renamed_key)
key = renamed_key
if key_names & exclude_keys:
return {}
if _is_primitive(value):
return {key: value}
return _flatten_compound_value(
key=key,
value=value,
exclude_keys=exclude_keys,
rename_keys=rename_keys,
flatten_functions=flatten_functions,
key_names=key_names,
_from_json=_from_json,
)
def _flatten_dict(
d: Dict[str, Any],
key_prefix: str,
exclude_keys: Set[str],
rename_keys: Dict[str, str],
flatten_functions: Dict[str, FlattenFunc],
) -> FlattenedDict:
result = {}
for key, value in d.items():
if key in exclude_keys:
continue
full_key = _concat_key(key_prefix, key)
flattened = _flatten_value(
full_key,
value,
exclude_keys=exclude_keys,
rename_keys=rename_keys,
flatten_functions=flatten_functions,
)
result.update(flattened)
return result
def _flatten_list(
lst: list[Any],
key_prefix: str,
exclude_keys: Set[str],
rename_keys: Dict[str, str],
flatten_functions: Dict[str, FlattenFunc],
) -> FlattenedDict:
result = {}
result[_concat_key(key_prefix, "length")] = len(lst)
for index, value in enumerate(lst):
full_key = f"{key_prefix}[{index}]"
flattened = _flatten_value(
full_key,
value,
exclude_keys=exclude_keys,
rename_keys=rename_keys,
flatten_functions=flatten_functions,
)
result.update(flattened)
return result
def flatten_dict(
d: Dict[str, Any],
key_prefix: Optional[str] = None,
exclude_keys: Optional[Sequence[str]] = None,
rename_keys: Optional[Dict[str, str]] = None,
flatten_functions: Optional[Dict[str, FlattenFunc]] = None,
):
key_prefix = key_prefix or ""
exclude_keys = set(exclude_keys or [])
rename_keys = rename_keys or {}
flatten_functions = flatten_functions or {}
return _flatten_dict(
d,
key_prefix=key_prefix,
exclude_keys=exclude_keys,
rename_keys=rename_keys,
flatten_functions=flatten_functions,
)

View File

@ -0,0 +1,23 @@
# Copyright The OpenTelemetry Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
_CONTENT_RECORDING_ENV_VAR = (
"OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT"
)
def is_content_recording_enabled():
return os.getenv(_CONTENT_RECORDING_ENV_VAR, "false").lower() == "true"

View File

@ -0,0 +1,790 @@
# Copyright The OpenTelemetry Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import copy
import functools
import json
import logging
import os
import time
from typing import Any, AsyncIterator, Awaitable, Iterator, Optional, Union
from google.genai.models import AsyncModels, Models
from google.genai.types import (
BlockedReason,
Candidate,
Content,
ContentListUnion,
ContentListUnionDict,
ContentUnion,
ContentUnionDict,
GenerateContentConfig,
GenerateContentConfigOrDict,
GenerateContentResponse,
)
from opentelemetry import trace
from opentelemetry.semconv._incubating.attributes import (
code_attributes,
gen_ai_attributes,
)
from opentelemetry.semconv.attributes import error_attributes
from .allowlist_util import AllowList
from .custom_semconv import GCP_GENAI_OPERATION_CONFIG
from .dict_util import flatten_dict
from .flags import is_content_recording_enabled
from .otel_wrapper import OTelWrapper
from .tool_call_wrapper import wrapped as wrapped_tool
_logger = logging.getLogger(__name__)
# Constant used to make the absence of content more understandable.
_CONTENT_ELIDED = "<elided>"
# Constant used for the value of 'gen_ai.operation.name".
_GENERATE_CONTENT_OP_NAME = "generate_content"
class _MethodsSnapshot:
def __init__(self):
self._original_generate_content = Models.generate_content
self._original_generate_content_stream = Models.generate_content_stream
self._original_async_generate_content = AsyncModels.generate_content
self._original_async_generate_content_stream = (
AsyncModels.generate_content_stream
)
@property
def generate_content(self):
return self._original_generate_content
@property
def generate_content_stream(self):
return self._original_generate_content_stream
@property
def async_generate_content(self):
return self._original_async_generate_content
@property
def async_generate_content_stream(self):
return self._original_async_generate_content_stream
def restore(self):
Models.generate_content = self._original_generate_content
Models.generate_content_stream = self._original_generate_content_stream
AsyncModels.generate_content = self._original_async_generate_content
AsyncModels.generate_content_stream = (
self._original_async_generate_content_stream
)
def _get_vertexai_system_name():
return gen_ai_attributes.GenAiSystemValues.VERTEX_AI.name.lower()
def _get_gemini_system_name():
return gen_ai_attributes.GenAiSystemValues.GEMINI.name.lower()
def _guess_genai_system_from_env():
if os.environ.get("GOOGLE_GENAI_USE_VERTEXAI", "0").lower() in [
"true",
"1",
]:
return _get_vertexai_system_name()
return _get_gemini_system_name()
def _get_is_vertexai(models_object: Union[Models, AsyncModels]):
# Since commit 8e561de04965bb8766db87ad8eea7c57c1040442 of "googleapis/python-genai",
# it is possible to obtain the information using a documented property.
if hasattr(models_object, "vertexai"):
vertexai_attr = getattr(models_object, "vertexai")
if vertexai_attr is not None:
return vertexai_attr
# For earlier revisions, it is necessary to deeply inspect the internals.
if hasattr(models_object, "_api_client"):
client = getattr(models_object, "_api_client")
if not client:
return None
if hasattr(client, "vertexai"):
return getattr(client, "vertexai")
return None
def _determine_genai_system(models_object: Union[Models, AsyncModels]):
vertexai_attr = _get_is_vertexai(models_object)
if vertexai_attr is None:
return _guess_genai_system_from_env()
if vertexai_attr:
return _get_vertexai_system_name()
return _get_gemini_system_name()
def _to_dict(value: object):
if isinstance(value, dict):
return value
if hasattr(value, "model_dump"):
return value.model_dump()
return json.loads(json.dumps(value))
def _add_request_options_to_span(
span, config: Optional[GenerateContentConfigOrDict], allow_list: AllowList
):
if config is None:
return
span_context = span.get_span_context()
if not span_context.trace_flags.sampled:
# Avoid potentially costly traversal of config
# options if the span will be dropped, anyway.
return
# Automatically derive attributes from the contents of the
# config object. This ensures that all relevant parameters
# are captured in the telemetry data (except for those
# that are excluded via "exclude_keys"). Dynamic attributes (those
# starting with "gcp.gen_ai." instead of simply "gen_ai.request.")
# are filtered with the "allow_list" before inclusion in the span.
attributes = flatten_dict(
_to_dict(config),
# A custom prefix is used, because the names/structure of the
# configuration is likely to be specific to Google Gen AI SDK.
key_prefix=GCP_GENAI_OPERATION_CONFIG,
exclude_keys=[
# System instruction can be overly long for a span attribute.
# Additionally, it is recorded as an event (log), instead.
"gcp.gen_ai.operation.config.system_instruction",
],
# Although a custom prefix is used by default, some of the attributes
# are captured in common, standard, Semantic Conventions. For the
# well-known properties whose values align with Semantic Conventions,
# we ensure that the key name matches the standard SemConv name.
rename_keys={
# TODO: add more entries here as more semantic conventions are
# generalized to cover more of the available config options.
"gcp.gen_ai.operation.config.temperature": gen_ai_attributes.GEN_AI_REQUEST_TEMPERATURE,
"gcp.gen_ai.operation.config.top_k": gen_ai_attributes.GEN_AI_REQUEST_TOP_K,
"gcp.gen_ai.operation.config.top_p": gen_ai_attributes.GEN_AI_REQUEST_TOP_P,
"gcp.gen_ai.operation.config.candidate_count": gen_ai_attributes.GEN_AI_REQUEST_CHOICE_COUNT,
"gcp.gen_ai.operation.config.max_output_tokens": gen_ai_attributes.GEN_AI_REQUEST_MAX_TOKENS,
"gcp.gen_ai.operation.config.stop_sequences": gen_ai_attributes.GEN_AI_REQUEST_STOP_SEQUENCES,
"gcp.gen_ai.operation.config.frequency_penalty": gen_ai_attributes.GEN_AI_REQUEST_FREQUENCY_PENALTY,
"gcp.gen_ai.operation.config.presence_penalty": gen_ai_attributes.GEN_AI_REQUEST_PRESENCE_PENALTY,
"gcp.gen_ai.operation.config.seed": gen_ai_attributes.GEN_AI_REQUEST_SEED,
},
)
for key, value in attributes.items():
if key.startswith(
GCP_GENAI_OPERATION_CONFIG
) and not allow_list.allowed(key):
# The allowlist is used to control inclusion of the dynamic keys.
continue
span.set_attribute(key, value)
def _get_response_property(response: GenerateContentResponse, path: str):
path_segments = path.split(".")
current_context = response
for path_segment in path_segments:
if current_context is None:
return None
if isinstance(current_context, dict):
current_context = current_context.get(path_segment)
else:
current_context = getattr(current_context, path_segment)
return current_context
def _coerce_config_to_object(
config: GenerateContentConfigOrDict,
) -> GenerateContentConfig:
if isinstance(config, GenerateContentConfig):
return config
# Input must be a dictionary; convert by invoking the constructor.
return GenerateContentConfig(**config)
def _wrapped_config_with_tools(
otel_wrapper: OTelWrapper,
config: GenerateContentConfig,
**kwargs,
):
if not config.tools:
return config
result = copy.copy(config)
result.tools = [
wrapped_tool(tool, otel_wrapper, **kwargs) for tool in config.tools
]
return result
class _GenerateContentInstrumentationHelper:
def __init__(
self,
models_object: Union[Models, AsyncModels],
otel_wrapper: OTelWrapper,
model: str,
generate_content_config_key_allowlist: Optional[AllowList] = None,
):
self._start_time = time.time_ns()
self._otel_wrapper = otel_wrapper
self._genai_system = _determine_genai_system(models_object)
self._genai_request_model = model
self._finish_reasons_set = set()
self._error_type = None
self._input_tokens = 0
self._output_tokens = 0
self._content_recording_enabled = is_content_recording_enabled()
self._response_index = 0
self._candidate_index = 0
self._generate_content_config_key_allowlist = (
generate_content_config_key_allowlist or AllowList()
)
def wrapped_config(
self, config: Optional[GenerateContentConfigOrDict]
) -> Optional[GenerateContentConfig]:
if config is None:
return None
return _wrapped_config_with_tools(
self._otel_wrapper,
_coerce_config_to_object(config),
extra_span_attributes={"gen_ai.system": self._genai_system},
)
def start_span_as_current_span(
self, model_name, function_name, end_on_exit=True
):
return self._otel_wrapper.start_as_current_span(
f"{_GENERATE_CONTENT_OP_NAME} {model_name}",
start_time=self._start_time,
attributes={
code_attributes.CODE_FUNCTION_NAME: function_name,
gen_ai_attributes.GEN_AI_SYSTEM: self._genai_system,
gen_ai_attributes.GEN_AI_REQUEST_MODEL: self._genai_request_model,
gen_ai_attributes.GEN_AI_OPERATION_NAME: _GENERATE_CONTENT_OP_NAME,
},
end_on_exit=end_on_exit,
)
def process_request(
self,
contents: Union[ContentListUnion, ContentListUnionDict],
config: Optional[GenerateContentConfigOrDict],
):
span = trace.get_current_span()
_add_request_options_to_span(
span, config, self._generate_content_config_key_allowlist
)
self._maybe_log_system_instruction(config=config)
self._maybe_log_user_prompt(contents)
def process_response(self, response: GenerateContentResponse):
# TODO: Determine if there are other response properties that
# need to be reflected back into the span attributes.
#
# See also: TODOS.md.
self._update_finish_reasons(response)
self._maybe_update_token_counts(response)
self._maybe_update_error_type(response)
self._maybe_log_response(response)
self._response_index += 1
def process_error(self, e: Exception):
self._error_type = str(e.__class__.__name__)
def finalize_processing(self):
span = trace.get_current_span()
span.set_attribute(
gen_ai_attributes.GEN_AI_USAGE_INPUT_TOKENS, self._input_tokens
)
span.set_attribute(
gen_ai_attributes.GEN_AI_USAGE_OUTPUT_TOKENS, self._output_tokens
)
span.set_attribute(
gen_ai_attributes.GEN_AI_RESPONSE_FINISH_REASONS,
sorted(self._finish_reasons_set),
)
self._record_token_usage_metric()
self._record_duration_metric()
def _update_finish_reasons(self, response):
if not response.candidates:
return
for candidate in response.candidates:
finish_reason = candidate.finish_reason
if finish_reason is None:
continue
finish_reason_str = finish_reason.name.lower().removeprefix(
"finish_reason_"
)
self._finish_reasons_set.add(finish_reason_str)
def _maybe_update_token_counts(self, response: GenerateContentResponse):
input_tokens = _get_response_property(
response, "usage_metadata.prompt_token_count"
)
output_tokens = _get_response_property(
response, "usage_metadata.candidates_token_count"
)
if input_tokens and isinstance(input_tokens, int):
self._input_tokens += input_tokens
if output_tokens and isinstance(output_tokens, int):
self._output_tokens += output_tokens
def _maybe_update_error_type(self, response: GenerateContentResponse):
if response.candidates:
return
if (
(not response.prompt_feedback)
or (not response.prompt_feedback.block_reason)
or (
response.prompt_feedback.block_reason
== BlockedReason.BLOCKED_REASON_UNSPECIFIED
)
):
self._error_type = "NO_CANDIDATES"
return
# TODO: in the case where there are no candidate responses due to
# safety settings like this, it might make sense to emit an event
# that contains more details regarding the safety settings, their
# thresholds, etc. However, this requires defining an associated
# semantic convention to capture this. Follow up with SemConv to
# establish appropriate data modelling to capture these details,
# and then emit those details accordingly. (For the time being,
# we use the defined 'error.type' semantic convention to relay
# just the minimum amount of error information here).
#
# See also: "TODOS.md"
block_reason = response.prompt_feedback.block_reason.name.upper()
self._error_type = f"BLOCKED_{block_reason}"
def _maybe_log_system_instruction(
self, config: Optional[GenerateContentConfigOrDict] = None
):
system_instruction = None
if config is not None:
if isinstance(config, dict):
system_instruction = config.get("system_instruction")
else:
system_instruction = config.system_instruction
if not system_instruction:
return
attributes = {
gen_ai_attributes.GEN_AI_SYSTEM: self._genai_system,
}
# TODO: determine if "role" should be reported here or not. It is unclear
# since the caller does not supply a "role" and since this comes through
# a property named "system_instruction" which would seem to align with
# the default "role" that is allowed to be omitted by default.
#
# See also: "TODOS.md"
body = {}
if self._content_recording_enabled:
body["content"] = _to_dict(system_instruction)
else:
body["content"] = _CONTENT_ELIDED
self._otel_wrapper.log_system_prompt(
attributes=attributes,
body=body,
)
def _maybe_log_user_prompt(
self, contents: Union[ContentListUnion, ContentListUnionDict]
):
if isinstance(contents, list):
total = len(contents)
index = 0
for entry in contents:
self._maybe_log_single_user_prompt(
entry, index=index, total=total
)
index += 1
else:
self._maybe_log_single_user_prompt(contents)
def _maybe_log_single_user_prompt(
self, contents: Union[ContentUnion, ContentUnionDict], index=0, total=1
):
# TODO: figure out how to report the index in a manner that is
# aligned with the OTel semantic conventions.
attributes = {
gen_ai_attributes.GEN_AI_SYSTEM: self._genai_system,
}
# TODO: determine if "role" should be reported here or not and, if so,
# what the value ought to be. It is not clear whether there is always
# a role supplied (and it looks like there could be cases where there
# is more than one role present in the supplied contents)?
#
# See also: "TODOS.md"
body = {}
if self._content_recording_enabled:
logged_contents = contents
if isinstance(contents, list):
logged_contents = Content(parts=contents)
body["content"] = _to_dict(logged_contents)
else:
body["content"] = _CONTENT_ELIDED
self._otel_wrapper.log_user_prompt(
attributes=attributes,
body=body,
)
def _maybe_log_response_stats(self, response: GenerateContentResponse):
# TODO: Determine if there is a way that we can log a summary
# of the overall response in a manner that is aligned with
# Semantic Conventions. For example, it would be natural
# to report an event that looks something like:
#
# gen_ai.response.stats {
# response_index: 0,
# candidate_count: 3,
# parts_per_candidate: [
# 3,
# 1,
# 5
# ]
# }
#
pass
def _maybe_log_response_safety_ratings(
self, response: GenerateContentResponse
):
# TODO: Determine if there is a way that we can log
# the "prompt_feedback". This would be especially useful
# in the case where the response is blocked.
pass
def _maybe_log_response(self, response: GenerateContentResponse):
self._maybe_log_response_stats(response)
self._maybe_log_response_safety_ratings(response)
if not response.candidates:
return
candidate_in_response_index = 0
for candidate in response.candidates:
self._maybe_log_response_candidate(
candidate,
flat_candidate_index=self._candidate_index,
candidate_in_response_index=candidate_in_response_index,
response_index=self._response_index,
)
self._candidate_index += 1
candidate_in_response_index += 1
def _maybe_log_response_candidate(
self,
candidate: Candidate,
flat_candidate_index: int,
candidate_in_response_index: int,
response_index: int,
):
# TODO: Determine if there might be a way to report the
# response index and candidate response index.
attributes = {
gen_ai_attributes.GEN_AI_SYSTEM: self._genai_system,
}
# TODO: determine if "role" should be reported here or not and, if so,
# what the value ought to be.
#
# TODO: extract tool information into a separate tool message.
#
# TODO: determine if/when we need to emit a 'gen_ai.assistant.message' event.
#
# TODO: determine how to report other relevant details in the candidate that
# are not presently captured by Semantic Conventions. For example, the
# "citation_metadata", "grounding_metadata", "logprobs_result", etc.
#
# See also: "TODOS.md"
body = {
"index": flat_candidate_index,
}
if self._content_recording_enabled:
if candidate.content:
body["content"] = _to_dict(candidate.content)
else:
body["content"] = _CONTENT_ELIDED
if candidate.finish_reason is not None:
body["finish_reason"] = candidate.finish_reason.name
self._otel_wrapper.log_response_content(
attributes=attributes,
body=body,
)
def _record_token_usage_metric(self):
self._otel_wrapper.token_usage_metric.record(
self._input_tokens,
attributes={
gen_ai_attributes.GEN_AI_TOKEN_TYPE: "input",
gen_ai_attributes.GEN_AI_SYSTEM: self._genai_system,
gen_ai_attributes.GEN_AI_REQUEST_MODEL: self._genai_request_model,
gen_ai_attributes.GEN_AI_OPERATION_NAME: _GENERATE_CONTENT_OP_NAME,
},
)
self._otel_wrapper.token_usage_metric.record(
self._output_tokens,
attributes={
gen_ai_attributes.GEN_AI_TOKEN_TYPE: "output",
gen_ai_attributes.GEN_AI_SYSTEM: self._genai_system,
gen_ai_attributes.GEN_AI_REQUEST_MODEL: self._genai_request_model,
gen_ai_attributes.GEN_AI_OPERATION_NAME: _GENERATE_CONTENT_OP_NAME,
},
)
def _record_duration_metric(self):
attributes = {
gen_ai_attributes.GEN_AI_SYSTEM: self._genai_system,
gen_ai_attributes.GEN_AI_REQUEST_MODEL: self._genai_request_model,
gen_ai_attributes.GEN_AI_OPERATION_NAME: _GENERATE_CONTENT_OP_NAME,
}
if self._error_type is not None:
attributes[error_attributes.ERROR_TYPE] = self._error_type
duration_nanos = time.time_ns() - self._start_time
duration_seconds = duration_nanos / 1e9
self._otel_wrapper.operation_duration_metric.record(
duration_seconds,
attributes=attributes,
)
def _create_instrumented_generate_content(
snapshot: _MethodsSnapshot,
otel_wrapper: OTelWrapper,
generate_content_config_key_allowlist: Optional[AllowList] = None,
):
wrapped_func = snapshot.generate_content
@functools.wraps(wrapped_func)
def instrumented_generate_content(
self: Models,
*,
model: str,
contents: Union[ContentListUnion, ContentListUnionDict],
config: Optional[GenerateContentConfigOrDict] = None,
**kwargs: Any,
) -> GenerateContentResponse:
helper = _GenerateContentInstrumentationHelper(
self,
otel_wrapper,
model,
generate_content_config_key_allowlist=generate_content_config_key_allowlist,
)
with helper.start_span_as_current_span(
model, "google.genai.Models.generate_content"
):
helper.process_request(contents, config)
try:
response = wrapped_func(
self,
model=model,
contents=contents,
config=helper.wrapped_config(config),
**kwargs,
)
helper.process_response(response)
return response
except Exception as error:
helper.process_error(error)
raise
finally:
helper.finalize_processing()
return instrumented_generate_content
def _create_instrumented_generate_content_stream(
snapshot: _MethodsSnapshot,
otel_wrapper: OTelWrapper,
generate_content_config_key_allowlist: Optional[AllowList] = None,
):
wrapped_func = snapshot.generate_content_stream
@functools.wraps(wrapped_func)
def instrumented_generate_content_stream(
self: Models,
*,
model: str,
contents: Union[ContentListUnion, ContentListUnionDict],
config: Optional[GenerateContentConfigOrDict] = None,
**kwargs: Any,
) -> Iterator[GenerateContentResponse]:
helper = _GenerateContentInstrumentationHelper(
self,
otel_wrapper,
model,
generate_content_config_key_allowlist=generate_content_config_key_allowlist,
)
with helper.start_span_as_current_span(
model, "google.genai.Models.generate_content_stream"
):
helper.process_request(contents, config)
try:
for response in wrapped_func(
self,
model=model,
contents=contents,
config=helper.wrapped_config(config),
**kwargs,
):
helper.process_response(response)
yield response
except Exception as error:
helper.process_error(error)
raise
finally:
helper.finalize_processing()
return instrumented_generate_content_stream
def _create_instrumented_async_generate_content(
snapshot: _MethodsSnapshot,
otel_wrapper: OTelWrapper,
generate_content_config_key_allowlist: Optional[AllowList] = None,
):
wrapped_func = snapshot.async_generate_content
@functools.wraps(wrapped_func)
async def instrumented_generate_content(
self: AsyncModels,
*,
model: str,
contents: Union[ContentListUnion, ContentListUnionDict],
config: Optional[GenerateContentConfigOrDict] = None,
**kwargs: Any,
) -> GenerateContentResponse:
helper = _GenerateContentInstrumentationHelper(
self,
otel_wrapper,
model,
generate_content_config_key_allowlist=generate_content_config_key_allowlist,
)
with helper.start_span_as_current_span(
model, "google.genai.AsyncModels.generate_content"
):
helper.process_request(contents, config)
try:
response = await wrapped_func(
self,
model=model,
contents=contents,
config=helper.wrapped_config(config),
**kwargs,
)
helper.process_response(response)
return response
except Exception as error:
helper.process_error(error)
raise
finally:
helper.finalize_processing()
return instrumented_generate_content
# Disabling type checking because this is not yet implemented and tested fully.
def _create_instrumented_async_generate_content_stream( # type: ignore
snapshot: _MethodsSnapshot,
otel_wrapper: OTelWrapper,
generate_content_config_key_allowlist: Optional[AllowList] = None,
):
wrapped_func = snapshot.async_generate_content_stream
@functools.wraps(wrapped_func)
async def instrumented_generate_content_stream(
self: AsyncModels,
*,
model: str,
contents: Union[ContentListUnion, ContentListUnionDict],
config: Optional[GenerateContentConfigOrDict] = None,
**kwargs: Any,
) -> Awaitable[AsyncIterator[GenerateContentResponse]]: # type: ignore
helper = _GenerateContentInstrumentationHelper(
self,
otel_wrapper,
model,
generate_content_config_key_allowlist=generate_content_config_key_allowlist,
)
with helper.start_span_as_current_span(
model,
"google.genai.AsyncModels.generate_content_stream",
end_on_exit=False,
) as span:
helper.process_request(contents, config)
try:
response_async_generator = await wrapped_func(
self,
model=model,
contents=contents,
config=helper.wrapped_config(config),
**kwargs,
)
except Exception as error: # pylint: disable=broad-exception-caught
helper.process_error(error)
helper.finalize_processing()
with trace.use_span(span, end_on_exit=True):
raise
async def _response_async_generator_wrapper():
with trace.use_span(span, end_on_exit=True):
try:
async for response in response_async_generator:
helper.process_response(response)
yield response
except Exception as error:
helper.process_error(error)
raise
finally:
helper.finalize_processing()
return _response_async_generator_wrapper()
return instrumented_generate_content_stream
def uninstrument_generate_content(snapshot: object):
assert isinstance(snapshot, _MethodsSnapshot)
snapshot.restore()
def instrument_generate_content(
otel_wrapper: OTelWrapper,
generate_content_config_key_allowlist: Optional[AllowList] = None,
) -> object:
snapshot = _MethodsSnapshot()
Models.generate_content = _create_instrumented_generate_content(
snapshot,
otel_wrapper,
generate_content_config_key_allowlist=generate_content_config_key_allowlist,
)
Models.generate_content_stream = _create_instrumented_generate_content_stream(
snapshot,
otel_wrapper,
generate_content_config_key_allowlist=generate_content_config_key_allowlist,
)
AsyncModels.generate_content = _create_instrumented_async_generate_content(
snapshot,
otel_wrapper,
generate_content_config_key_allowlist=generate_content_config_key_allowlist,
)
AsyncModels.generate_content_stream = _create_instrumented_async_generate_content_stream(
snapshot,
otel_wrapper,
generate_content_config_key_allowlist=generate_content_config_key_allowlist,
)
return snapshot

View File

@ -0,0 +1,67 @@
# Copyright The OpenTelemetry Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from typing import Any, Collection, Optional
from opentelemetry._events import get_event_logger_provider
from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
from opentelemetry.metrics import get_meter_provider
from opentelemetry.trace import get_tracer_provider
from .allowlist_util import AllowList
from .generate_content import (
instrument_generate_content,
uninstrument_generate_content,
)
from .otel_wrapper import OTelWrapper
class GoogleGenAiSdkInstrumentor(BaseInstrumentor):
def __init__(
self, generate_content_config_key_allowlist: Optional[AllowList] = None
):
self._generate_content_snapshot = None
self._generate_content_config_key_allowlist = (
generate_content_config_key_allowlist
or AllowList.from_env(
"OTEL_GOOGLE_GENAI_GENERATE_CONTENT_CONFIG_INCLUDES",
excludes_env_var="OTEL_GOOGLE_GENAI_GENERATE_CONTENT_CONFIG_EXCLUDES",
)
)
# Inherited, abstract function from 'BaseInstrumentor'. Even though 'self' is
# not used in the definition, a method is required per the API contract.
def instrumentation_dependencies(self) -> Collection[str]: # pylint: disable=no-self-use
return ["google-genai>=1.0.0,<2"]
def _instrument(self, **kwargs: Any):
tracer_provider = (
kwargs.get("tracer_provider") or get_tracer_provider()
)
event_logger_provider = (
kwargs.get("event_logger_provider") or get_event_logger_provider()
)
meter_provider = kwargs.get("meter_provider") or get_meter_provider()
otel_wrapper = OTelWrapper.from_providers(
tracer_provider=tracer_provider,
event_logger_provider=event_logger_provider,
meter_provider=meter_provider,
)
self._generate_content_snapshot = instrument_generate_content(
otel_wrapper,
generate_content_config_key_allowlist=self._generate_content_config_key_allowlist,
)
def _uninstrument(self, **kwargs: Any):
uninstrument_generate_content(self._generate_content_snapshot)

View File

@ -0,0 +1,92 @@
# Copyright The OpenTelemetry Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
import google.genai
from opentelemetry._events import Event
from opentelemetry.semconv._incubating.metrics import gen_ai_metrics
from opentelemetry.semconv.schemas import Schemas
from .version import __version__ as _LIBRARY_VERSION
_logger = logging.getLogger(__name__)
_SCOPE_NAME = "opentelemetry.instrumentation.google_genai"
_PYPI_PACKAGE_NAME = "opentelemetry-instrumentation-google-genai"
_SCHEMA_URL = Schemas.V1_30_0.value
_SCOPE_ATTRIBUTES = {
"gcp.client.name": "google.genai",
"gcp.client.repo": "googleapis/python-genai",
"gcp.client.version": google.genai.__version__,
"pypi.package.name": _PYPI_PACKAGE_NAME,
}
class OTelWrapper:
def __init__(self, tracer, event_logger, meter):
self._tracer = tracer
self._event_logger = event_logger
self._meter = meter
self._operation_duration_metric = (
gen_ai_metrics.create_gen_ai_client_operation_duration(meter)
)
self._token_usage_metric = (
gen_ai_metrics.create_gen_ai_client_token_usage(meter)
)
@staticmethod
def from_providers(tracer_provider, event_logger_provider, meter_provider):
return OTelWrapper(
tracer_provider.get_tracer(
_SCOPE_NAME, _LIBRARY_VERSION, _SCHEMA_URL, _SCOPE_ATTRIBUTES
),
event_logger_provider.get_event_logger(
_SCOPE_NAME, _LIBRARY_VERSION, _SCHEMA_URL, _SCOPE_ATTRIBUTES
),
meter=meter_provider.get_meter(
_SCOPE_NAME, _LIBRARY_VERSION, _SCHEMA_URL, _SCOPE_ATTRIBUTES
),
)
def start_as_current_span(self, *args, **kwargs):
return self._tracer.start_as_current_span(*args, **kwargs)
@property
def operation_duration_metric(self):
return self._operation_duration_metric
@property
def token_usage_metric(self):
return self._token_usage_metric
def log_system_prompt(self, attributes, body):
_logger.debug("Recording system prompt.")
event_name = "gen_ai.system.message"
self._log_event(event_name, attributes, body)
def log_user_prompt(self, attributes, body):
_logger.debug("Recording user prompt.")
event_name = "gen_ai.user.message"
self._log_event(event_name, attributes, body)
def log_response_content(self, attributes, body):
_logger.debug("Recording response.")
event_name = "gen_ai.choice"
self._log_event(event_name, attributes, body)
def _log_event(self, event_name, attributes, body):
event = Event(event_name, body=body, attributes=attributes)
self._event_logger.emit(event)

View File

@ -11,7 +11,5 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
This library provides a WSGI middleware that can be used on any WSGI framework
(such as Django / Flask / Web.py) to track requests timing through OpenTelemetry.
"""
_instruments = ("google-genai >= 1.0.0",)

View File

@ -0,0 +1,220 @@
# Copyright The OpenTelemetry Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import functools
import inspect
import json
from typing import Any, Callable, Optional, Union
from google.genai.types import (
ToolListUnion,
ToolListUnionDict,
ToolOrDict,
)
from opentelemetry import trace
from opentelemetry.semconv._incubating.attributes import (
code_attributes,
)
from .flags import is_content_recording_enabled
from .otel_wrapper import OTelWrapper
ToolFunction = Callable[..., Any]
def _is_primitive(value):
return isinstance(value, (str, int, bool, float))
def _to_otel_value(python_value):
"""Coerces parameters to something representable with Open Telemetry."""
if python_value is None or _is_primitive(python_value):
return python_value
if isinstance(python_value, list):
return [_to_otel_value(x) for x in python_value]
if isinstance(python_value, dict):
return {
key: _to_otel_value(val) for (key, val) in python_value.items()
}
if hasattr(python_value, "model_dump"):
return python_value.model_dump()
if hasattr(python_value, "__dict__"):
return _to_otel_value(python_value.__dict__)
return repr(python_value)
def _is_homogenous_primitive_list(value):
if not isinstance(value, list):
return False
if not value:
return True
if not _is_primitive(value[0]):
return False
first_type = type(value[0])
for entry in value[1:]:
if not isinstance(entry, first_type):
return False
return True
def _to_otel_attribute(python_value):
otel_value = _to_otel_value(python_value)
if _is_primitive(otel_value) or _is_homogenous_primitive_list(otel_value):
return otel_value
return json.dumps(otel_value)
def _create_function_span_name(wrapped_function):
"""Constructs the span name for a given local function tool call."""
function_name = wrapped_function.__name__
return f"execute_tool {function_name}"
def _create_function_span_attributes(
wrapped_function, function_args, function_kwargs, extra_span_attributes
):
"""Creates the attributes for a tool call function span."""
result = {}
if extra_span_attributes:
result.update(extra_span_attributes)
result["gen_ai.operation.name"] = "execute_tool"
result["gen_ai.tool.name"] = wrapped_function.__name__
if wrapped_function.__doc__:
result["gen_ai.tool.description"] = wrapped_function.__doc__
result[code_attributes.CODE_FUNCTION_NAME] = wrapped_function.__name__
result["code.module"] = wrapped_function.__module__
result["code.args.positional.count"] = len(function_args)
result["code.args.keyword.count"] = len(function_kwargs)
return result
def _record_function_call_argument(
span, param_name, param_value, include_values
):
attribute_prefix = f"code.function.parameters.{param_name}"
type_attribute = f"{attribute_prefix}.type"
span.set_attribute(type_attribute, type(param_value).__name__)
if include_values:
value_attribute = f"{attribute_prefix}.value"
span.set_attribute(value_attribute, _to_otel_attribute(param_value))
def _record_function_call_arguments(
otel_wrapper, wrapped_function, function_args, function_kwargs
):
"""Records the details about a function invocation as span attributes."""
include_values = is_content_recording_enabled()
span = trace.get_current_span()
signature = inspect.signature(wrapped_function)
params = list(signature.parameters.values())
for index, entry in enumerate(function_args):
param_name = f"args[{index}]"
if index < len(params):
param_name = params[index].name
_record_function_call_argument(span, param_name, entry, include_values)
for key, value in function_kwargs.items():
_record_function_call_argument(span, key, value, include_values)
def _record_function_call_result(otel_wrapper, wrapped_function, result):
"""Records the details about a function result as span attributes."""
include_values = is_content_recording_enabled()
span = trace.get_current_span()
span.set_attribute("code.function.return.type", type(result).__name__)
if include_values:
span.set_attribute(
"code.function.return.value", _to_otel_attribute(result)
)
def _wrap_sync_tool_function(
tool_function: ToolFunction,
otel_wrapper: OTelWrapper,
extra_span_attributes: Optional[dict[str, str]] = None,
**unused_kwargs,
):
@functools.wraps(tool_function)
def wrapped_function(*args, **kwargs):
span_name = _create_function_span_name(tool_function)
attributes = _create_function_span_attributes(
tool_function, args, kwargs, extra_span_attributes
)
with otel_wrapper.start_as_current_span(
span_name, attributes=attributes
):
_record_function_call_arguments(
otel_wrapper, tool_function, args, kwargs
)
result = tool_function(*args, **kwargs)
_record_function_call_result(otel_wrapper, tool_function, result)
return result
return wrapped_function
def _wrap_async_tool_function(
tool_function: ToolFunction,
otel_wrapper: OTelWrapper,
extra_span_attributes: Optional[dict[str, str]] = None,
**unused_kwargs,
):
@functools.wraps(tool_function)
async def wrapped_function(*args, **kwargs):
span_name = _create_function_span_name(tool_function)
attributes = _create_function_span_attributes(
tool_function, args, kwargs, extra_span_attributes
)
with otel_wrapper.start_as_current_span(
span_name, attributes=attributes
):
_record_function_call_arguments(
otel_wrapper, tool_function, args, kwargs
)
result = await tool_function(*args, **kwargs)
_record_function_call_result(otel_wrapper, tool_function, result)
return result
return wrapped_function
def _wrap_tool_function(
tool_function: ToolFunction, otel_wrapper: OTelWrapper, **kwargs
):
if inspect.iscoroutinefunction(tool_function):
return _wrap_async_tool_function(tool_function, otel_wrapper, **kwargs)
return _wrap_sync_tool_function(tool_function, otel_wrapper, **kwargs)
def wrapped(
tool_or_tools: Optional[
Union[ToolFunction, ToolOrDict, ToolListUnion, ToolListUnionDict]
],
otel_wrapper: OTelWrapper,
**kwargs,
):
if tool_or_tools is None:
return None
if isinstance(tool_or_tools, list):
return [
wrapped(item, otel_wrapper, **kwargs) for item in tool_or_tools
]
if isinstance(tool_or_tools, dict):
return {
key: wrapped(value, otel_wrapper, **kwargs)
for (key, value) in tool_or_tools.items()
}
if callable(tool_or_tools):
return _wrap_tool_function(tool_or_tools, otel_wrapper, **kwargs)
return tool_or_tools

View File

@ -0,0 +1,20 @@
# Copyright The OpenTelemetry Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# **IMPORTANT**:
#
# This version should stay below "1.0" until the fundamentals
# in "TODOS.md" have been addressed. Please revisit the TODOs
# listed there before bumping to a stable version.
__version__ = "0.4b0.dev"

View File

@ -0,0 +1,20 @@
# Copyright The OpenTelemetry Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import google.auth.credentials
class FakeCredentials(google.auth.credentials.AnonymousCredentials):
def refresh(self, request):
pass

View File

@ -0,0 +1,84 @@
# Copyright The OpenTelemetry Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import unittest
import google.genai
from .auth import FakeCredentials
from .instrumentation_context import InstrumentationContext
from .otel_mocker import OTelMocker
class TestCase(unittest.TestCase):
def setUp(self):
self._otel = OTelMocker()
self._otel.install()
self._instrumentation_context = None
self._api_key = "test-api-key"
self._project = "test-project"
self._location = "test-location"
self._client = None
self._uses_vertex = False
self._credentials = FakeCredentials()
self._instrumentor_args = {}
def _lazy_init(self):
self._instrumentation_context = InstrumentationContext(
**self._instrumentor_args
)
self._instrumentation_context.install()
def set_instrumentor_constructor_kwarg(self, key, value):
self._instrumentor_args[key] = value
@property
def client(self):
if self._client is None:
self._client = self._create_client()
return self._client
@property
def otel(self):
return self._otel
def set_use_vertex(self, use_vertex):
self._uses_vertex = use_vertex
def reset_client(self):
self._client = None
def reset_instrumentation(self):
if self._instrumentation_context is None:
return
self._instrumentation_context.uninstall()
self._instrumentation_context = None
def _create_client(self):
self._lazy_init()
if self._uses_vertex:
os.environ["GOOGLE_API_KEY"] = self._api_key
return google.genai.Client(
vertexai=True,
project=self._project,
location=self._location,
credentials=self._credentials,
)
return google.genai.Client(vertexai=False, api_key=self._api_key)
def tearDown(self):
if self._instrumentation_context is not None:
self._instrumentation_context.uninstall()
self._otel.uninstall()

View File

@ -0,0 +1,28 @@
# Copyright The OpenTelemetry Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from opentelemetry.instrumentation.google_genai import (
GoogleGenAiSdkInstrumentor,
)
class InstrumentationContext:
def __init__(self, **kwargs):
self._instrumentor = GoogleGenAiSdkInstrumentor(**kwargs)
def install(self):
self._instrumentor.instrument()
def uninstall(self):
self._instrumentor.uninstrument()

View File

@ -0,0 +1,232 @@
# Copyright The OpenTelemetry Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import opentelemetry._events
import opentelemetry._logs._internal
import opentelemetry.metrics._internal
import opentelemetry.trace
from opentelemetry._events import (
get_event_logger_provider,
set_event_logger_provider,
)
from opentelemetry._logs import get_logger_provider, set_logger_provider
from opentelemetry.metrics import get_meter_provider, set_meter_provider
from opentelemetry.sdk._events import EventLoggerProvider
from opentelemetry.sdk._logs import LoggerProvider
from opentelemetry.sdk._logs.export import (
InMemoryLogExporter,
SimpleLogRecordProcessor,
)
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics._internal.export import InMemoryMetricReader
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import SimpleSpanProcessor
from opentelemetry.sdk.trace.export.in_memory_span_exporter import (
InMemorySpanExporter,
)
from opentelemetry.trace import get_tracer_provider, set_tracer_provider
from opentelemetry.util._once import Once
def _bypass_otel_once():
opentelemetry.trace._TRACER_PROVIDER_SET_ONCE = Once()
opentelemetry._logs._internal._LOGGER_PROVIDER_SET_ONCE = Once()
opentelemetry._events._EVENT_LOGGER_PROVIDER_SET_ONCE = Once()
opentelemetry.metrics._internal._METER_PROVIDER_SET_ONCE = Once()
class OTelProviderSnapshot:
def __init__(self):
self._tracer_provider = get_tracer_provider()
self._logger_provider = get_logger_provider()
self._event_logger_provider = get_event_logger_provider()
self._meter_provider = get_meter_provider()
def restore(self):
_bypass_otel_once()
set_tracer_provider(self._tracer_provider)
set_logger_provider(self._logger_provider)
set_event_logger_provider(self._event_logger_provider)
set_meter_provider(self._meter_provider)
class _LogWrapper:
def __init__(self, log_data):
self._log_data = log_data
@property
def scope(self):
return self._log_data.instrumentation_scope
@property
def resource(self):
return self._log_data.log_record.resource
@property
def attributes(self):
return self._log_data.log_record.attributes
@property
def body(self):
return self._log_data.log_record.body
def __str__(self):
return self._log_data.log_record.to_json()
class _MetricDataPointWrapper:
def __init__(self, resource, scope, metric):
self._resource = resource
self._scope = scope
self._metric = metric
@property
def resource(self):
return self._resource
@property
def scope(self):
return self._scope
@property
def metric(self):
return self._metric
@property
def name(self):
return self._metric.name
@property
def data(self):
return self._metric.data
class OTelMocker:
def __init__(self):
self._snapshot = None
self._logs = InMemoryLogExporter()
self._traces = InMemorySpanExporter()
self._metrics = InMemoryMetricReader()
self._spans = []
self._finished_logs = []
self._metrics_data = []
def install(self):
self._snapshot = OTelProviderSnapshot()
_bypass_otel_once()
self._install_logs()
self._install_metrics()
self._install_traces()
def uninstall(self):
self._snapshot.restore()
def get_finished_logs(self):
for log_data in self._logs.get_finished_logs():
self._finished_logs.append(_LogWrapper(log_data))
return self._finished_logs
def get_finished_spans(self):
for span in self._traces.get_finished_spans():
self._spans.append(span)
return self._spans
def get_metrics_data(self):
data = self._metrics.get_metrics_data()
if data is not None:
for resource_metric in data.resource_metrics:
resource = resource_metric.resource
for scope_metrics in resource_metric.scope_metrics:
scope = scope_metrics.scope
for metric in scope_metrics.metrics:
wrapper = _MetricDataPointWrapper(
resource, scope, metric
)
self._metrics_data.append(wrapper)
return self._metrics_data
def get_span_named(self, name):
for span in self.get_finished_spans():
if span.name == name:
return span
return None
def assert_has_span_named(self, name):
span = self.get_span_named(name)
finished_spans = [span.name for span in self.get_finished_spans()]
assert (
span is not None
), f'Could not find span named "{name}"; finished spans: {finished_spans}'
def assert_does_not_have_span_named(self, name):
span = self.get_span_named(name)
assert span is None, f"Found unexpected span named {name}"
def get_event_named(self, event_name):
for event in self.get_finished_logs():
event_name_attr = event.attributes.get("event.name")
if event_name_attr is None:
continue
if event_name_attr == event_name:
return event
return None
def get_events_named(self, event_name):
result = []
for event in self.get_finished_logs():
event_name_attr = event.attributes.get("event.name")
if event_name_attr is None:
continue
if event_name_attr == event_name:
result.append(event)
return result
def assert_has_event_named(self, name):
event = self.get_event_named(name)
finished_logs = self.get_finished_logs()
assert (
event is not None
), f'Could not find event named "{name}"; finished logs: {finished_logs}'
def assert_does_not_have_event_named(self, name):
event = self.get_event_named(name)
assert event is None, f"Unexpected event: {event}"
def get_metrics_data_named(self, name):
results = []
for entry in self.get_metrics_data():
if entry.name == name:
results.append(entry)
return results
def assert_has_metrics_data_named(self, name):
data = self.get_metrics_data_named(name)
assert len(data) > 0
def _install_logs(self):
provider = LoggerProvider()
provider.add_log_record_processor(SimpleLogRecordProcessor(self._logs))
set_logger_provider(provider)
event_provider = EventLoggerProvider(logger_provider=provider)
set_event_logger_provider(event_provider)
def _install_metrics(self):
provider = MeterProvider(metric_readers=[self._metrics])
set_meter_provider(provider)
def _install_traces(self):
provider = TracerProvider()
provider.add_span_processor(SimpleSpanProcessor(self._traces))
set_tracer_provider(provider)

View File

@ -0,0 +1,163 @@
# Copyright The OpenTelemetry Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import unittest
import unittest.mock
from google.genai.models import AsyncModels, Models
from ..common.base import TestCase as CommonTestCaseBase
from .util import convert_to_response, create_response
# Helper used in "_install_mocks" below.
def _wrap_output(mock_generate_content):
def _wrapped(*args, **kwargs):
return convert_to_response(mock_generate_content(*args, **kwargs))
return _wrapped
# Helper used in "_install_mocks" below.
def _wrap_output_stream(mock_generate_content_stream):
def _wrapped(*args, **kwargs):
for output in mock_generate_content_stream(*args, **kwargs):
yield convert_to_response(output)
return _wrapped
# Helper used in "_install_mocks" below.
def _async_wrapper(mock_generate_content):
async def _wrapped(*args, **kwargs):
return mock_generate_content(*args, **kwargs)
return _wrapped
# Helper used in "_install_mocks" below.
def _async_stream_wrapper(mock_generate_content_stream):
async def _wrapped(*args, **kwargs):
async def _internal_generator():
for result in mock_generate_content_stream(*args, **kwargs):
yield result
return _internal_generator()
return _wrapped
class TestCase(CommonTestCaseBase):
# The "setUp" function is defined by "unittest.TestCase" and thus
# this name must be used. Uncertain why pylint doesn't seem to
# recognize that this is a unit test class for which this is inherited.
def setUp(self): # pylint: disable=invalid-name
super().setUp()
if self.__class__ == TestCase:
raise unittest.SkipTest("Skipping testcase base.")
self._generate_content_mock = None
self._generate_content_stream_mock = None
self._original_generate_content = Models.generate_content
self._original_generate_content_stream = Models.generate_content_stream
self._original_async_generate_content = AsyncModels.generate_content
self._original_async_generate_content_stream = (
AsyncModels.generate_content_stream
)
self._responses = []
self._response_index = 0
@property
def mock_generate_content(self):
if self._generate_content_mock is None:
self._create_and_install_mocks()
return self._generate_content_mock
@property
def mock_generate_content_stream(self):
if self._generate_content_stream_mock is None:
self._create_and_install_mocks()
return self._generate_content_stream_mock
def configure_valid_response(self, **kwargs):
self._create_and_install_mocks()
response = create_response(**kwargs)
self._responses.append(response)
def _create_and_install_mocks(self):
if self._generate_content_mock is not None:
return
self.reset_client()
self.reset_instrumentation()
self._generate_content_mock = self._create_nonstream_mock()
self._generate_content_stream_mock = self._create_stream_mock()
self._install_mocks()
def _create_nonstream_mock(self):
mock = unittest.mock.MagicMock()
def _default_impl(*args, **kwargs):
if not self._responses:
return create_response(text="Some response")
index = self._response_index % len(self._responses)
result = self._responses[index]
self._response_index += 1
return result
mock.side_effect = _default_impl
return mock
def _create_stream_mock(self):
mock = unittest.mock.MagicMock()
def _default_impl(*args, **kwargs):
for response in self._responses:
yield response
mock.side_effect = _default_impl
return mock
def _install_mocks(self):
output_wrapped = _wrap_output(self._generate_content_mock)
output_wrapped_stream = _wrap_output_stream(
self._generate_content_stream_mock
)
Models.generate_content = output_wrapped
Models.generate_content_stream = output_wrapped_stream
AsyncModels.generate_content = _async_wrapper(output_wrapped)
AsyncModels.generate_content_stream = _async_stream_wrapper(
output_wrapped_stream
)
def tearDown(self):
super().tearDown()
if self._generate_content_mock is None:
assert Models.generate_content == self._original_generate_content
assert (
Models.generate_content_stream
== self._original_generate_content_stream
)
assert (
AsyncModels.generate_content
== self._original_async_generate_content
)
assert (
AsyncModels.generate_content_stream
== self._original_async_generate_content_stream
)
Models.generate_content = self._original_generate_content
Models.generate_content_stream = self._original_generate_content_stream
AsyncModels.generate_content = self._original_async_generate_content
AsyncModels.generate_content_stream = (
self._original_async_generate_content_stream
)

View File

@ -0,0 +1,94 @@
interactions:
- request:
body: |-
{
"contents": [
{
"parts": [
{
"text": "Create a poem about Open Telemetry."
}
],
"role": "user"
}
]
}
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
Content-Length:
- '92'
Content-Type:
- application/json
user-agent:
- google-genai-sdk/1.0.0 gl-python/3.12.8
x-goog-api-client:
- <REDACTED>
x-goog-user-project:
- <REDACTED>
method: POST
uri: https://test-location-aiplatform.googleapis.com/v1beta1/projects/test-project/locations/test-location/publishers/google/models/gemini-1.5-flash-002:generateContent
response:
body:
string: |-
{
"candidates": [
{
"content": {
"role": "model",
"parts": [
{
"text": "No more dark, inscrutable ways,\nTo trace a request through hazy days.\nOpen Telemetry, a beacon bright,\nIlluminates the path, both day and night.\n\nFrom metrics gathered, a clear display,\nOf latency's dance, and errors' sway.\nTraces unwind, a silken thread,\nShowing the journey, from start to head.\n\nLogs interweave, a richer hue,\nContextual clues, for me and you.\nNo vendor lock-in, a freedom's call,\nTo choose your tools, to stand up tall.\n\nExporters aplenty, a varied choice,\nTo send your data, amplify your voice.\nJaeger, Zipkin, Prometheus' might,\nAll integrate, a glorious sight.\n\nWith spans and attributes, a detailed scene,\nOf how your system works, both sleek and keen.\nPerformance bottlenecks, now laid bare,\nOpen Telemetry, beyond compare.\n\nSo embrace the light, let darkness flee,\nWith Open Telemetry, set your systems free.\nObserve, and learn, and optimize with grace,\nA brighter future, in this digital space.\n"
}
]
},
"finishReason": "STOP",
"avgLogprobs": -0.3303731600443522
}
],
"usageMetadata": {
"promptTokenCount": 8,
"candidatesTokenCount": 240,
"totalTokenCount": 248,
"promptTokensDetails": [
{
"modality": "TEXT",
"tokenCount": 8
}
],
"candidatesTokensDetails": [
{
"modality": "TEXT",
"tokenCount": 240
}
]
},
"modelVersion": "gemini-1.5-flash-002",
"createTime": "2025-03-07T22:19:18.083091Z",
"responseId": "5nDLZ5OJBdyY3NoPiZGx0Ag"
}
headers:
Content-Encoding:
- gzip
Content-Type:
- application/json; charset=UTF-8
Transfer-Encoding:
- chunked
Vary:
- Origin
- X-Origin
- Referer
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- SAMEORIGIN
X-XSS-Protection:
- '0'
status:
code: 200
message: OK
version: 1

View File

@ -0,0 +1,94 @@
interactions:
- request:
body: |-
{
"contents": [
{
"parts": [
{
"text": "Create a poem about Open Telemetry."
}
],
"role": "user"
}
]
}
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
Content-Length:
- '92'
Content-Type:
- application/json
user-agent:
- google-genai-sdk/1.0.0 gl-python/3.12.8
x-goog-api-client:
- <REDACTED>
x-goog-user-project:
- <REDACTED>
method: POST
uri: https://test-location-aiplatform.googleapis.com/v1beta1/projects/test-project/locations/test-location/publishers/google/models/gemini-1.5-flash-002:generateContent
response:
body:
string: |-
{
"candidates": [
{
"content": {
"role": "model",
"parts": [
{
"text": "No more dark logs, a cryptic, hidden trace,\nOf failing systems, lost in time and space.\nOpenTelemetry, a beacon shining bright,\nIlluminating paths, both dark and light.\n\nFrom microservices, a sprawling, tangled mesh,\nTo monolithic beasts, put to the test,\nIt gathers traces, spans, and metrics too,\nA holistic view, for me and you.\n\nWith signals clear, from every single node,\nPerformance bottlenecks, instantly bestowed.\nDistributed tracing, paints a vivid scene,\nWhere latency lurks, and slowdowns intervene.\n\nExporters rise, to send the data forth,\nTo dashboards grand, of proven, measured worth.\nPrometheus, Grafana, Jaeger, fluent streams,\nVisualizing insights, fulfilling data dreams.\n\nFrom Jaeger's diagrams, a branching, flowing art,\nTo Grafana's charts, that play a vital part,\nThe mysteries unravel, hidden deep inside,\nWhere errors slumber, and slow responses hide.\n\nSo hail OpenTelemetry, a gift to all who code,\nA brighter future, on a well-lit road.\nNo more guesswork, no more fruitless chase,\nJust clear observability, in time and space.\n"
}
]
},
"finishReason": "STOP",
"avgLogprobs": -0.45532724261283875
}
],
"usageMetadata": {
"promptTokenCount": 8,
"candidatesTokenCount": 256,
"totalTokenCount": 264,
"promptTokensDetails": [
{
"modality": "TEXT",
"tokenCount": 8
}
],
"candidatesTokensDetails": [
{
"modality": "TEXT",
"tokenCount": 256
}
]
},
"modelVersion": "gemini-1.5-flash-002",
"createTime": "2025-03-07T22:19:15.268428Z",
"responseId": "43DLZ4yxEM6F3NoPzaTkiQU"
}
headers:
Content-Encoding:
- gzip
Content-Type:
- application/json; charset=UTF-8
Transfer-Encoding:
- chunked
Vary:
- Origin
- X-Origin
- Referer
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- SAMEORIGIN
X-XSS-Protection:
- '0'
status:
code: 200
message: OK
version: 1

View File

@ -0,0 +1,94 @@
interactions:
- request:
body: |-
{
"contents": [
{
"parts": [
{
"text": "Create a poem about Open Telemetry."
}
],
"role": "user"
}
]
}
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
Content-Length:
- '92'
Content-Type:
- application/json
user-agent:
- google-genai-sdk/1.0.0 gl-python/3.12.8
x-goog-api-client:
- <REDACTED>
x-goog-user-project:
- <REDACTED>
method: POST
uri: https://test-location-aiplatform.googleapis.com/v1beta1/projects/test-project/locations/test-location/publishers/google/models/gemini-1.5-flash-002:generateContent
response:
body:
string: |-
{
"candidates": [
{
"content": {
"role": "model",
"parts": [
{
"text": "No more dark, mysterious traces,\nNo more guessing, in empty spaces.\nOpenTelemetry's light now shines,\nIlluminating all our designs.\n\nFrom microservices, small and fleet,\nTo monolithic beasts, hard to beat,\nIt weaves a net, both fine and strong,\nWhere metrics flow, where logs belong.\n\nTraces dance, a vibrant hue,\nShowing journeys, old and new.\nSpans unfold, a story told,\nOf requests handled, brave and bold.\n\nMetrics hum, a steady beat,\nLatency, errors, can't be beat.\nDistribution charts, a clear display,\nGuiding us along the way.\n\nLogs provide a detailed view,\nOf what happened, me and you.\nContext rich, with helpful clues,\nDebugging woes, it quickly subdues.\n\nWith exporters wise, a thoughtful choice,\nTo Prometheus, Jaeger, or Zipkin's voice,\nOur data flows, a precious stream,\nReal-time insights, a waking dream.\n\nSo hail to OpenTelemetry's might,\nBringing clarity to our darkest night.\nObservability's champion, bold and true,\nA brighter future, for me and you.\n"
}
]
},
"finishReason": "STOP",
"avgLogprobs": -0.4071464086238575
}
],
"usageMetadata": {
"promptTokenCount": 8,
"candidatesTokenCount": 253,
"totalTokenCount": 261,
"promptTokensDetails": [
{
"modality": "TEXT",
"tokenCount": 8
}
],
"candidatesTokensDetails": [
{
"modality": "TEXT",
"tokenCount": 253
}
]
},
"modelVersion": "gemini-1.5-flash-002",
"createTime": "2025-03-07T22:19:12.443989Z",
"responseId": "4HDLZ9WMG6SK698Pr5uZ2Qw"
}
headers:
Content-Encoding:
- gzip
Content-Type:
- application/json; charset=UTF-8
Transfer-Encoding:
- chunked
Vary:
- Origin
- X-Origin
- Referer
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- SAMEORIGIN
X-XSS-Protection:
- '0'
status:
code: 200
message: OK
version: 1

View File

@ -0,0 +1,94 @@
interactions:
- request:
body: |-
{
"contents": [
{
"parts": [
{
"text": "Create a poem about Open Telemetry."
}
],
"role": "user"
}
]
}
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
Content-Length:
- '92'
Content-Type:
- application/json
user-agent:
- google-genai-sdk/1.0.0 gl-python/3.12.8
x-goog-api-client:
- <REDACTED>
x-goog-user-project:
- <REDACTED>
method: POST
uri: https://test-location-aiplatform.googleapis.com/v1beta1/projects/test-project/locations/test-location/publishers/google/models/gemini-1.5-flash-002:generateContent
response:
body:
string: |-
{
"candidates": [
{
"content": {
"role": "model",
"parts": [
{
"text": "No more dark, mysterious traces,\nOf failing systems, hidden spaces.\nOpen Telemetry's light shines bright,\nGuiding us through the darkest night.\n\nFrom metrics gathered, finely spun,\nTo logs that tell of tasks undone,\nAnd traces linking every call,\nIt answers questions, standing tall.\n\nDistributed systems, complex and vast,\nTheir hidden flaws, no longer cast\nIn shadows deep, beyond our view,\nOpen Telemetry sees them through.\n\nWith spans and attributes, it weaves a tale,\nOf requests flowing, never frail.\nIt pinpoints bottlenecks, slow and grim,\nAnd helps us optimize, system trim.\n\nAcross languages, a common ground,\nWhere data's shared, and insights found.\nExporters whisper, collectors hum,\nA symphony of data, overcome.\n\nSo raise a glass, to this open source,\nA shining beacon, a powerful force.\nOpen Telemetry, a guiding star,\nRevealing secrets, near and far.\n"
}
]
},
"finishReason": "STOP",
"avgLogprobs": -0.3586180628193498
}
],
"usageMetadata": {
"promptTokenCount": 8,
"candidatesTokenCount": 211,
"totalTokenCount": 219,
"promptTokensDetails": [
{
"modality": "TEXT",
"tokenCount": 8
}
],
"candidatesTokensDetails": [
{
"modality": "TEXT",
"tokenCount": 211
}
]
},
"modelVersion": "gemini-1.5-flash-002",
"createTime": "2025-03-07T22:19:09.936326Z",
"responseId": "3XDLZ4aTOZSpnvgPn-e0qQk"
}
headers:
Content-Encoding:
- gzip
Content-Type:
- application/json; charset=UTF-8
Transfer-Encoding:
- chunked
Vary:
- Origin
- X-Origin
- Referer
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- SAMEORIGIN
X-XSS-Protection:
- '0'
status:
code: 200
message: OK
version: 1

View File

@ -0,0 +1,97 @@
interactions:
- request:
body: |-
{
"contents": [
{
"parts": [
{
"text": "Create a poem about Open Telemetry."
}
],
"role": "user"
}
]
}
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
Content-Length:
- '92'
Content-Type:
- application/json
user-agent:
- google-genai-sdk/1.0.0 gl-python/3.12.8
x-goog-api-client:
- <REDACTED>
x-goog-user-project:
- <REDACTED>
method: POST
uri: https://test-location-aiplatform.googleapis.com/v1beta1/projects/test-project/locations/test-location/publishers/google/models/gemini-1.5-flash-002:streamGenerateContent?alt=sse
response:
body:
string: "data: {\"candidates\": [{\"content\": {\"role\": \"model\",\"parts\"\
: [{\"text\": \"No\"}]}}],\"usageMetadata\": {},\"modelVersion\": \"gemini-1.5-flash-002\"\
,\"createTime\": \"2025-03-07T22:19:29.293930Z\",\"responseId\": \"8XDLZ6r4Efa1-O4PwIHamQ4\"\
}\r\n\r\ndata: {\"candidates\": [{\"content\": {\"role\": \"model\",\"parts\"\
: [{\"text\": \" longer dark, the tracing's light,\\nOpen Telemetry, shining\
\ bright\"}]}}],\"modelVersion\": \"gemini-1.5-flash-002\",\"createTime\"\
: \"2025-03-07T22:19:29.293930Z\",\"responseId\": \"8XDLZ6r4Efa1-O4PwIHamQ4\"\
}\r\n\r\ndata: {\"candidates\": [{\"content\": {\"role\": \"model\",\"parts\"\
: [{\"text\": \".\\nA beacon in the coding night,\\nRevealing paths, both\
\ dark\"}]}}],\"modelVersion\": \"gemini-1.5-flash-002\",\"createTime\": \"\
2025-03-07T22:19:29.293930Z\",\"responseId\": \"8XDLZ6r4Efa1-O4PwIHamQ4\"\
}\r\n\r\ndata: {\"candidates\": [{\"content\": {\"role\": \"model\",\"parts\"\
: [{\"text\": \" and bright.\\n\\nFrom microservice to sprawling beast,\\\
nIts watchful eye, a silent priest.\\nObserving calls, both small and vast,\\\
nPerformance\"}]}}],\"modelVersion\": \"gemini-1.5-flash-002\",\"createTime\"\
: \"2025-03-07T22:19:29.293930Z\",\"responseId\": \"8XDLZ6r4Efa1-O4PwIHamQ4\"\
}\r\n\r\ndata: {\"candidates\": [{\"content\": {\"role\": \"model\",\"parts\"\
: [{\"text\": \" flaws, revealed at last.\\n\\nWith metrics gleaned and logs\
\ aligned,\\nA clearer picture, you will find.\\nOf latency, and errors dire,\\\
n\"}]}}],\"modelVersion\": \"gemini-1.5-flash-002\",\"createTime\": \"2025-03-07T22:19:29.293930Z\"\
,\"responseId\": \"8XDLZ6r4Efa1-O4PwIHamQ4\"}\r\n\r\ndata: {\"candidates\"\
: [{\"content\": {\"role\": \"model\",\"parts\": [{\"text\": \"And bottlenecks\
\ that set afire.\\n\\nIt spans the clouds, a network wide,\\nWhere data streams,\
\ a surging tide.\\nCollecting traces, rich and deep,\\nWhile slumbering apps\
\ their secrets keep.\\n\\nJaeger, Zip\"}]}}],\"modelVersion\": \"gemini-1.5-flash-002\"\
,\"createTime\": \"2025-03-07T22:19:29.293930Z\",\"responseId\": \"8XDLZ6r4Efa1-O4PwIHamQ4\"\
}\r\n\r\ndata: {\"candidates\": [{\"content\": {\"role\": \"model\",\"parts\"\
: [{\"text\": \"kin, the tools it holds,\\nA tapestry of stories told.\\nOf\
\ requests flowing, swift and free,\\nOr tangled knots, for all to see.\\\
n\\nSo embrace the power, understand,\\nThe vital role, across the\"}]}}],\"\
modelVersion\": \"gemini-1.5-flash-002\",\"createTime\": \"2025-03-07T22:19:29.293930Z\"\
,\"responseId\": \"8XDLZ6r4Efa1-O4PwIHamQ4\"}\r\n\r\ndata: {\"candidates\"\
: [{\"content\": {\"role\": \"model\",\"parts\": [{\"text\": \" land.\\nOpen\
\ Telemetry, a guiding star,\\nTo navigate the digital afar.\\n\"}]},\"finishReason\"\
: \"STOP\"}],\"usageMetadata\": {\"promptTokenCount\": 8,\"candidatesTokenCount\"\
: 212,\"totalTokenCount\": 220,\"promptTokensDetails\": [{\"modality\": \"\
TEXT\",\"tokenCount\": 8}],\"candidatesTokensDetails\": [{\"modality\": \"\
TEXT\",\"tokenCount\": 212}]},\"modelVersion\": \"gemini-1.5-flash-002\",\"\
createTime\": \"2025-03-07T22:19:29.293930Z\",\"responseId\": \"8XDLZ6r4Efa1-O4PwIHamQ4\"\
}\r\n\r\n"
headers:
Content-Disposition:
- attachment
Content-Type:
- text/event-stream
Transfer-Encoding:
- chunked
Vary:
- Origin
- X-Origin
- Referer
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- SAMEORIGIN
X-XSS-Protection:
- '0'
status:
code: 200
message: OK
version: 1

View File

@ -0,0 +1,102 @@
interactions:
- request:
body: |-
{
"contents": [
{
"parts": [
{
"text": "Create a poem about Open Telemetry."
}
],
"role": "user"
}
]
}
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
Content-Length:
- '92'
Content-Type:
- application/json
user-agent:
- google-genai-sdk/1.0.0 gl-python/3.12.8
x-goog-api-client:
- <REDACTED>
x-goog-user-project:
- <REDACTED>
method: POST
uri: https://test-location-aiplatform.googleapis.com/v1beta1/projects/test-project/locations/test-location/publishers/google/models/gemini-1.5-flash-002:streamGenerateContent?alt=sse
response:
body:
string: "data: {\"candidates\": [{\"content\": {\"role\": \"model\",\"parts\"\
: [{\"text\": \"The\"}]}}],\"usageMetadata\": {},\"modelVersion\": \"gemini-1.5-flash-002\"\
,\"createTime\": \"2025-03-07T22:19:26.378633Z\",\"responseId\": \"7nDLZ4mOF_Hg-O4P7YfKqQ8\"\
}\r\n\r\ndata: {\"candidates\": [{\"content\": {\"role\": \"model\",\"parts\"\
: [{\"text\": \" black box whispers, secrets deep,\\nOf failing systems, promises\
\ to keep.\"}]}}],\"modelVersion\": \"gemini-1.5-flash-002\",\"createTime\"\
: \"2025-03-07T22:19:26.378633Z\",\"responseId\": \"7nDLZ4mOF_Hg-O4P7YfKqQ8\"\
}\r\n\r\ndata: {\"candidates\": [{\"content\": {\"role\": \"model\",\"parts\"\
: [{\"text\": \"\\nBut tracing's light, a guiding hand,\\nReveals the path\"\
}]}}],\"modelVersion\": \"gemini-1.5-flash-002\",\"createTime\": \"2025-03-07T22:19:26.378633Z\"\
,\"responseId\": \"7nDLZ4mOF_Hg-O4P7YfKqQ8\"}\r\n\r\ndata: {\"candidates\"\
: [{\"content\": {\"role\": \"model\",\"parts\": [{\"text\": \", across the\
\ land.\\n\\nOpen Telemetry, a beacon bright,\\nIlluminating pathways, day\
\ and night.\\nFrom spans and traces, stories told,\"}]}}],\"modelVersion\"\
: \"gemini-1.5-flash-002\",\"createTime\": \"2025-03-07T22:19:26.378633Z\"\
,\"responseId\": \"7nDLZ4mOF_Hg-O4P7YfKqQ8\"}\r\n\r\ndata: {\"candidates\"\
: [{\"content\": {\"role\": \"model\",\"parts\": [{\"text\": \"\\nOf requests\
\ flowing, brave and bold.\\n\\nThe metrics rise, a vibrant chart,\\nDisplaying\
\ latency, a work of art.\\nEach request'\"}]}}],\"modelVersion\": \"gemini-1.5-flash-002\"\
,\"createTime\": \"2025-03-07T22:19:26.378633Z\",\"responseId\": \"7nDLZ4mOF_Hg-O4P7YfKqQ8\"\
}\r\n\r\ndata: {\"candidates\": [{\"content\": {\"role\": \"model\",\"parts\"\
: [{\"text\": \"s journey, clearly shown,\\nWhere bottlenecks slumber, seeds\
\ are sown.\\n\\nWith logs appended, context clear,\\nThe root of problems,\
\ drawing near.\\nObservability's embrace, so wide,\\nUnraveling mysteries,\"\
}]}}],\"modelVersion\": \"gemini-1.5-flash-002\",\"createTime\": \"2025-03-07T22:19:26.378633Z\"\
,\"responseId\": \"7nDLZ4mOF_Hg-O4P7YfKqQ8\"}\r\n\r\ndata: {\"candidates\"\
: [{\"content\": {\"role\": \"model\",\"parts\": [{\"text\": \" deep inside.\\\
n\\nFrom simple apps to complex weaves,\\nOpen Telemetry's power achieves,\\\
nA unified vision, strong and true,\\nMonitoring systems, old and new.\\n\\\
nNo vendor lock-in, free to roam,\"}]}}],\"modelVersion\": \"gemini-1.5-flash-002\"\
,\"createTime\": \"2025-03-07T22:19:26.378633Z\",\"responseId\": \"7nDLZ4mOF_Hg-O4P7YfKqQ8\"\
}\r\n\r\ndata: {\"candidates\": [{\"content\": {\"role\": \"model\",\"parts\"\
: [{\"text\": \"\\nAcross the clouds, and find your home.\\nA standard rising,\
\ strong and bold,\\nA future brighter, to behold.\\n\\nSo let the traces\
\ flow and gleam,\\nOpen Telemetry, a vibrant dream.\\nOf healthy systems,\
\ running free,\\nFor all to see, for all to be.\"}]}}],\"modelVersion\":\
\ \"gemini-1.5-flash-002\",\"createTime\": \"2025-03-07T22:19:26.378633Z\"\
,\"responseId\": \"7nDLZ4mOF_Hg-O4P7YfKqQ8\"}\r\n\r\ndata: {\"candidates\"\
: [{\"content\": {\"role\": \"model\",\"parts\": [{\"text\": \"\\n\"}]},\"\
finishReason\": \"STOP\"}],\"usageMetadata\": {\"promptTokenCount\": 8,\"\
candidatesTokenCount\": 258,\"totalTokenCount\": 266,\"promptTokensDetails\"\
: [{\"modality\": \"TEXT\",\"tokenCount\": 8}],\"candidatesTokensDetails\"\
: [{\"modality\": \"TEXT\",\"tokenCount\": 258}]},\"modelVersion\": \"gemini-1.5-flash-002\"\
,\"createTime\": \"2025-03-07T22:19:26.378633Z\",\"responseId\": \"7nDLZ4mOF_Hg-O4P7YfKqQ8\"\
}\r\n\r\n"
headers:
Content-Disposition:
- attachment
Content-Type:
- text/event-stream
Transfer-Encoding:
- chunked
Vary:
- Origin
- X-Origin
- Referer
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- SAMEORIGIN
X-XSS-Protection:
- '0'
status:
code: 200
message: OK
version: 1

Some files were not shown because too many files have changed in this diff Show More