Add Initial Support for Instrumenting OpenAI Python Library - Chat Completion Create (#2759)
This commit is contained in:
parent
cef28d6f24
commit
beed0aa395
|
|
@ -16,6 +16,24 @@ env:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
|
lint-instrumentation-openai-v2:
|
||||||
|
name: instrumentation-openai-v2
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
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
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: tox -e lint-instrumentation-openai-v2
|
||||||
|
|
||||||
lint-resource-detector-container:
|
lint-resource-detector-container:
|
||||||
name: resource-detector-container
|
name: resource-detector-container
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,114 @@ env:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
|
py38-test-instrumentation-openai-v2_ubuntu-latest:
|
||||||
|
name: instrumentation-openai-v2 3.8 Ubuntu
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout repo @ SHA - ${{ github.sha }}
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Python 3.8
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.8"
|
||||||
|
|
||||||
|
- name: Install tox
|
||||||
|
run: pip install tox
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: tox -e py38-test-instrumentation-openai-v2 -- -ra
|
||||||
|
|
||||||
|
py39-test-instrumentation-openai-v2_ubuntu-latest:
|
||||||
|
name: instrumentation-openai-v2 3.9 Ubuntu
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
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
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: tox -e py39-test-instrumentation-openai-v2 -- -ra
|
||||||
|
|
||||||
|
py310-test-instrumentation-openai-v2_ubuntu-latest:
|
||||||
|
name: instrumentation-openai-v2 3.10 Ubuntu
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
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
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: tox -e py310-test-instrumentation-openai-v2 -- -ra
|
||||||
|
|
||||||
|
py311-test-instrumentation-openai-v2_ubuntu-latest:
|
||||||
|
name: instrumentation-openai-v2 3.11 Ubuntu
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
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
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: tox -e py311-test-instrumentation-openai-v2 -- -ra
|
||||||
|
|
||||||
|
py312-test-instrumentation-openai-v2_ubuntu-latest:
|
||||||
|
name: instrumentation-openai-v2 3.12 Ubuntu
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
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
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: tox -e py312-test-instrumentation-openai-v2 -- -ra
|
||||||
|
|
||||||
|
pypy3-test-instrumentation-openai-v2_ubuntu-latest:
|
||||||
|
name: instrumentation-openai-v2 pypy-3.8 Ubuntu
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout repo @ SHA - ${{ github.sha }}
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Python pypy-3.8
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "pypy-3.8"
|
||||||
|
|
||||||
|
- name: Install tox
|
||||||
|
run: pip install tox
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: tox -e pypy3-test-instrumentation-openai-v2 -- -ra
|
||||||
|
|
||||||
py38-test-resource-detector-container_ubuntu-latest:
|
py38-test-resource-detector-container_ubuntu-latest:
|
||||||
name: resource-detector-container 3.8 Ubuntu
|
name: resource-detector-container 3.8 Ubuntu
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
@ -4407,111 +4515,3 @@ jobs:
|
||||||
|
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: tox -e py311-test-instrumentation-pymemcache-2 -- -ra
|
run: tox -e py311-test-instrumentation-pymemcache-2 -- -ra
|
||||||
|
|
||||||
py311-test-instrumentation-pymemcache-3_ubuntu-latest:
|
|
||||||
name: instrumentation-pymemcache-3 3.11 Ubuntu
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
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
|
|
||||||
|
|
||||||
- name: Run tests
|
|
||||||
run: tox -e py311-test-instrumentation-pymemcache-3 -- -ra
|
|
||||||
|
|
||||||
py311-test-instrumentation-pymemcache-4_ubuntu-latest:
|
|
||||||
name: instrumentation-pymemcache-4 3.11 Ubuntu
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
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
|
|
||||||
|
|
||||||
- name: Run tests
|
|
||||||
run: tox -e py311-test-instrumentation-pymemcache-4 -- -ra
|
|
||||||
|
|
||||||
py312-test-instrumentation-pymemcache-0_ubuntu-latest:
|
|
||||||
name: instrumentation-pymemcache-0 3.12 Ubuntu
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
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
|
|
||||||
|
|
||||||
- name: Run tests
|
|
||||||
run: tox -e py312-test-instrumentation-pymemcache-0 -- -ra
|
|
||||||
|
|
||||||
py312-test-instrumentation-pymemcache-1_ubuntu-latest:
|
|
||||||
name: instrumentation-pymemcache-1 3.12 Ubuntu
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
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
|
|
||||||
|
|
||||||
- name: Run tests
|
|
||||||
run: tox -e py312-test-instrumentation-pymemcache-1 -- -ra
|
|
||||||
|
|
||||||
py312-test-instrumentation-pymemcache-2_ubuntu-latest:
|
|
||||||
name: instrumentation-pymemcache-2 3.12 Ubuntu
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
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
|
|
||||||
|
|
||||||
- name: Run tests
|
|
||||||
run: tox -e py312-test-instrumentation-pymemcache-2 -- -ra
|
|
||||||
|
|
||||||
py312-test-instrumentation-pymemcache-3_ubuntu-latest:
|
|
||||||
name: instrumentation-pymemcache-3 3.12 Ubuntu
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
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
|
|
||||||
|
|
||||||
- name: Run tests
|
|
||||||
run: tox -e py312-test-instrumentation-pymemcache-3 -- -ra
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,114 @@ env:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
|
py311-test-instrumentation-pymemcache-3_ubuntu-latest:
|
||||||
|
name: instrumentation-pymemcache-3 3.11 Ubuntu
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
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
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: tox -e py311-test-instrumentation-pymemcache-3 -- -ra
|
||||||
|
|
||||||
|
py311-test-instrumentation-pymemcache-4_ubuntu-latest:
|
||||||
|
name: instrumentation-pymemcache-4 3.11 Ubuntu
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
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
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: tox -e py311-test-instrumentation-pymemcache-4 -- -ra
|
||||||
|
|
||||||
|
py312-test-instrumentation-pymemcache-0_ubuntu-latest:
|
||||||
|
name: instrumentation-pymemcache-0 3.12 Ubuntu
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
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
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: tox -e py312-test-instrumentation-pymemcache-0 -- -ra
|
||||||
|
|
||||||
|
py312-test-instrumentation-pymemcache-1_ubuntu-latest:
|
||||||
|
name: instrumentation-pymemcache-1 3.12 Ubuntu
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
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
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: tox -e py312-test-instrumentation-pymemcache-1 -- -ra
|
||||||
|
|
||||||
|
py312-test-instrumentation-pymemcache-2_ubuntu-latest:
|
||||||
|
name: instrumentation-pymemcache-2 3.12 Ubuntu
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
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
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: tox -e py312-test-instrumentation-pymemcache-2 -- -ra
|
||||||
|
|
||||||
|
py312-test-instrumentation-pymemcache-3_ubuntu-latest:
|
||||||
|
name: instrumentation-pymemcache-3 3.12 Ubuntu
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
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
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: tox -e py312-test-instrumentation-pymemcache-3 -- -ra
|
||||||
|
|
||||||
py312-test-instrumentation-pymemcache-4_ubuntu-latest:
|
py312-test-instrumentation-pymemcache-4_ubuntu-latest:
|
||||||
name: instrumentation-pymemcache-4 3.12 Ubuntu
|
name: instrumentation-pymemcache-4 3.12 Ubuntu
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
|
||||||
66
CHANGELOG.md
66
CHANGELOG.md
|
|
@ -11,6 +11,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
## Version 1.27.0/0.49b0 ()
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- `opentelemetry-instrumentation-openai-v2` Instrumentation for OpenAI >= 0.27.0
|
||||||
|
([#2759](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2759))
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- `opentelemetry-instrumentation-fastapi` Add autoinstrumentation mechanism tests.
|
- `opentelemetry-instrumentation-fastapi` Add autoinstrumentation mechanism tests.
|
||||||
|
|
@ -236,7 +243,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
([#2420](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2420))
|
([#2420](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2420))
|
||||||
- `opentelemetry-instrumentation-elasticsearch` Disabling instrumentation with native OTel support enabled
|
- `opentelemetry-instrumentation-elasticsearch` Disabling instrumentation with native OTel support enabled
|
||||||
([#2524](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2524))
|
([#2524](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2524))
|
||||||
- `opentelemetry-instrumentation-asyncio` Check for __name__ attribute in the coroutine
|
- `opentelemetry-instrumentation-asyncio` Check for **name** attribute in the coroutine
|
||||||
([#2521](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2521))
|
([#2521](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2521))
|
||||||
- `opentelemetry-instrumentation-requests` Fix wrong time unit for duration histogram
|
- `opentelemetry-instrumentation-requests` Fix wrong time unit for duration histogram
|
||||||
([#2553](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2553))
|
([#2553](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2553))
|
||||||
|
|
@ -251,6 +258,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
([#2146](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2146))
|
([#2146](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2146))
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- `opentelemetry-instrumentation-celery` Allow Celery instrumentation to be installed multiple times
|
- `opentelemetry-instrumentation-celery` Allow Celery instrumentation to be installed multiple times
|
||||||
([#2342](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2342))
|
([#2342](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2342))
|
||||||
- Align gRPC span status codes to OTEL specification
|
- Align gRPC span status codes to OTEL specification
|
||||||
|
|
@ -268,8 +276,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- AwsLambdaInstrumentor sets `cloud.account.id` span attribute
|
- AwsLambdaInstrumentor sets `cloud.account.id` span attribute
|
||||||
([#2367](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2367))
|
([#2367](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2367))
|
||||||
|
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- `opentelemetry-instrumentation-fastapi` Add support for configuring header extraction via runtime constructor parameters
|
- `opentelemetry-instrumentation-fastapi` Add support for configuring header extraction via runtime constructor parameters
|
||||||
([#2241](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2241))
|
([#2241](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2241))
|
||||||
|
|
||||||
|
|
@ -280,7 +288,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- `opentelemetry-resource-detector-azure` Added 10s timeout to VM Resource Detector
|
- `opentelemetry-resource-detector-azure` Added 10s timeout to VM Resource Detector
|
||||||
([#2119](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2119))
|
([#2119](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2119))
|
||||||
- `opentelemetry-instrumentation-asyncpg` Allow AsyncPGInstrumentor to be instantiated multiple times
|
- `opentelemetry-instrumentation-asyncpg` Allow AsyncPGInstrumentor to be instantiated multiple times
|
||||||
([#1791](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1791))
|
([#1791](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1791))
|
||||||
- `opentelemetry-instrumentation-confluent-kafka` Add support for higher versions until 2.3.0 of confluent_kafka
|
- `opentelemetry-instrumentation-confluent-kafka` Add support for higher versions until 2.3.0 of confluent_kafka
|
||||||
([#2132](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2132))
|
([#2132](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2132))
|
||||||
- `opentelemetry-resource-detector-azure` Changed timeout to 4 seconds due to [timeout bug](https://github.com/open-telemetry/opentelemetry-python/issues/3644)
|
- `opentelemetry-resource-detector-azure` Changed timeout to 4 seconds due to [timeout bug](https://github.com/open-telemetry/opentelemetry-python/issues/3644)
|
||||||
|
|
@ -364,6 +372,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
([#152](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2013))
|
([#152](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2013))
|
||||||
|
|
||||||
## Version 1.19.0/0.40b0 (2023-07-13)
|
## Version 1.19.0/0.40b0 (2023-07-13)
|
||||||
|
|
||||||
- `opentelemetry-instrumentation-asgi` Add `http.server.request.size` metric
|
- `opentelemetry-instrumentation-asgi` Add `http.server.request.size` metric
|
||||||
([#1867](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1867))
|
([#1867](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1867))
|
||||||
|
|
||||||
|
|
@ -410,6 +419,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
([#1823](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1823))
|
([#1823](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1823))
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- `opentelemetry-instrumentation-kafka-python` Add instrumentation to `consume` method
|
- `opentelemetry-instrumentation-kafka-python` Add instrumentation to `consume` method
|
||||||
([#1786](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1786))
|
([#1786](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1786))
|
||||||
|
|
||||||
|
|
@ -460,6 +470,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
([#1692](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1692))
|
([#1692](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1692))
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Update HTTP server/client instrumentation span names to comply with spec
|
- Update HTTP server/client instrumentation span names to comply with spec
|
||||||
([#1759](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1759))
|
([#1759](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1759))
|
||||||
|
|
||||||
|
|
@ -497,7 +508,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Support `aio_pika` 9.x (([#1670](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1670])
|
- Support `aio_pika` 9.x (([#1670](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1670])
|
||||||
- `opentelemetry-instrumentation-redis` Add `sanitize_query` config option to allow query sanitization. ([#1572](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1572))
|
- `opentelemetry-instrumentation-redis` Add `sanitize_query` config option to allow query sanitization. ([#1572](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1572))
|
||||||
- `opentelemetry-instrumentation-elasticsearch` Add optional db.statement query sanitization.
|
- `opentelemetry-instrumentation-elasticsearch` Add optional db.statement query sanitization.
|
||||||
([#1598](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1598))
|
([#1598](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1598))
|
||||||
- `opentelemetry-instrumentation-celery` Record exceptions as events on the span.
|
- `opentelemetry-instrumentation-celery` Record exceptions as events on the span.
|
||||||
|
|
@ -521,7 +532,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
([#1575](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1575))
|
([#1575](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1575))
|
||||||
- Fix SQLAlchemy uninstrumentation
|
- Fix SQLAlchemy uninstrumentation
|
||||||
([#1581](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1581))
|
([#1581](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1581))
|
||||||
- `opentelemetry-instrumentation-grpc` Fix code()/details() of _OpentelemetryServicerContext.
|
- `opentelemetry-instrumentation-grpc` Fix code()/details() of \_OpentelemetryServicerContext.
|
||||||
([#1578](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1578))
|
([#1578](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1578))
|
||||||
- Fix aiopg instrumentation to work with aiopg < 2.0.0
|
- Fix aiopg instrumentation to work with aiopg < 2.0.0
|
||||||
([#1473](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1473))
|
([#1473](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1473))
|
||||||
|
|
@ -573,7 +584,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
([#1430](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1430))
|
([#1430](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1430))
|
||||||
- `opentelemetry-instrumentation-aiohttp-client` Allow overriding of status in response hook.
|
- `opentelemetry-instrumentation-aiohttp-client` Allow overriding of status in response hook.
|
||||||
([#1394](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1394))
|
([#1394](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1394))
|
||||||
- `opentelemetry-instrumentation-pymysql` Fix dbapi connection instrument wrapper has no _sock member.
|
- `opentelemetry-instrumentation-pymysql` Fix dbapi connection instrument wrapper has no \_sock member.
|
||||||
([#1424](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1424))
|
([#1424](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1424))
|
||||||
- `opentelemetry-instrumentation-dbapi` Fix the check for the connection already being instrumented in instrument_connection().
|
- `opentelemetry-instrumentation-dbapi` Fix the check for the connection already being instrumented in instrument_connection().
|
||||||
([#1424](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1424))
|
([#1424](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1424))
|
||||||
|
|
@ -658,7 +669,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- Add metric instrumentation in starlette
|
- Add metric instrumentation in starlette
|
||||||
([#1327](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1327))
|
([#1327](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1327))
|
||||||
|
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- `opentelemetry-instrumentation-kafka-python`: wait for metadata
|
- `opentelemetry-instrumentation-kafka-python`: wait for metadata
|
||||||
|
|
@ -671,7 +681,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
([#1208](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1208))
|
([#1208](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1208))
|
||||||
- `opentelemetry-instrumentation-aiohttp-client` Fix producing additional spans with each newly created ClientSession
|
- `opentelemetry-instrumentation-aiohttp-client` Fix producing additional spans with each newly created ClientSession
|
||||||
- ([#1246](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1246))
|
- ([#1246](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1246))
|
||||||
- Add _is_opentelemetry_instrumented check in _InstrumentedFastAPI class
|
- Add \_is_opentelemetry_instrumented check in \_InstrumentedFastAPI class
|
||||||
([#1313](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1313))
|
([#1313](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1313))
|
||||||
- Fix uninstrumentation of existing app instances in FastAPI
|
- Fix uninstrumentation of existing app instances in FastAPI
|
||||||
([#1258](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1258))
|
([#1258](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1258))
|
||||||
|
|
@ -690,6 +700,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
([#1203](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1203))
|
([#1203](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1203))
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- `opentelemetry-instrumentation-redis` add support to instrument RedisCluster clients
|
- `opentelemetry-instrumentation-redis` add support to instrument RedisCluster clients
|
||||||
([#1177](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1177))
|
([#1177](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1177))
|
||||||
- `opentelemetry-instrumentation-sqlalchemy` Added span for the connection phase ([#1133](https://github.com/open-telemetry/opentelemetry-python-contrib/issues/1133))
|
- `opentelemetry-instrumentation-sqlalchemy` Added span for the connection phase ([#1133](https://github.com/open-telemetry/opentelemetry-python-contrib/issues/1133))
|
||||||
|
|
@ -702,11 +713,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
## [1.12.0rc2-0.32b0](https://github.com/open-telemetry/opentelemetry-python/releases/tag/v1.12.0rc2-0.32b0) - 2022-07-01
|
## [1.12.0rc2-0.32b0](https://github.com/open-telemetry/opentelemetry-python/releases/tag/v1.12.0rc2-0.32b0) - 2022-07-01
|
||||||
|
|
||||||
|
|
||||||
- Pyramid: Only categorize 500s server exceptions as errors
|
- Pyramid: Only categorize 500s server exceptions as errors
|
||||||
([#1037](https://github.com/open-telemetry/opentelemetry-python-contrib/issues/1037))
|
([#1037](https://github.com/open-telemetry/opentelemetry-python-contrib/issues/1037))
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fix bug in system metrics by checking their configuration
|
- Fix bug in system metrics by checking their configuration
|
||||||
([#1129](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1129))
|
([#1129](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1129))
|
||||||
- Adding escape call to fix [auto-instrumentation not producing spans on Windows](https://github.com/open-telemetry/opentelemetry-python/issues/2703).
|
- Adding escape call to fix [auto-instrumentation not producing spans on Windows](https://github.com/open-telemetry/opentelemetry-python/issues/2703).
|
||||||
|
|
@ -719,8 +730,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- fixed typo in `system.network.io` metric configuration
|
- fixed typo in `system.network.io` metric configuration
|
||||||
([#1135](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1135))
|
([#1135](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1135))
|
||||||
|
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- `opentelemetry-instrumentation-aiohttp-client` Add support for optional custom trace_configs argument.
|
- `opentelemetry-instrumentation-aiohttp-client` Add support for optional custom trace_configs argument.
|
||||||
([1079](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1079))
|
([1079](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1079))
|
||||||
- `opentelemetry-instrumentation-sqlalchemy` add support to instrument multiple engines
|
- `opentelemetry-instrumentation-sqlalchemy` add support to instrument multiple engines
|
||||||
|
|
@ -744,10 +755,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- Integrated sqlcommenter plugin into opentelemetry-instrumentation-django
|
- Integrated sqlcommenter plugin into opentelemetry-instrumentation-django
|
||||||
([#896](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/896))
|
([#896](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/896))
|
||||||
|
|
||||||
|
|
||||||
## Version 1.12.0rc1/0.31b0 (2022-05-17)
|
## Version 1.12.0rc1/0.31b0 (2022-05-17)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- `opentelemetry-instrumentation-aiohttp-client` make span attributes available to sampler
|
- `opentelemetry-instrumentation-aiohttp-client` make span attributes available to sampler
|
||||||
([#1072](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1072))
|
([#1072](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1072))
|
||||||
- `opentelemetry-instrumentation-aws-lambda` Fixed an issue - in some rare cases (API GW proxy integration test)
|
- `opentelemetry-instrumentation-aws-lambda` Fixed an issue - in some rare cases (API GW proxy integration test)
|
||||||
|
|
@ -760,6 +771,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- `opentelemetry-sdk-extension-aws` change timeout for AWS EC2 and EKS metadata requests from 1000 seconds and 2000 seconds to 1 second
|
- `opentelemetry-sdk-extension-aws` change timeout for AWS EC2 and EKS metadata requests from 1000 seconds and 2000 seconds to 1 second
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- `opentelemetry-instrument` and `opentelemetry-bootstrap` now include a `--version` flag
|
- `opentelemetry-instrument` and `opentelemetry-bootstrap` now include a `--version` flag
|
||||||
([#1065](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1065))
|
([#1065](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1065))
|
||||||
- `opentelemetry-instrumentation-redis` now instruments asynchronous Redis clients, if the installed redis-py includes async support (>=4.2.0).
|
- `opentelemetry-instrumentation-redis` now instruments asynchronous Redis clients, if the installed redis-py includes async support (>=4.2.0).
|
||||||
|
|
@ -767,22 +779,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- `opentelemetry-instrumentation-boto3sqs` added AWS's SQS instrumentation.
|
- `opentelemetry-instrumentation-boto3sqs` added AWS's SQS instrumentation.
|
||||||
([#1081](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1081))
|
([#1081](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1081))
|
||||||
|
|
||||||
|
|
||||||
## Version 1.11.1/0.30b1 (2022-04-21)
|
## Version 1.11.1/0.30b1 (2022-04-21)
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- `opentelemetry-instrumentation-starlette` Capture custom request/response headers in span attributes
|
- `opentelemetry-instrumentation-starlette` Capture custom request/response headers in span attributes
|
||||||
([#1046](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1046))
|
([#1046](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1046))
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Prune autoinstrumentation sitecustomize module directory from PYTHONPATH immediately
|
- Prune autoinstrumentation sitecustomize module directory from PYTHONPATH immediately
|
||||||
([#1066](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1066))
|
([#1066](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1066))
|
||||||
|
|
||||||
|
|
||||||
## Version 1.11.0/0.30b0 (2022-04-18)
|
## Version 1.11.0/0.30b0 (2022-04-18)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- `opentelemetry-instrumentation-pyramid` Fixed which package is the correct caller in _traced_init.
|
|
||||||
|
- `opentelemetry-instrumentation-pyramid` Fixed which package is the correct caller in \_traced_init.
|
||||||
([#830](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/830))
|
([#830](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/830))
|
||||||
- `opentelemetry-instrumentation-tornado` Fix Tornado errors mapping to 500
|
- `opentelemetry-instrumentation-tornado` Fix Tornado errors mapping to 500
|
||||||
([#1048](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1048))
|
([#1048](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1048))
|
||||||
|
|
@ -816,7 +829,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- `opentelemetry-instrumentation-pyramid` Pyramid: Capture custom request/response headers in span attributes
|
- `opentelemetry-instrumentation-pyramid` Pyramid: Capture custom request/response headers in span attributes
|
||||||
([#1022](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1022))
|
([#1022](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1022))
|
||||||
|
|
||||||
|
|
||||||
## Version 1.10.0/0.29b0 (2022-03-10)
|
## Version 1.10.0/0.29b0 (2022-03-10)
|
||||||
|
|
||||||
- `opentelemetry-instrumentation-wsgi` Capture custom request/response headers in span attributes
|
- `opentelemetry-instrumentation-wsgi` Capture custom request/response headers in span attributes
|
||||||
|
|
@ -830,7 +842,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
- `opentelemetry-instrumentation-aws-lambda` `SpanKind.SERVER` by default, add more cases for `SpanKind.CONSUMER` services. ([#926](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/926))
|
- `opentelemetry-instrumentation-aws-lambda` `SpanKind.SERVER` by default, add more cases for `SpanKind.CONSUMER` services. ([#926](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/926))
|
||||||
- `opentelemetry-instrumentation-sqlalchemy` added experimental sql commenter capability
|
- `opentelemetry-instrumentation-sqlalchemy` added experimental sql commenter capability
|
||||||
([#924](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/924))
|
([#924](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/924))
|
||||||
- `opentelemetry-contrib-instrumentations` added new meta-package that installs all contrib instrumentations.
|
- `opentelemetry-contrib-instrumentations` added new meta-package that installs all contrib instrumentations.
|
||||||
([#681](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/681))
|
([#681](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/681))
|
||||||
- `opentelemetry-instrumentation-dbapi` add experimental sql commenter capability
|
- `opentelemetry-instrumentation-dbapi` add experimental sql commenter capability
|
||||||
|
|
@ -869,12 +881,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
## Version 1.9.0/0.28b0 (2022-01-26)
|
## Version 1.9.0/0.28b0 (2022-01-26)
|
||||||
|
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- `opentelemetry-instrumentation-pyramid` Pyramid: Conditionally create SERVER spans
|
- `opentelemetry-instrumentation-pyramid` Pyramid: Conditionally create SERVER spans
|
||||||
([#869](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/869))
|
([#869](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/869))
|
||||||
- `opentelemetry-instrumentation-grpc` added `trailing_metadata` to _OpenTelemetryServicerContext.
|
- `opentelemetry-instrumentation-grpc` added `trailing_metadata` to \_OpenTelemetryServicerContext.
|
||||||
([#871](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/871))
|
([#871](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/871))
|
||||||
- `opentelemetry-instrumentation-asgi` now returns a `traceresponse` response header.
|
- `opentelemetry-instrumentation-asgi` now returns a `traceresponse` response header.
|
||||||
([#817](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/817))
|
([#817](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/817))
|
||||||
|
|
@ -908,12 +919,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- `opentelemetry-instrumentation-aiohttp-client` aiohttp: Remove `span_name` from docs
|
- `opentelemetry-instrumentation-aiohttp-client` aiohttp: Remove `span_name` from docs
|
||||||
([#857](https://github.com/open-telemetry/opentelemetry-python-contrib/issues/857))
|
([#857](https://github.com/open-telemetry/opentelemetry-python-contrib/issues/857))
|
||||||
|
|
||||||
|
|
||||||
## Version 1.8.0/0.27b0 (2021-12-17)
|
## Version 1.8.0/0.27b0 (2021-12-17)
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- `opentelemetry-instrumentation-aws-lambda` Adds support for configurable flush timeout via `OTEL_INSTRUMENTATION_AWS_LAMBDA_FLUSH_TIMEOUT` property. ([#825](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/825))
|
- `opentelemetry-instrumentation-aws-lambda` Adds support for configurable flush timeout via `OTEL_INSTRUMENTATION_AWS_LAMBDA_FLUSH_TIMEOUT` property. ([#825](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/825))
|
||||||
- `opentelemetry-instrumentation-pika` Adds support for versions between `0.12.0` to `1.0.0`. ([#837](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/837))
|
- `opentelemetry-instrumentation-pika` Adds support for versions between `0.12.0` to `1.0.0`. ([#837](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/837))
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
@ -983,13 +993,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
([#755](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/755))
|
([#755](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/755))
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- `opentelemetry-instrumentation-pika` Add `publish_hook` and `consume_hook` callbacks passed as arguments to the instrument method
|
- `opentelemetry-instrumentation-pika` Add `publish_hook` and `consume_hook` callbacks passed as arguments to the instrument method
|
||||||
([#763](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/763))
|
([#763](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/763))
|
||||||
|
|
||||||
|
|
||||||
## Version 1.6.1/0.25b1 (2021-10-18)
|
## Version 1.6.1/0.25b1 (2021-10-18)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- `opentelemetry-util-http` no longer contains an instrumentation entrypoint and will not be loaded
|
- `opentelemetry-util-http` no longer contains an instrumentation entrypoint and will not be loaded
|
||||||
automatically by the auto instrumentor.
|
automatically by the auto instrumentor.
|
||||||
([#745](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/745))
|
([#745](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/745))
|
||||||
|
|
@ -1003,7 +1014,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
([#760](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/760))
|
([#760](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/760))
|
||||||
|
|
||||||
## Version 1.6.0/0.25b0 (2021-10-13)
|
## Version 1.6.0/0.25b0 (2021-10-13)
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- `opentelemetry-sdk-extension-aws` Release AWS Python SDK Extension as 1.0.0
|
- `opentelemetry-sdk-extension-aws` Release AWS Python SDK Extension as 1.0.0
|
||||||
([#667](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/667))
|
([#667](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/667))
|
||||||
- `opentelemetry-instrumentation-urllib3`, `opentelemetry-instrumentation-requests`
|
- `opentelemetry-instrumentation-urllib3`, `opentelemetry-instrumentation-requests`
|
||||||
|
|
@ -1030,6 +1043,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
([#391](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/391))
|
([#391](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/391))
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- `opentelemetry-instrumentation-flask` Fix `RuntimeError: Working outside of request context`
|
- `opentelemetry-instrumentation-flask` Fix `RuntimeError: Working outside of request context`
|
||||||
([#734](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/734))
|
([#734](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/734))
|
||||||
- `opentelemetry-propagators-aws-xray` Rename `AwsXRayFormat` to `AwsXRayPropagator`
|
- `opentelemetry-propagators-aws-xray` Rename `AwsXRayFormat` to `AwsXRayPropagator`
|
||||||
|
|
@ -1060,6 +1074,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
## Version 1.5.0/0.24b0 (2021-08-26)
|
## Version 1.5.0/0.24b0 (2021-08-26)
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- `opentelemetry-sdk-extension-aws` Add AWS resource detectors to extension package
|
- `opentelemetry-sdk-extension-aws` Add AWS resource detectors to extension package
|
||||||
([#586](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/586))
|
([#586](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/586))
|
||||||
- `opentelemetry-instrumentation-asgi`, `opentelemetry-instrumentation-aiohttp-client`, `openetelemetry-instrumentation-fastapi`,
|
- `opentelemetry-instrumentation-asgi`, `opentelemetry-instrumentation-aiohttp-client`, `openetelemetry-instrumentation-fastapi`,
|
||||||
|
|
@ -1078,10 +1093,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
## Version 1.4.0/0.23b0 (2021-07-21)
|
## Version 1.4.0/0.23b0 (2021-07-21)
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
- Move `opentelemetry-instrumentation` to the core repo.
|
- Move `opentelemetry-instrumentation` to the core repo.
|
||||||
([#595](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/595))
|
([#595](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/595))
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- `opentelemetry-instrumentation-falcon` added support for Falcon 3.
|
- `opentelemetry-instrumentation-falcon` added support for Falcon 3.
|
||||||
([#607](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/607))
|
([#607](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/607))
|
||||||
- `opentelemetry-instrumentation-tornado` properly instrument work done in tornado on_finish method.
|
- `opentelemetry-instrumentation-tornado` properly instrument work done in tornado on_finish method.
|
||||||
|
|
@ -1129,12 +1146,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
([#568](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/568))
|
([#568](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/568))
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- `opentelemetry-instrumentation-httpx` Add `httpx` instrumentation
|
- `opentelemetry-instrumentation-httpx` Add `httpx` instrumentation
|
||||||
([#461](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/461))
|
([#461](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/461))
|
||||||
|
|
||||||
## Version 1.3.0/0.22b0 (2021-06-01)
|
## Version 1.3.0/0.22b0 (2021-06-01)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- `opentelemetry-bootstrap` not longer forcibly removes and re-installs libraries and their instrumentations.
|
- `opentelemetry-bootstrap` not longer forcibly removes and re-installs libraries and their instrumentations.
|
||||||
This means running bootstrap will not auto-upgrade existing dependencies and as a result not cause dependency
|
This means running bootstrap will not auto-upgrade existing dependencies and as a result not cause dependency
|
||||||
conflicts.
|
conflicts.
|
||||||
|
|
@ -1151,6 +1170,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
([#488](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/488))
|
([#488](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/488))
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- `opentelemetry-instrumentation-botocore` now supports
|
- `opentelemetry-instrumentation-botocore` now supports
|
||||||
context propagation for lambda invoke via Payload embedded headers.
|
context propagation for lambda invoke via Payload embedded headers.
|
||||||
([#458](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/458))
|
([#458](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/458))
|
||||||
|
|
@ -1160,6 +1180,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
## Version 1.2.0/0.21b0 (2021-05-11)
|
## Version 1.2.0/0.21b0 (2021-05-11)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Instrumentation packages don't specify the libraries they instrument as dependencies
|
- Instrumentation packages don't specify the libraries they instrument as dependencies
|
||||||
anymore. Instead, they verify the correct version of libraries are installed at runtime.
|
anymore. Instead, they verify the correct version of libraries are installed at runtime.
|
||||||
([#475](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/475))
|
([#475](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/475))
|
||||||
|
|
@ -1711,6 +1732,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- `opentelemetry-ext-http-requests` Updates for core library changes
|
- `opentelemetry-ext-http-requests` Updates for core library changes
|
||||||
|
|
||||||
- `Added support for PyPy3` Initial release
|
- `Added support for PyPy3` Initial release
|
||||||
|
|
||||||
## [#1033](https://github.com/open-telemetryopentelemetry-python-contrib/issues/1033)
|
## [#1033](https://github.com/open-telemetryopentelemetry-python-contrib/issues/1033)
|
||||||
|
|
||||||
## Version 0.1a0 (2019-09-30)
|
## Version 0.1a0 (2019-09-30)
|
||||||
|
|
@ -1725,7 +1747,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- `opentelemetry-resource-detector-azure` Added 10s timeout to VM Resource Detector
|
- `opentelemetry-resource-detector-azure` Added 10s timeout to VM Resource Detector
|
||||||
([#2119](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2119))
|
([#2119](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2119))
|
||||||
- `opentelemetry-instrumentation-asyncpg` Allow AsyncPGInstrumentor to be instantiated multiple times
|
- `opentelemetry-instrumentation-asyncpg` Allow AsyncPGInstrumentor to be instantiated multiple times
|
||||||
([#1791](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1791))
|
([#1791](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1791))
|
||||||
- `opentelemetry-instrumentation-confluent-kafka` Add support for higher versions until 2.3.0 of confluent_kafka
|
- `opentelemetry-instrumentation-confluent-kafka` Add support for higher versions until 2.3.0 of confluent_kafka
|
||||||
([#2132](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2132))
|
([#2132](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2132))
|
||||||
- `opentelemetry-resource-detector-azure` Changed timeout to 4 seconds due to [timeout bug](https://github.com/open-telemetry/opentelemetry-python/issues/3644)
|
- `opentelemetry-resource-detector-azure` Changed timeout to 4 seconds due to [timeout bug](https://github.com/open-telemetry/opentelemetry-python/issues/3644)
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@ packages=
|
||||||
opentelemetry-resource-detector-azure
|
opentelemetry-resource-detector-azure
|
||||||
opentelemetry-sdk-extension-aws
|
opentelemetry-sdk-extension-aws
|
||||||
opentelemetry-propagator-aws-xray
|
opentelemetry-propagator-aws-xray
|
||||||
|
opentelemetry-instrumentation-openai-v2
|
||||||
opentelemetry-instrumentation-test
|
opentelemetry-instrumentation-test
|
||||||
|
|
||||||
[lintroots]
|
[lintroots]
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@
|
||||||
| [opentelemetry-instrumentation-logging](./opentelemetry-instrumentation-logging) | logging | No | experimental
|
| [opentelemetry-instrumentation-logging](./opentelemetry-instrumentation-logging) | logging | No | experimental
|
||||||
| [opentelemetry-instrumentation-mysql](./opentelemetry-instrumentation-mysql) | mysql-connector-python >= 8.0, < 10.0 | No | experimental
|
| [opentelemetry-instrumentation-mysql](./opentelemetry-instrumentation-mysql) | mysql-connector-python >= 8.0, < 10.0 | No | experimental
|
||||||
| [opentelemetry-instrumentation-mysqlclient](./opentelemetry-instrumentation-mysqlclient) | mysqlclient < 3 | No | experimental
|
| [opentelemetry-instrumentation-mysqlclient](./opentelemetry-instrumentation-mysqlclient) | mysqlclient < 3 | No | experimental
|
||||||
|
| [opentelemetry-instrumentation-openai-v2](./opentelemetry-instrumentation-openai-v2) | openai >= 1.26.0 | No | experimental
|
||||||
| [opentelemetry-instrumentation-pika](./opentelemetry-instrumentation-pika) | pika >= 0.12.0 | No | experimental
|
| [opentelemetry-instrumentation-pika](./opentelemetry-instrumentation-pika) | pika >= 0.12.0 | No | experimental
|
||||||
| [opentelemetry-instrumentation-psycopg](./opentelemetry-instrumentation-psycopg) | psycopg >= 3.1.0 | No | experimental
|
| [opentelemetry-instrumentation-psycopg](./opentelemetry-instrumentation-psycopg) | psycopg >= 3.1.0 | No | experimental
|
||||||
| [opentelemetry-instrumentation-psycopg2](./opentelemetry-instrumentation-psycopg2) | psycopg2 >= 2.7.3.1 | No | experimental
|
| [opentelemetry-instrumentation-psycopg2](./opentelemetry-instrumentation-psycopg2) | psycopg2 >= 2.7.3.1 | No | experimental
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,201 @@
|
||||||
|
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.
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
OpenTelemetry OpenAI Instrumentation
|
||||||
|
====================================
|
||||||
|
|
||||||
|
|pypi|
|
||||||
|
|
||||||
|
.. |pypi| image:: https://badge.fury.io/py/opentelemetry-instrumentation-openai-v2.svg
|
||||||
|
:target: https://pypi.org/project/opentelemetry-instrumentation-openai-v2/
|
||||||
|
|
||||||
|
Instrumentation with OpenAI that supports the openai library and is
|
||||||
|
specified to trace_integration using 'OpenAI'.
|
||||||
|
|
||||||
|
|
||||||
|
Installation
|
||||||
|
------------
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
pip install opentelemetry-instrumentation-openai-v2
|
||||||
|
|
||||||
|
|
||||||
|
References
|
||||||
|
----------
|
||||||
|
* `OpenTelemetry OpenAI Instrumentation <https://opentelemetry-python-contrib.readthedocs.io/en/latest/instrumentation/openai/openai.html>`_
|
||||||
|
* `OpenTelemetry Project <https://opentelemetry.io/>`_
|
||||||
|
* `OpenTelemetry Python Examples <https://github.com/open-telemetry/opentelemetry-python/tree/main/docs/examples>`_
|
||||||
|
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
[build-system]
|
||||||
|
requires = ["hatchling"]
|
||||||
|
build-backend = "hatchling.build"
|
||||||
|
|
||||||
|
[project]
|
||||||
|
name = "opentelemetry-instrumentation-openai-v2"
|
||||||
|
dynamic = ["version"]
|
||||||
|
description = "OpenTelemetry Official OpenAI instrumentation"
|
||||||
|
readme = "README.rst"
|
||||||
|
license = "Apache-2.0"
|
||||||
|
requires-python = ">=3.8"
|
||||||
|
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.8",
|
||||||
|
"Programming Language :: Python :: 3.9",
|
||||||
|
"Programming Language :: Python :: 3.10",
|
||||||
|
"Programming Language :: Python :: 3.11",
|
||||||
|
"Programming Language :: Python :: 3.12",
|
||||||
|
]
|
||||||
|
dependencies = [
|
||||||
|
"opentelemetry-api ~= 1.12",
|
||||||
|
"opentelemetry-instrumentation ~= 0.48b0",
|
||||||
|
"opentelemetry-semantic-conventions ~= 0.48b0"
|
||||||
|
]
|
||||||
|
|
||||||
|
[project.optional-dependencies]
|
||||||
|
instruments = [
|
||||||
|
"openai >= 1.0.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[project.entry-points.opentelemetry_instrumentor]
|
||||||
|
openai = "opentelemetry.instrumentation.openai_v2:OpenAIInstrumentor"
|
||||||
|
|
||||||
|
[project.urls]
|
||||||
|
Homepage = "https://github.com/open-telemetry/opentelemetry-python-contrib/tree/main/instrumentation/opentelemetry-instrumentation-openai-v2"
|
||||||
|
|
||||||
|
[tool.hatch.version]
|
||||||
|
path = "src/opentelemetry/instrumentation/openai_v2/version.py"
|
||||||
|
|
||||||
|
[tool.hatch.build.targets.sdist]
|
||||||
|
include = [
|
||||||
|
"/src",
|
||||||
|
"/tests",
|
||||||
|
]
|
||||||
|
|
||||||
|
[tool.hatch.build.targets.wheel]
|
||||||
|
packages = ["src/opentelemetry"]
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
"""
|
||||||
|
OpenAI client instrumentation supporting `openai`, it can be enabled by
|
||||||
|
using ``OpenAIInstrumentor``.
|
||||||
|
|
||||||
|
.. _openai: https://pypi.org/project/openai/
|
||||||
|
|
||||||
|
Usage
|
||||||
|
-----
|
||||||
|
|
||||||
|
.. code:: python
|
||||||
|
|
||||||
|
from openai import OpenAI
|
||||||
|
from opentelemetry.instrumentation.openai import OpenAIInstrumentor
|
||||||
|
|
||||||
|
OpenAIInstrumentor().instrument()
|
||||||
|
|
||||||
|
client = OpenAI()
|
||||||
|
response = client.chat.completions.create(
|
||||||
|
model="gpt-4o-mini",
|
||||||
|
messages=[
|
||||||
|
{"role": "user", "content": "Write a short poem on open telemetry."},
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
API
|
||||||
|
---
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
from typing import Collection
|
||||||
|
|
||||||
|
from wrapt import wrap_function_wrapper
|
||||||
|
|
||||||
|
from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
|
||||||
|
from opentelemetry.instrumentation.openai_v2.package import _instruments
|
||||||
|
from opentelemetry.instrumentation.utils import unwrap
|
||||||
|
from opentelemetry.semconv.schemas import Schemas
|
||||||
|
from opentelemetry.trace import get_tracer
|
||||||
|
|
||||||
|
from .patch import chat_completions_create
|
||||||
|
|
||||||
|
|
||||||
|
class OpenAIInstrumentor(BaseInstrumentor):
|
||||||
|
|
||||||
|
def instrumentation_dependencies(self) -> Collection[str]:
|
||||||
|
return _instruments
|
||||||
|
|
||||||
|
def _instrument(self, **kwargs):
|
||||||
|
"""Enable OpenAI instrumentation."""
|
||||||
|
tracer_provider = kwargs.get("tracer_provider")
|
||||||
|
tracer = get_tracer(
|
||||||
|
__name__,
|
||||||
|
"",
|
||||||
|
tracer_provider,
|
||||||
|
schema_url=Schemas.V1_27_0.value,
|
||||||
|
)
|
||||||
|
wrap_function_wrapper(
|
||||||
|
module="openai.resources.chat.completions",
|
||||||
|
name="Completions.create",
|
||||||
|
wrapper=chat_completions_create(tracer),
|
||||||
|
)
|
||||||
|
|
||||||
|
def _uninstrument(self, **kwargs):
|
||||||
|
import openai
|
||||||
|
|
||||||
|
unwrap(openai.resources.chat.completions.Completions, "create")
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
|
||||||
|
_instruments = ("openai >= 1.26.0",)
|
||||||
|
|
@ -0,0 +1,316 @@
|
||||||
|
# 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
|
||||||
|
|
||||||
|
from opentelemetry.semconv._incubating.attributes import (
|
||||||
|
gen_ai_attributes as GenAIAttributes,
|
||||||
|
)
|
||||||
|
from opentelemetry.semconv.attributes import (
|
||||||
|
error_attributes as ErrorAttributes,
|
||||||
|
)
|
||||||
|
from opentelemetry.trace import Span, SpanKind, Tracer
|
||||||
|
from opentelemetry.trace.status import Status, StatusCode
|
||||||
|
|
||||||
|
from .utils import (
|
||||||
|
extract_content,
|
||||||
|
extract_tools_prompt,
|
||||||
|
get_llm_request_attributes,
|
||||||
|
is_streaming,
|
||||||
|
set_event_completion,
|
||||||
|
set_event_prompt,
|
||||||
|
set_span_attribute,
|
||||||
|
silently_fail,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def chat_completions_create(tracer: Tracer):
|
||||||
|
"""Wrap the `create` method of the `ChatCompletion` class to trace it."""
|
||||||
|
|
||||||
|
def traced_method(wrapped, instance, args, kwargs):
|
||||||
|
|
||||||
|
llm_prompts = []
|
||||||
|
|
||||||
|
for item in kwargs.get("messages", []):
|
||||||
|
tools_prompt = extract_tools_prompt(item)
|
||||||
|
llm_prompts.append(tools_prompt if tools_prompt else item)
|
||||||
|
|
||||||
|
span_attributes = {**get_llm_request_attributes(kwargs)}
|
||||||
|
span_name = f"{span_attributes[GenAIAttributes.GEN_AI_OPERATION_NAME]} {span_attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL]}"
|
||||||
|
|
||||||
|
span = tracer.start_span(
|
||||||
|
name=span_name, kind=SpanKind.CLIENT, attributes=span_attributes
|
||||||
|
)
|
||||||
|
if span.is_recording():
|
||||||
|
_set_input_attributes(span, span_attributes)
|
||||||
|
set_event_prompt(span, json.dumps(llm_prompts))
|
||||||
|
|
||||||
|
try:
|
||||||
|
result = wrapped(*args, **kwargs)
|
||||||
|
if is_streaming(kwargs):
|
||||||
|
return StreamWrapper(
|
||||||
|
result,
|
||||||
|
span,
|
||||||
|
function_call=kwargs.get("functions") is not None,
|
||||||
|
tool_calls=kwargs.get("tools") is not None,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
if span.is_recording():
|
||||||
|
_set_response_attributes(span, result)
|
||||||
|
span.end()
|
||||||
|
return result
|
||||||
|
|
||||||
|
except Exception as error:
|
||||||
|
span.set_status(Status(StatusCode.ERROR, str(error)))
|
||||||
|
if span.is_recording():
|
||||||
|
span.set_attribute(
|
||||||
|
ErrorAttributes.ERROR_TYPE, type(error).__qualname__
|
||||||
|
)
|
||||||
|
span.end()
|
||||||
|
raise
|
||||||
|
|
||||||
|
return traced_method
|
||||||
|
|
||||||
|
|
||||||
|
@silently_fail
|
||||||
|
def _set_input_attributes(span, attributes):
|
||||||
|
for field, value in attributes.items():
|
||||||
|
set_span_attribute(span, field, value)
|
||||||
|
|
||||||
|
|
||||||
|
@silently_fail
|
||||||
|
def _set_response_attributes(span, result):
|
||||||
|
set_span_attribute(
|
||||||
|
span, GenAIAttributes.GEN_AI_RESPONSE_MODEL, result.model
|
||||||
|
)
|
||||||
|
if getattr(result, "choices", None):
|
||||||
|
choices = result.choices
|
||||||
|
responses = [
|
||||||
|
{
|
||||||
|
"role": (
|
||||||
|
choice.message.role
|
||||||
|
if choice.message and choice.message.role
|
||||||
|
else "assistant"
|
||||||
|
),
|
||||||
|
"content": extract_content(choice),
|
||||||
|
**(
|
||||||
|
{
|
||||||
|
"content_filter_results": choice[
|
||||||
|
"content_filter_results"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
if "content_filter_results" in choice
|
||||||
|
else {}
|
||||||
|
),
|
||||||
|
}
|
||||||
|
for choice in choices
|
||||||
|
]
|
||||||
|
finish_reasons = []
|
||||||
|
for choice in choices:
|
||||||
|
finish_reasons.append(choice.finish_reason or "error")
|
||||||
|
|
||||||
|
set_span_attribute(
|
||||||
|
span,
|
||||||
|
GenAIAttributes.GEN_AI_RESPONSE_FINISH_REASONS,
|
||||||
|
finish_reasons,
|
||||||
|
)
|
||||||
|
set_event_completion(span, responses)
|
||||||
|
|
||||||
|
if getattr(result, "id", None):
|
||||||
|
set_span_attribute(span, GenAIAttributes.GEN_AI_RESPONSE_ID, result.id)
|
||||||
|
|
||||||
|
# Get the usage
|
||||||
|
if getattr(result, "usage", None):
|
||||||
|
set_span_attribute(
|
||||||
|
span,
|
||||||
|
GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS,
|
||||||
|
result.usage.prompt_tokens,
|
||||||
|
)
|
||||||
|
set_span_attribute(
|
||||||
|
span,
|
||||||
|
GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS,
|
||||||
|
result.usage.completion_tokens,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class StreamWrapper:
|
||||||
|
span: Span
|
||||||
|
response_id: str = ""
|
||||||
|
response_model: str = ""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
stream,
|
||||||
|
span,
|
||||||
|
prompt_tokens=0,
|
||||||
|
function_call=False,
|
||||||
|
tool_calls=False,
|
||||||
|
):
|
||||||
|
self.stream = stream
|
||||||
|
self.span = span
|
||||||
|
self.prompt_tokens = prompt_tokens
|
||||||
|
self.function_call = function_call
|
||||||
|
self.tool_calls = tool_calls
|
||||||
|
self.result_content = []
|
||||||
|
self.completion_tokens = 0
|
||||||
|
self._span_started = False
|
||||||
|
self.setup()
|
||||||
|
|
||||||
|
def setup(self):
|
||||||
|
if not self._span_started:
|
||||||
|
self._span_started = True
|
||||||
|
|
||||||
|
def cleanup(self):
|
||||||
|
if self._span_started:
|
||||||
|
if self.response_model:
|
||||||
|
set_span_attribute(
|
||||||
|
self.span,
|
||||||
|
GenAIAttributes.GEN_AI_RESPONSE_MODEL,
|
||||||
|
self.response_model,
|
||||||
|
)
|
||||||
|
|
||||||
|
if self.response_id:
|
||||||
|
set_span_attribute(
|
||||||
|
self.span,
|
||||||
|
GenAIAttributes.GEN_AI_RESPONSE_ID,
|
||||||
|
self.response_id,
|
||||||
|
)
|
||||||
|
|
||||||
|
set_span_attribute(
|
||||||
|
self.span,
|
||||||
|
GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS,
|
||||||
|
self.prompt_tokens,
|
||||||
|
)
|
||||||
|
set_span_attribute(
|
||||||
|
self.span,
|
||||||
|
GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS,
|
||||||
|
self.completion_tokens,
|
||||||
|
)
|
||||||
|
set_event_completion(
|
||||||
|
self.span,
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"role": "assistant",
|
||||||
|
"content": "".join(self.result_content),
|
||||||
|
}
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
self.span.end()
|
||||||
|
self._span_started = False
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
self.setup()
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||||
|
try:
|
||||||
|
if exc_type is not None:
|
||||||
|
self.span.set_status(Status(StatusCode.ERROR, str(exc_val)))
|
||||||
|
self.span.set_attribute(
|
||||||
|
ErrorAttributes.ERROR_TYPE, exc_type.__qualname__
|
||||||
|
)
|
||||||
|
finally:
|
||||||
|
self.cleanup()
|
||||||
|
return False # Propagate the exception
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __next__(self):
|
||||||
|
try:
|
||||||
|
chunk = next(self.stream)
|
||||||
|
self.process_chunk(chunk)
|
||||||
|
return chunk
|
||||||
|
except StopIteration:
|
||||||
|
self.cleanup()
|
||||||
|
raise
|
||||||
|
except Exception as error:
|
||||||
|
self.span.set_status(Status(StatusCode.ERROR, str(error)))
|
||||||
|
self.span.set_attribute(
|
||||||
|
ErrorAttributes.ERROR_TYPE, type(error).__qualname__
|
||||||
|
)
|
||||||
|
self.cleanup()
|
||||||
|
raise
|
||||||
|
|
||||||
|
def set_response_model(self, chunk):
|
||||||
|
if self.response_model:
|
||||||
|
return
|
||||||
|
|
||||||
|
if getattr(chunk, "model", None):
|
||||||
|
self.response_model = chunk.model
|
||||||
|
|
||||||
|
def set_response_id(self, chunk):
|
||||||
|
if self.response_id:
|
||||||
|
return
|
||||||
|
|
||||||
|
if getattr(chunk, "id", None):
|
||||||
|
self.response_id = chunk.id
|
||||||
|
|
||||||
|
def build_streaming_response(self, chunk):
|
||||||
|
if getattr(chunk, "choices", None) is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
choices = chunk.choices
|
||||||
|
content = []
|
||||||
|
if not self.function_call and not self.tool_calls:
|
||||||
|
for choice in choices:
|
||||||
|
if choice.delta and choice.delta.content is not None:
|
||||||
|
content = [choice.delta.content]
|
||||||
|
|
||||||
|
elif self.function_call:
|
||||||
|
for choice in choices:
|
||||||
|
if (
|
||||||
|
choice.delta
|
||||||
|
and choice.delta.function_call is not None
|
||||||
|
and choice.delta.function_call.arguments is not None
|
||||||
|
):
|
||||||
|
content = [choice.delta.function_call.arguments]
|
||||||
|
|
||||||
|
elif self.tool_calls:
|
||||||
|
for choice in choices:
|
||||||
|
if choice.delta and choice.delta.tool_calls is not None:
|
||||||
|
toolcalls = choice.delta.tool_calls
|
||||||
|
content = []
|
||||||
|
for tool_call in toolcalls:
|
||||||
|
if (
|
||||||
|
tool_call
|
||||||
|
and tool_call.function is not None
|
||||||
|
and tool_call.function.arguments is not None
|
||||||
|
):
|
||||||
|
content.append(tool_call.function.arguments)
|
||||||
|
|
||||||
|
finish_reasons = []
|
||||||
|
for choice in choices:
|
||||||
|
finish_reasons.append(choice.finish_reason or "error")
|
||||||
|
|
||||||
|
set_span_attribute(
|
||||||
|
self.span,
|
||||||
|
GenAIAttributes.GEN_AI_RESPONSE_FINISH_REASONS,
|
||||||
|
finish_reasons,
|
||||||
|
)
|
||||||
|
if content:
|
||||||
|
self.result_content.append(content[0])
|
||||||
|
|
||||||
|
def set_usage(self, chunk):
|
||||||
|
if getattr(chunk, "usage", None):
|
||||||
|
self.completion_tokens = chunk.usage.completion_tokens
|
||||||
|
self.prompt_tokens = chunk.usage.prompt_tokens
|
||||||
|
|
||||||
|
def process_chunk(self, chunk):
|
||||||
|
self.set_response_id(chunk)
|
||||||
|
self.set_response_model(chunk)
|
||||||
|
self.build_streaming_response(chunk)
|
||||||
|
self.set_usage(chunk)
|
||||||
|
|
@ -0,0 +1,165 @@
|
||||||
|
# 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 Optional, Union
|
||||||
|
|
||||||
|
from openai import NOT_GIVEN
|
||||||
|
|
||||||
|
from opentelemetry.semconv._incubating.attributes import (
|
||||||
|
gen_ai_attributes as GenAIAttributes,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def silently_fail(func):
|
||||||
|
"""
|
||||||
|
A decorator that catches exceptions thrown by the decorated function and logs them as warnings.
|
||||||
|
"""
|
||||||
|
|
||||||
|
logger = logging.getLogger(func.__module__)
|
||||||
|
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
try:
|
||||||
|
return func(*args, **kwargs)
|
||||||
|
except Exception as exception:
|
||||||
|
logger.warning(
|
||||||
|
"Failed to execute %s, error: %s",
|
||||||
|
func.__name__,
|
||||||
|
str(exception),
|
||||||
|
)
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
def extract_content(choice):
|
||||||
|
if getattr(choice, "message", None) is None:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
# Check if choice.message exists and has a content attribute
|
||||||
|
message = choice.message
|
||||||
|
if getattr(message, "content", None):
|
||||||
|
return choice.message.content
|
||||||
|
|
||||||
|
# Check if choice.message has tool_calls and extract information accordingly
|
||||||
|
elif getattr(message, "tool_calls", None):
|
||||||
|
result = [
|
||||||
|
{
|
||||||
|
"id": tool_call.id,
|
||||||
|
"type": tool_call.type,
|
||||||
|
"function": {
|
||||||
|
"name": tool_call.function.name,
|
||||||
|
"arguments": tool_call.function.arguments,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for tool_call in choice.message.tool_calls
|
||||||
|
]
|
||||||
|
return result
|
||||||
|
|
||||||
|
# Check if choice.message has a function_call and extract information accordingly
|
||||||
|
elif getattr(message, "function_call", None):
|
||||||
|
return {
|
||||||
|
"name": choice.message.function_call.name,
|
||||||
|
"arguments": choice.message.function_call.arguments,
|
||||||
|
}
|
||||||
|
|
||||||
|
# Return an empty string if none of the above conditions are met
|
||||||
|
else:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
|
def extract_tools_prompt(item):
|
||||||
|
tool_calls = getattr(item, "tool_calls", None)
|
||||||
|
if tool_calls is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
calls = []
|
||||||
|
for tool_call in tool_calls:
|
||||||
|
tool_call_dict = {
|
||||||
|
"id": getattr(tool_call, "id", ""),
|
||||||
|
"type": getattr(tool_call, "type", ""),
|
||||||
|
}
|
||||||
|
|
||||||
|
if hasattr(tool_call, "function"):
|
||||||
|
tool_call_dict["function"] = {
|
||||||
|
"name": getattr(tool_call.function, "name", ""),
|
||||||
|
"arguments": getattr(tool_call.function, "arguments", ""),
|
||||||
|
}
|
||||||
|
calls.append(tool_call_dict)
|
||||||
|
return calls
|
||||||
|
|
||||||
|
|
||||||
|
def set_event_prompt(span, prompt):
|
||||||
|
span.add_event(
|
||||||
|
name="gen_ai.content.prompt",
|
||||||
|
attributes={
|
||||||
|
GenAIAttributes.GEN_AI_PROMPT: prompt,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def set_span_attributes(span, attributes: dict):
|
||||||
|
for field, value in attributes.model_dump(by_alias=True).items():
|
||||||
|
set_span_attribute(span, field, value)
|
||||||
|
|
||||||
|
|
||||||
|
def set_event_completion(span, result_content):
|
||||||
|
span.add_event(
|
||||||
|
name="gen_ai.content.completion",
|
||||||
|
attributes={
|
||||||
|
GenAIAttributes.GEN_AI_COMPLETION: json.dumps(result_content),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def set_span_attribute(span, name, value):
|
||||||
|
if non_numerical_value_is_set(value) is False:
|
||||||
|
return
|
||||||
|
|
||||||
|
span.set_attribute(name, value)
|
||||||
|
|
||||||
|
|
||||||
|
def is_streaming(kwargs):
|
||||||
|
return non_numerical_value_is_set(kwargs.get("stream"))
|
||||||
|
|
||||||
|
|
||||||
|
def non_numerical_value_is_set(value: Optional[Union[bool, str]]):
|
||||||
|
return bool(value) and value != NOT_GIVEN
|
||||||
|
|
||||||
|
|
||||||
|
def get_llm_request_attributes(
|
||||||
|
kwargs,
|
||||||
|
operation_name=GenAIAttributes.GenAiOperationNameValues.CHAT.value,
|
||||||
|
):
|
||||||
|
|
||||||
|
attributes = {
|
||||||
|
GenAIAttributes.GEN_AI_OPERATION_NAME: operation_name,
|
||||||
|
GenAIAttributes.GEN_AI_SYSTEM: GenAIAttributes.GenAiSystemValues.OPENAI.value,
|
||||||
|
GenAIAttributes.GEN_AI_REQUEST_MODEL: kwargs.get(
|
||||||
|
"model", "gpt-3.5-turbo"
|
||||||
|
),
|
||||||
|
GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE: kwargs.get("temperature"),
|
||||||
|
GenAIAttributes.GEN_AI_REQUEST_TOP_P: kwargs.get("p")
|
||||||
|
or kwargs.get("top_p"),
|
||||||
|
GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS: kwargs.get("max_tokens"),
|
||||||
|
GenAIAttributes.GEN_AI_REQUEST_PRESENCE_PENALTY: kwargs.get(
|
||||||
|
"presence_penalty"
|
||||||
|
),
|
||||||
|
GenAIAttributes.GEN_AI_REQUEST_FREQUENCY_PENALTY: kwargs.get(
|
||||||
|
"frequency_penalty"
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
# filter out None values
|
||||||
|
return {k: v for k, v in attributes.items() if v is not None}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
__version__ = "2.0.0.dev"
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
openai==1.26.0
|
||||||
|
pydantic==2.8.2
|
||||||
|
Deprecated==1.2.14
|
||||||
|
importlib-metadata==6.11.0
|
||||||
|
packaging==24.0
|
||||||
|
pytest==7.4.4
|
||||||
|
pytest-vcr==1.0.2
|
||||||
|
wrapt==1.16.0
|
||||||
|
|
||||||
|
-e opentelemetry-instrumentation
|
||||||
|
-e instrumentation/opentelemetry-instrumentation-openai-v2
|
||||||
|
|
@ -0,0 +1,92 @@
|
||||||
|
interactions:
|
||||||
|
- request:
|
||||||
|
body: '{"messages": [{"role": "user", "content": "Say this is a test"}], "model":
|
||||||
|
"gpt-4", "stream": false}'
|
||||||
|
headers:
|
||||||
|
accept:
|
||||||
|
- application/json
|
||||||
|
accept-encoding:
|
||||||
|
- gzip, deflate
|
||||||
|
connection:
|
||||||
|
- keep-alive
|
||||||
|
content-length:
|
||||||
|
- '100'
|
||||||
|
content-type:
|
||||||
|
- application/json
|
||||||
|
host:
|
||||||
|
- api.openai.com
|
||||||
|
user-agent:
|
||||||
|
- OpenAI/Python 1.47.0
|
||||||
|
x-stainless-arch:
|
||||||
|
- arm64
|
||||||
|
x-stainless-async:
|
||||||
|
- 'false'
|
||||||
|
x-stainless-lang:
|
||||||
|
- python
|
||||||
|
x-stainless-os:
|
||||||
|
- MacOS
|
||||||
|
x-stainless-package-version:
|
||||||
|
- 1.47.0
|
||||||
|
x-stainless-runtime:
|
||||||
|
- CPython
|
||||||
|
x-stainless-runtime-version:
|
||||||
|
- 3.11.5
|
||||||
|
method: POST
|
||||||
|
uri: https://api.openai.com/v1/chat/completions
|
||||||
|
response:
|
||||||
|
body:
|
||||||
|
string: "{\n \"id\": \"chatcmpl-AC6ajKKHHpvf6x2Qm35t6m3QE8qli\",\n \"object\":
|
||||||
|
\"chat.completion\",\n \"created\": 1727448637,\n \"model\": \"gpt-4-0613\",\n
|
||||||
|
\ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\":
|
||||||
|
\"assistant\",\n \"content\": \"This is a test.\",\n \"refusal\":
|
||||||
|
null\n },\n \"logprobs\": null,\n \"finish_reason\": \"stop\"\n
|
||||||
|
\ }\n ],\n \"usage\": {\n \"prompt_tokens\": 12,\n \"completion_tokens\":
|
||||||
|
5,\n \"total_tokens\": 17,\n \"completion_tokens_details\": {\n \"reasoning_tokens\":
|
||||||
|
0\n }\n },\n \"system_fingerprint\": null\n}\n"
|
||||||
|
headers:
|
||||||
|
CF-Cache-Status:
|
||||||
|
- DYNAMIC
|
||||||
|
CF-RAY:
|
||||||
|
- 8c9c4e9b7fb674d8-PMO
|
||||||
|
Connection:
|
||||||
|
- keep-alive
|
||||||
|
Content-Type:
|
||||||
|
- application/json
|
||||||
|
Date:
|
||||||
|
- Fri, 27 Sep 2024 14:50:37 GMT
|
||||||
|
Server:
|
||||||
|
- cloudflare
|
||||||
|
Set-Cookie: test_set_cookie
|
||||||
|
Transfer-Encoding:
|
||||||
|
- chunked
|
||||||
|
X-Content-Type-Options:
|
||||||
|
- nosniff
|
||||||
|
access-control-expose-headers:
|
||||||
|
- X-Request-ID
|
||||||
|
content-length:
|
||||||
|
- '551'
|
||||||
|
openai-organization: test_organization
|
||||||
|
openai-processing-ms:
|
||||||
|
- '434'
|
||||||
|
openai-version:
|
||||||
|
- '2020-10-01'
|
||||||
|
strict-transport-security:
|
||||||
|
- max-age=31536000; includeSubDomains; preload
|
||||||
|
x-ratelimit-limit-requests:
|
||||||
|
- '10000'
|
||||||
|
x-ratelimit-limit-tokens:
|
||||||
|
- '1000000'
|
||||||
|
x-ratelimit-remaining-requests:
|
||||||
|
- '9999'
|
||||||
|
x-ratelimit-remaining-tokens:
|
||||||
|
- '999977'
|
||||||
|
x-ratelimit-reset-requests:
|
||||||
|
- 6ms
|
||||||
|
x-ratelimit-reset-tokens:
|
||||||
|
- 1ms
|
||||||
|
x-request-id:
|
||||||
|
- req_5f2690abaf909a9f047488694d44495e
|
||||||
|
status:
|
||||||
|
code: 200
|
||||||
|
message: OK
|
||||||
|
version: 1
|
||||||
|
|
@ -0,0 +1,113 @@
|
||||||
|
interactions:
|
||||||
|
- request:
|
||||||
|
body: '{"messages": [{"role": "user", "content": "Say this is a test"}], "model":
|
||||||
|
"gpt-4", "stream": true, "stream_options": {"include_usage": true}}'
|
||||||
|
headers:
|
||||||
|
accept:
|
||||||
|
- application/json
|
||||||
|
accept-encoding:
|
||||||
|
- gzip, deflate
|
||||||
|
connection:
|
||||||
|
- keep-alive
|
||||||
|
content-length:
|
||||||
|
- '142'
|
||||||
|
content-type:
|
||||||
|
- application/json
|
||||||
|
host:
|
||||||
|
- api.openai.com
|
||||||
|
user-agent:
|
||||||
|
- OpenAI/Python 1.47.0
|
||||||
|
x-stainless-arch:
|
||||||
|
- arm64
|
||||||
|
x-stainless-async:
|
||||||
|
- 'false'
|
||||||
|
x-stainless-lang:
|
||||||
|
- python
|
||||||
|
x-stainless-os:
|
||||||
|
- MacOS
|
||||||
|
x-stainless-package-version:
|
||||||
|
- 1.47.0
|
||||||
|
x-stainless-runtime:
|
||||||
|
- CPython
|
||||||
|
x-stainless-runtime-version:
|
||||||
|
- 3.11.5
|
||||||
|
method: POST
|
||||||
|
uri: https://api.openai.com/v1/chat/completions
|
||||||
|
response:
|
||||||
|
body:
|
||||||
|
string: 'data: {"id":"chatcmpl-AC6akONKCxc8HS63qZ08HyjeTSq6p","object":"chat.completion.chunk","created":1727448638,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null}
|
||||||
|
|
||||||
|
|
||||||
|
data: {"id":"chatcmpl-AC6akONKCxc8HS63qZ08HyjeTSq6p","object":"chat.completion.chunk","created":1727448638,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"This"},"logprobs":null,"finish_reason":null}],"usage":null}
|
||||||
|
|
||||||
|
|
||||||
|
data: {"id":"chatcmpl-AC6akONKCxc8HS63qZ08HyjeTSq6p","object":"chat.completion.chunk","created":1727448638,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"
|
||||||
|
is"},"logprobs":null,"finish_reason":null}],"usage":null}
|
||||||
|
|
||||||
|
|
||||||
|
data: {"id":"chatcmpl-AC6akONKCxc8HS63qZ08HyjeTSq6p","object":"chat.completion.chunk","created":1727448638,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"
|
||||||
|
a"},"logprobs":null,"finish_reason":null}],"usage":null}
|
||||||
|
|
||||||
|
|
||||||
|
data: {"id":"chatcmpl-AC6akONKCxc8HS63qZ08HyjeTSq6p","object":"chat.completion.chunk","created":1727448638,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"
|
||||||
|
test"},"logprobs":null,"finish_reason":null}],"usage":null}
|
||||||
|
|
||||||
|
|
||||||
|
data: {"id":"chatcmpl-AC6akONKCxc8HS63qZ08HyjeTSq6p","object":"chat.completion.chunk","created":1727448638,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"."},"logprobs":null,"finish_reason":null}],"usage":null}
|
||||||
|
|
||||||
|
|
||||||
|
data: {"id":"chatcmpl-AC6akONKCxc8HS63qZ08HyjeTSq6p","object":"chat.completion.chunk","created":1727448638,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null}
|
||||||
|
|
||||||
|
|
||||||
|
data: {"id":"chatcmpl-AC6akONKCxc8HS63qZ08HyjeTSq6p","object":"chat.completion.chunk","created":1727448638,"model":"gpt-4-0613","system_fingerprint":null,"choices":[],"usage":{"prompt_tokens":12,"completion_tokens":5,"total_tokens":17,"completion_tokens_details":{"reasoning_tokens":0}}}
|
||||||
|
|
||||||
|
|
||||||
|
data: [DONE]
|
||||||
|
|
||||||
|
|
||||||
|
'
|
||||||
|
headers:
|
||||||
|
CF-Cache-Status:
|
||||||
|
- DYNAMIC
|
||||||
|
CF-RAY:
|
||||||
|
- 8c9c4ea489d57948-PMO
|
||||||
|
Connection:
|
||||||
|
- keep-alive
|
||||||
|
Content-Type:
|
||||||
|
- text/event-stream; charset=utf-8
|
||||||
|
Date:
|
||||||
|
- Fri, 27 Sep 2024 14:50:38 GMT
|
||||||
|
Server:
|
||||||
|
- cloudflare
|
||||||
|
Set-Cookie: test_set_cookie
|
||||||
|
Transfer-Encoding:
|
||||||
|
- chunked
|
||||||
|
X-Content-Type-Options:
|
||||||
|
- nosniff
|
||||||
|
access-control-expose-headers:
|
||||||
|
- X-Request-ID
|
||||||
|
openai-organization: test_organization
|
||||||
|
openai-processing-ms:
|
||||||
|
- '161'
|
||||||
|
openai-version:
|
||||||
|
- '2020-10-01'
|
||||||
|
strict-transport-security:
|
||||||
|
- max-age=31536000; includeSubDomains; preload
|
||||||
|
x-ratelimit-limit-requests:
|
||||||
|
- '10000'
|
||||||
|
x-ratelimit-limit-tokens:
|
||||||
|
- '1000000'
|
||||||
|
x-ratelimit-remaining-requests:
|
||||||
|
- '9999'
|
||||||
|
x-ratelimit-remaining-tokens:
|
||||||
|
- '999977'
|
||||||
|
x-ratelimit-reset-requests:
|
||||||
|
- 6ms
|
||||||
|
x-ratelimit-reset-tokens:
|
||||||
|
- 1ms
|
||||||
|
x-request-id:
|
||||||
|
- req_3fa9ac9f3693c712e4c377e26d203e58
|
||||||
|
status:
|
||||||
|
code: 200
|
||||||
|
message: OK
|
||||||
|
version: 1
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
"""Unit tests configuration module."""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from openai import OpenAI
|
||||||
|
|
||||||
|
from opentelemetry import trace
|
||||||
|
from opentelemetry.instrumentation.openai_v2 import OpenAIInstrumentor
|
||||||
|
from opentelemetry.sdk.trace import TracerProvider
|
||||||
|
from opentelemetry.sdk.trace.export import SimpleSpanProcessor
|
||||||
|
from opentelemetry.sdk.trace.export.in_memory_span_exporter import (
|
||||||
|
InMemorySpanExporter,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="session")
|
||||||
|
def exporter():
|
||||||
|
exporter = InMemorySpanExporter()
|
||||||
|
processor = SimpleSpanProcessor(exporter)
|
||||||
|
|
||||||
|
provider = TracerProvider()
|
||||||
|
provider.add_span_processor(processor)
|
||||||
|
trace.set_tracer_provider(provider)
|
||||||
|
|
||||||
|
return exporter
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(autouse=True)
|
||||||
|
def clear_exporter(exporter):
|
||||||
|
exporter.clear()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(autouse=True)
|
||||||
|
def environment():
|
||||||
|
if not os.getenv("OPENAI_API_KEY"):
|
||||||
|
os.environ["OPENAI_API_KEY"] = "test-api-key"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def openai_client():
|
||||||
|
return OpenAI()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="module")
|
||||||
|
def vcr_config():
|
||||||
|
return {
|
||||||
|
"filter_headers": ["authorization", "api-key"],
|
||||||
|
"decode_compressed_response": True,
|
||||||
|
"before_record_response": scrub_response_headers,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="session", autouse=True)
|
||||||
|
def instrument():
|
||||||
|
OpenAIInstrumentor().instrument()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="session", autouse=True)
|
||||||
|
def uninstrument():
|
||||||
|
OpenAIInstrumentor().uninstrument()
|
||||||
|
|
||||||
|
|
||||||
|
def scrub_response_headers(response):
|
||||||
|
"""
|
||||||
|
This scrubs sensitive response headers. Note they are case-sensitive!
|
||||||
|
"""
|
||||||
|
response["headers"]["openai-organization"] = "test_organization"
|
||||||
|
response["headers"]["Set-Cookie"] = "test_set_cookie"
|
||||||
|
return response
|
||||||
|
|
@ -0,0 +1,157 @@
|
||||||
|
import json
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from opentelemetry.semconv._incubating.attributes import (
|
||||||
|
gen_ai_attributes as GenAIAttributes,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.vcr()
|
||||||
|
def test_chat_completion(exporter, openai_client):
|
||||||
|
llm_model_value = "gpt-4"
|
||||||
|
messages_value = [{"role": "user", "content": "Say this is a test"}]
|
||||||
|
|
||||||
|
kwargs = {
|
||||||
|
"model": llm_model_value,
|
||||||
|
"messages": messages_value,
|
||||||
|
"stream": False,
|
||||||
|
}
|
||||||
|
|
||||||
|
response = openai_client.chat.completions.create(**kwargs)
|
||||||
|
spans = exporter.get_finished_spans()
|
||||||
|
chat_completion_span = spans[0]
|
||||||
|
# assert that the span name is correct
|
||||||
|
assert chat_completion_span.name == f"chat {llm_model_value}"
|
||||||
|
|
||||||
|
attributes = chat_completion_span.attributes
|
||||||
|
operation_name = attributes[GenAIAttributes.GEN_AI_OPERATION_NAME]
|
||||||
|
system = attributes[GenAIAttributes.GEN_AI_SYSTEM]
|
||||||
|
request_model = attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL]
|
||||||
|
response_model = attributes[GenAIAttributes.GEN_AI_RESPONSE_MODEL]
|
||||||
|
response_id = attributes[GenAIAttributes.GEN_AI_RESPONSE_ID]
|
||||||
|
input_tokens = attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS]
|
||||||
|
output_tokens = attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS]
|
||||||
|
# assert that the attributes are correct
|
||||||
|
assert (
|
||||||
|
operation_name == GenAIAttributes.GenAiOperationNameValues.CHAT.value
|
||||||
|
)
|
||||||
|
assert system == GenAIAttributes.GenAiSystemValues.OPENAI.value
|
||||||
|
assert request_model == llm_model_value
|
||||||
|
assert response_model == response.model
|
||||||
|
assert response_id == response.id
|
||||||
|
assert input_tokens == response.usage.prompt_tokens
|
||||||
|
assert output_tokens == response.usage.completion_tokens
|
||||||
|
|
||||||
|
events = chat_completion_span.events
|
||||||
|
|
||||||
|
# assert that the prompt and completion events are present
|
||||||
|
prompt_event = list(
|
||||||
|
filter(
|
||||||
|
lambda event: event.name == "gen_ai.content.prompt",
|
||||||
|
events,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
completion_event = list(
|
||||||
|
filter(
|
||||||
|
lambda event: event.name == "gen_ai.content.completion",
|
||||||
|
events,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
assert prompt_event
|
||||||
|
assert completion_event
|
||||||
|
|
||||||
|
# assert that the prompt and completion events have the correct attributes
|
||||||
|
assert prompt_event[0].attributes[
|
||||||
|
GenAIAttributes.GEN_AI_PROMPT
|
||||||
|
] == json.dumps(messages_value)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
json.loads(
|
||||||
|
completion_event[0].attributes[GenAIAttributes.GEN_AI_COMPLETION]
|
||||||
|
)[0]["content"]
|
||||||
|
== response.choices[0].message.content
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.vcr()
|
||||||
|
def test_chat_completion_streaming(exporter, openai_client):
|
||||||
|
llm_model_value = "gpt-4"
|
||||||
|
messages_value = [{"role": "user", "content": "Say this is a test"}]
|
||||||
|
|
||||||
|
kwargs = {
|
||||||
|
"model": llm_model_value,
|
||||||
|
"messages": messages_value,
|
||||||
|
"stream": True,
|
||||||
|
"stream_options": {"include_usage": True},
|
||||||
|
}
|
||||||
|
|
||||||
|
response_stream_usage = None
|
||||||
|
response_stream_model = None
|
||||||
|
response_stream_id = None
|
||||||
|
response_stream_result = ""
|
||||||
|
response = openai_client.chat.completions.create(**kwargs)
|
||||||
|
for chunk in response:
|
||||||
|
if chunk.choices:
|
||||||
|
response_stream_result += chunk.choices[0].delta.content or ""
|
||||||
|
|
||||||
|
# get the last chunk
|
||||||
|
if getattr(chunk, "usage", None):
|
||||||
|
response_stream_usage = chunk.usage
|
||||||
|
response_stream_model = chunk.model
|
||||||
|
response_stream_id = chunk.id
|
||||||
|
|
||||||
|
spans = exporter.get_finished_spans()
|
||||||
|
streaming_span = spans[0]
|
||||||
|
|
||||||
|
assert streaming_span.name == f"chat {llm_model_value}"
|
||||||
|
attributes = streaming_span.attributes
|
||||||
|
|
||||||
|
operation_name = attributes[GenAIAttributes.GEN_AI_OPERATION_NAME]
|
||||||
|
system = attributes[GenAIAttributes.GEN_AI_SYSTEM]
|
||||||
|
request_model = attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL]
|
||||||
|
response_model = attributes[GenAIAttributes.GEN_AI_RESPONSE_MODEL]
|
||||||
|
response_id = attributes[GenAIAttributes.GEN_AI_RESPONSE_ID]
|
||||||
|
input_tokens = attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS]
|
||||||
|
output_tokens = attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS]
|
||||||
|
assert (
|
||||||
|
operation_name == GenAIAttributes.GenAiOperationNameValues.CHAT.value
|
||||||
|
)
|
||||||
|
assert system == GenAIAttributes.GenAiSystemValues.OPENAI.value
|
||||||
|
assert request_model == llm_model_value
|
||||||
|
assert response_model == response_stream_model
|
||||||
|
assert response_id == response_stream_id
|
||||||
|
assert input_tokens == response_stream_usage.prompt_tokens
|
||||||
|
assert output_tokens == response_stream_usage.completion_tokens
|
||||||
|
|
||||||
|
events = streaming_span.events
|
||||||
|
|
||||||
|
# assert that the prompt and completion events are present
|
||||||
|
prompt_event = list(
|
||||||
|
filter(
|
||||||
|
lambda event: event.name == "gen_ai.content.prompt",
|
||||||
|
events,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
completion_event = list(
|
||||||
|
filter(
|
||||||
|
lambda event: event.name == "gen_ai.content.completion",
|
||||||
|
events,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
assert prompt_event
|
||||||
|
assert completion_event
|
||||||
|
|
||||||
|
# assert that the prompt and completion events have the correct attributes
|
||||||
|
assert prompt_event[0].attributes[
|
||||||
|
GenAIAttributes.GEN_AI_PROMPT
|
||||||
|
] == json.dumps(messages_value)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
json.loads(
|
||||||
|
completion_event[0].attributes[GenAIAttributes.GEN_AI_COMPLETION]
|
||||||
|
)[0]["content"]
|
||||||
|
== response_stream_result
|
||||||
|
)
|
||||||
|
|
@ -57,6 +57,7 @@ dependencies = [
|
||||||
"opentelemetry-instrumentation-logging==0.49b0.dev",
|
"opentelemetry-instrumentation-logging==0.49b0.dev",
|
||||||
"opentelemetry-instrumentation-mysql==0.49b0.dev",
|
"opentelemetry-instrumentation-mysql==0.49b0.dev",
|
||||||
"opentelemetry-instrumentation-mysqlclient==0.49b0.dev",
|
"opentelemetry-instrumentation-mysqlclient==0.49b0.dev",
|
||||||
|
"opentelemetry-instrumentation-openai-v2==2.0.0.dev",
|
||||||
"opentelemetry-instrumentation-pika==0.49b0.dev",
|
"opentelemetry-instrumentation-pika==0.49b0.dev",
|
||||||
"opentelemetry-instrumentation-psycopg==0.49b0.dev",
|
"opentelemetry-instrumentation-psycopg==0.49b0.dev",
|
||||||
"opentelemetry-instrumentation-psycopg2==0.49b0.dev",
|
"opentelemetry-instrumentation-psycopg2==0.49b0.dev",
|
||||||
|
|
|
||||||
|
|
@ -120,6 +120,10 @@ libraries = [
|
||||||
"library": "mysqlclient < 3",
|
"library": "mysqlclient < 3",
|
||||||
"instrumentation": "opentelemetry-instrumentation-mysqlclient==0.49b0.dev",
|
"instrumentation": "opentelemetry-instrumentation-mysqlclient==0.49b0.dev",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"library": "openai >= 1.0.0",
|
||||||
|
"instrumentation": "opentelemetry-instrumentation-openai-v2==2.0.0.dev",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"library": "pika >= 0.12.0",
|
"library": "pika >= 0.12.0",
|
||||||
"instrumentation": "opentelemetry-instrumentation-pika==0.49b0.dev",
|
"instrumentation": "opentelemetry-instrumentation-pika==0.49b0.dev",
|
||||||
|
|
|
||||||
16
tox.ini
16
tox.ini
|
|
@ -6,6 +6,11 @@ envlist =
|
||||||
; Environments are organized by individual package, allowing
|
; Environments are organized by individual package, allowing
|
||||||
; for specifying supported Python versions per package.
|
; for specifying supported Python versions per package.
|
||||||
|
|
||||||
|
; instrumentation-openai
|
||||||
|
py3{8,9,10,11,12}-test-instrumentation-openai-v2
|
||||||
|
pypy3-test-instrumentation-openai-v2
|
||||||
|
lint-instrumentation-openai-v2
|
||||||
|
|
||||||
; opentelemetry-resource-detector-container
|
; opentelemetry-resource-detector-container
|
||||||
py3{8,9,10,11,12}-test-resource-detector-container
|
py3{8,9,10,11,12}-test-resource-detector-container
|
||||||
pypy3-test-resource-detector-container
|
pypy3-test-resource-detector-container
|
||||||
|
|
@ -404,6 +409,12 @@ commands_pre =
|
||||||
opentelemetry-instrumentation: pip install opentelemetry-test-utils@{env:CORE_REPO}\#egg=opentelemetry-test-utils&subdirectory=tests/opentelemetry-test-utils
|
opentelemetry-instrumentation: pip install opentelemetry-test-utils@{env:CORE_REPO}\#egg=opentelemetry-test-utils&subdirectory=tests/opentelemetry-test-utils
|
||||||
opentelemetry-instrumentation: pip install -r {toxinidir}/opentelemetry-instrumentation/test-requirements.txt
|
opentelemetry-instrumentation: pip install -r {toxinidir}/opentelemetry-instrumentation/test-requirements.txt
|
||||||
|
|
||||||
|
openai: pip install opentelemetry-api@{env:CORE_REPO}\#egg=opentelemetry-api&subdirectory=opentelemetry-api
|
||||||
|
openai: pip install opentelemetry-semantic-conventions@{env:CORE_REPO}\#egg=opentelemetry-semantic-conventions&subdirectory=opentelemetry-semantic-conventions
|
||||||
|
openai: pip install opentelemetry-sdk@{env:CORE_REPO}\#egg=opentelemetry-sdk&subdirectory=opentelemetry-sdk
|
||||||
|
openai: pip install opentelemetry-test-utils@{env:CORE_REPO}\#egg=opentelemetry-test-utils&subdirectory=tests/opentelemetry-test-utils
|
||||||
|
openai: pip install -r {toxinidir}/instrumentation/opentelemetry-instrumentation-openai-v2/test-requirements.txt
|
||||||
|
|
||||||
distro: pip install opentelemetry-api@{env:CORE_REPO}\#egg=opentelemetry-api&subdirectory=opentelemetry-api
|
distro: pip install opentelemetry-api@{env:CORE_REPO}\#egg=opentelemetry-api&subdirectory=opentelemetry-api
|
||||||
distro: pip install opentelemetry-semantic-conventions@{env:CORE_REPO}\#egg=opentelemetry-semantic-conventions&subdirectory=opentelemetry-semantic-conventions
|
distro: pip install opentelemetry-semantic-conventions@{env:CORE_REPO}\#egg=opentelemetry-semantic-conventions&subdirectory=opentelemetry-semantic-conventions
|
||||||
distro: pip install opentelemetry-sdk@{env:CORE_REPO}\#egg=opentelemetry-sdk&subdirectory=opentelemetry-sdk
|
distro: pip install opentelemetry-sdk@{env:CORE_REPO}\#egg=opentelemetry-sdk&subdirectory=opentelemetry-sdk
|
||||||
|
|
@ -456,6 +467,11 @@ commands_pre =
|
||||||
kafka-pythonng: pip install opentelemetry-sdk@{env:CORE_REPO}\#egg=opentelemetry-sdk&subdirectory=opentelemetry-sdk
|
kafka-pythonng: pip install opentelemetry-sdk@{env:CORE_REPO}\#egg=opentelemetry-sdk&subdirectory=opentelemetry-sdk
|
||||||
kafka-pythonng: pip install -r {toxinidir}/instrumentation/opentelemetry-instrumentation-kafka-python/test-requirements-ng.txt
|
kafka-pythonng: pip install -r {toxinidir}/instrumentation/opentelemetry-instrumentation-kafka-python/test-requirements-ng.txt
|
||||||
|
|
||||||
|
openai: pip install opentelemetry-api@{env:CORE_REPO}\#egg=opentelemetry-api&subdirectory=opentelemetry-api
|
||||||
|
openai: pip install opentelemetry-sdk@{env:CORE_REPO}\#egg=opentelemetry-sdk&subdirectory=opentelemetry-sdk
|
||||||
|
openai: pip install opentelemetry-semantic-conventions@{env:CORE_REPO}\#egg=opentelemetry-semantic-conventions&subdirectory=opentelemetry-semantic-conventions
|
||||||
|
openai: pip install -r {toxinidir}/instrumentation/opentelemetry-instrumentation-openai-v2/test-requirements.txt
|
||||||
|
|
||||||
confluent-kafka: pip install opentelemetry-api@{env:CORE_REPO}\#egg=opentelemetry-api&subdirectory=opentelemetry-api
|
confluent-kafka: pip install opentelemetry-api@{env:CORE_REPO}\#egg=opentelemetry-api&subdirectory=opentelemetry-api
|
||||||
confluent-kafka: pip install opentelemetry-semantic-conventions@{env:CORE_REPO}\#egg=opentelemetry-semantic-conventions&subdirectory=opentelemetry-semantic-conventions
|
confluent-kafka: pip install opentelemetry-semantic-conventions@{env:CORE_REPO}\#egg=opentelemetry-semantic-conventions&subdirectory=opentelemetry-semantic-conventions
|
||||||
confluent-kafka: pip install opentelemetry-sdk@{env:CORE_REPO}\#egg=opentelemetry-sdk&subdirectory=opentelemetry-sdk
|
confluent-kafka: pip install opentelemetry-sdk@{env:CORE_REPO}\#egg=opentelemetry-sdk&subdirectory=opentelemetry-sdk
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue