diff --git a/.github/component_owners.yml b/.github/component_owners.yml
index 1e89d59567..5cbb6aa402 100644
--- a/.github/component_owners.yml
+++ b/.github/component_owners.yml
@@ -73,4 +73,5 @@ components:
- lzchen
- gyliu513
- nirga
+ - alizenhom
- codefromthecrypt
diff --git a/.github/scripts/update-version-patch.sh b/.github/scripts/update-version-patch.sh
new file mode 100755
index 0000000000..fec7cd8260
--- /dev/null
+++ b/.github/scripts/update-version-patch.sh
@@ -0,0 +1,11 @@
+#!/bin/bash -e
+
+sed -i "/\[stable\]/{n;s/version=.*/version=$1/}" eachdist.ini
+sed -i "/\[prerelease\]/{n;s/version=.*/version=$2/}" eachdist.ini
+
+./scripts/eachdist.py update_patch_versions \
+ --stable_version=$1 \
+ --unstable_version=$2 \
+ --stable_version_prev=$3 \
+ --unstable_version_prev=$4
+
diff --git a/.github/workflows/prepare-patch-release.yml b/.github/workflows/prepare-patch-release.yml
index 7c854d436d..51e1dd8208 100644
--- a/.github/workflows/prepare-patch-release.yml
+++ b/.github/workflows/prepare-patch-release.yml
@@ -40,14 +40,18 @@ jobs:
exit 1
fi
+ stable_version_prev="$stable_major_minor.$((stable_patch))"
+ unstable_version_prev="0.${unstable_minor}b$((unstable_patch))"
stable_version="$stable_major_minor.$((stable_patch + 1))"
unstable_version="0.${unstable_minor}b$((unstable_patch + 1))"
echo "STABLE_VERSION=$stable_version" >> $GITHUB_ENV
echo "UNSTABLE_VERSION=$unstable_version" >> $GITHUB_ENV
+ echo "STABLE_VERSION_PREV=$stable_version_prev" >> $GITHUB_ENV
+ echo "UNSTABLE_VERSION_PREV=$unstable_version_prev" >> $GITHUB_ENV
- name: Update version
- run: .github/scripts/update-version.sh $STABLE_VERSION $UNSTABLE_VERSION
+ run: .github/scripts/update-version-patch.sh $STABLE_VERSION $UNSTABLE_VERSION $STABLE_VERSION_PREV $UNSTABLE_VERSION_PREV
- name: Set up Python 3.9
uses: actions/setup-python@v5
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 7d7b18edc8..97e51c9c63 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -118,36 +118,3 @@ jobs:
# the step below is creating a pull request against main
ref: main
- - name: Copy change log updates to main
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: |
- echo "VERSION=${STABLE_VERSION}\/${UNSTABLE_VERSION}" >> $GITHUB_ENV
- echo "RELEASE_TAG=$STABLE_VERSION" >> $GITHUB_ENV
- ./scripts/merge_changelog_to_main.sh
-
- - name: Use CLA approved github bot
- run: .github/scripts/use-cla-approved-github-bot.sh
-
- - name: Create pull request against main
- env:
- # not using secrets.GITHUB_TOKEN since pull requests from that token do not run workflows
- GITHUB_TOKEN: ${{ secrets.OPENTELEMETRYBOT_GITHUB_TOKEN }}
- run: |
- message="Copy change log updates from $GITHUB_REF_NAME"
- body="Copy log updates from \`$GITHUB_REF_NAME\`."
- branch="opentelemetrybot/copy-change-log-updates-from-${GITHUB_REF_NAME//\//-}"
-
- if [[ -z $PRIOR_VERSION_WHEN_PATCH ]]; then
- if git diff --quiet; then
- echo there are no updates needed to the change log on main, not creating pull request
- exit 0 # success
- fi
- fi
-
- git commit -a -m "$message"
- git push origin HEAD:$branch
- gh pr create --title "$message" \
- --body "$body" \
- --head $branch \
- --base main
diff --git a/.pylintrc b/.pylintrc
index 39ea7b5d35..bc3b25c978 100644
--- a/.pylintrc
+++ b/.pylintrc
@@ -7,7 +7,7 @@ extension-pkg-whitelist=cassandra
# Add list of files or directories to be excluded. They should be base names, not
# paths.
-ignore=CVS,gen,Dockerfile,docker-compose.yml,README.md,requirements.txt,docs
+ignore=CVS,gen,Dockerfile,docker-compose.yml,README.md,requirements.txt,docs,.venv
# Add files or directories matching the regex patterns to be excluded. The
# regex matches against base names, not paths.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6fdb7c123f..e53dbd9980 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,15 +15,38 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `opentelemetry-instrumentation-sqlalchemy` Update unit tests to run with SQLALchemy 2
([#2976](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2976))
+- Add `opentelemetry-instrumentation-openai-v2` to `opentelemetry-bootstrap`
+ ([#2996](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2996))
+- `opentelemetry-instrumentation-sqlalchemy` Add sqlcomment to `db.statement` attribute
+ ([#2937](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2937))
+- `opentelemetry-instrumentation-dbapi` Add sqlcomment to `db.statement` attribute
+ ([#2935](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2935))
+- `opentelemetry-instrumentation-dbapi` instrument_connection accepts optional connect_module
+ ([#3027](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3027))
+- `opentelemetry-instrumentation-mysqlclient` Add sqlcommenter support
+ ([#2941](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2941))
+- `opentelemetry-instrumentation-pymysql` Add sqlcommenter support
+ ([#2942](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2942))
### Fixed
+- `opentelemetry-instrumentation-httpx`: instrument_client is a static method again
+ ([#3003](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3003))
+- `opentelemetry-instrumentation-system_metrics`: fix callbacks reading wrong config
+ ([#3025](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3025))
+- `opentelemetry-instrumentation-httpx`: Check if mount transport is none before wrap it
+ ([#3022](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3022))
+- Replace all instrumentor unit test `assertEqualSpanInstrumentationInfo` calls with `assertEqualSpanInstrumentationScope` calls
+ ([#3037](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3037))
+
### Breaking changes
- `opentelemetry-instrumentation-sqlalchemy` teach instruments version
([#2971](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2971))
- Drop `opentelemetry-instrumentation-test` package from default instrumentation list
([#2969](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2969))
+- `opentelemetry-instrumentation-httpx`: remove private unused `_InstrumentedClient` and `_InstrumentedAsyncClient` classes
+ ([#3036](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3036))
## Version 1.28.0/0.49b0 (2024-11-05)
diff --git a/RELEASING.md b/RELEASING.md
index 2706d36c8f..490269e2e4 100644
--- a/RELEASING.md
+++ b/RELEASING.md
@@ -9,8 +9,9 @@
(otherwise the workflow will pick up the version from `main` and just remove the `.dev` suffix).
* Review the two pull requests that it creates.
(one is targeted to the release branch and one is targeted to `main`).
- * Merge the one targeted towards the release branch.
- * The builds will fail for the `main` pr because of validation rules. Follow the [release workflow](https://github.com/open-telemetry/opentelemetry-python/blob/main/RELEASING.md) for the core repo up until this same point. Change the SHAs of each PR to point at each other to get the `main` builds to pass.
+ * The builds will fail for both the `main` and release pr because of validation rules. Follow the [release workflow](https://github.com/open-telemetry/opentelemetry-python/blob/main/RELEASING.md) for the core repo up until this same point. Change the SHAs of each PR to point at each other to get the `main` and release builds to pass.
+ * Merge the release PR.
+ * Merge the PR to main (this can be done separately from [making the release](#making-the-release))
### Preparing a major or minor release for individual package
@@ -62,6 +63,7 @@ The workflow can only be run against long-term release branch such as `package-r
* Review and merge the pull request that it creates for updating the change log in main
(note that if this is not a patch release then the change log on main may already be up-to-date,
in which case no pull request will be created).
+ * Verify that a new [Github release](https://github.com/open-telemetry/opentelemetry-python-contrib/releases) has been created and that the CHANGELOGs look correct.
### Releasing individual package
@@ -79,6 +81,14 @@ to pick a specific package to release.
The workflow can only be run against long-term release branch such as `package-release/{package-name}/v{major}.{minor}.x` or `package-release/{package-name}/v{major}.{minor}bx`.
+## After the release
+
+* Check PyPI
+ * This should be handled automatically on release by the [publish action](https://github.com/open-telemetry/opentelemetry-python-contrib/blob/main/.github/workflows/release.yml).
+ * Check the [action logs](https://github.com/open-telemetry/opentelemetry-python-contrib/actions/workflows/release.yml) to make sure packages have been uploaded to PyPI
+ * Check the release history (e.g. https://pypi.org/project/opentelemetry-instrumentation/#history) on PyPI
+ * If for some reason the action failed, see [Publish failed](#publish-failed) below
+
## Notes about version numbering for stable components
* The version number for stable components in the `main` branch is always `X.Y.0.dev`,
@@ -110,28 +120,6 @@ The workflow can only be run against long-term release branch such as `package-r
* The version number for unstable components in the `main` branch will be bumped to the next version,
e.g. `0.{Y+1}b0.dev`.
-## After the release
-
-* Check PyPI
- * This should be handled automatically on release by the [publish action](https://github.com/open-telemetry/opentelemetry-python-contrib/blob/main/.github/workflows/release.yml).
- * Check the [action logs](https://github.com/open-telemetry/opentelemetry-python-contrib/actions/workflows/release.yml) to make sure packages have been uploaded to PyPI
- * Check the release history (e.g. https://pypi.org/project/opentelemetry-instrumentation/#history) on PyPI
- * If for some reason the action failed, see [Publish failed](#publish-failed) below
-* Move stable tag
- * Run the following (TODO automate):
-
- ```bash
- git tag -d stable
- git tag stable
- git push --delete origin tagname
- git push origin stable
- ```
-
- * This will ensure the docs are pointing at the stable release.
- * To validate this worked, ensure the stable build has run successfully:
- .
- If the build has not run automatically, it can be manually trigger via the readthedocs interface.
-
## Releasing dev version of new packages to claim namespace
When a contribution introduces a new package, in order to mitigate name-squatting incidents, release the current development version of the new package under the `opentelemetry` user to simply claim the namespace. This should be done shortly after the PR that introduced this package has been merged into `main`.
diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/CHANGELOG.md b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/CHANGELOG.md
index 2fdeeea74f..2c10498511 100644
--- a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/CHANGELOG.md
+++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/CHANGELOG.md
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased
+- Add example to `opentelemetry-instrumentation-openai-v2`
+ ([#3006](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3006))
+- Support for `AsyncOpenAI/AsyncCompletions` ([#2984](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2984))
+
## Version 2.0b0 (2024-11-08)
- Use generic `OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT` environment variable
diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/README.rst b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/README.rst
index 85817896ff..bbd142a97e 100644
--- a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/README.rst
+++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/README.rst
@@ -6,17 +6,21 @@ OpenTelemetry OpenAI Instrumentation
.. |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'.
+This library allows tracing LLM requests and logging of messages made by the
+`OpenAI Python API library `_.
Installation
------------
+If your application is already instrumented with OpenTelemetry, add this
+package to your requirements.
::
pip install opentelemetry-instrumentation-openai-v2
+If you don't have an OpenAI application, yet, try our `example `_
+which only needs a valid OpenAI API key.
References
----------
diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/example/.env b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/example/.env
new file mode 100644
index 0000000000..d6afa66723
--- /dev/null
+++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/example/.env
@@ -0,0 +1,18 @@
+# Update this with your real OpenAI API key
+OPENAI_API_KEY=sk-YOUR_API_KEY
+
+# Uncomment to use Ollama instead of OpenAI
+# OPENAI_BASE_URL=http://localhost:11434/v1
+# OPENAI_API_KEY=unused
+# CHAT_MODEL=qwen2.5:0.5b
+
+OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
+OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
+OTEL_SERVICE_NAME=opentelemetry-python-openai
+
+# Change to 'false' to disable logging
+OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED=true
+# Change to 'console' if your OTLP endpoint doesn't support logs
+OTEL_LOGS_EXPORTER=otlp_proto_http
+# Change to 'false' to hide prompt and completion content
+OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=true
diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/example/README.rst b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/example/README.rst
new file mode 100644
index 0000000000..019e141c70
--- /dev/null
+++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/example/README.rst
@@ -0,0 +1,39 @@
+OpenTelemetry OpenAI Instrumentation Example
+============================================
+
+This is an example of how to instrument OpenAI calls with zero code changes,
+using `opentelemetry-instrument`.
+
+When `main.py `_ is run, it exports traces and logs to an OTLP
+compatible endpoint. Traces include details such as the model used and the
+duration of the chat request. Logs capture the chat request and the generated
+response, providing a comprehensive view of the performance and behavior of
+your OpenAI requests.
+
+Setup
+-----
+
+Minimally, update the `.env <.env>`_ file with your "OPENAI_API_KEY". An
+OTLP compatible endpoint should be listening for traces and logs on
+http://localhost:4318. If not, update "OTEL_EXPORTER_OTLP_ENDPOINT" as well.
+
+Next, set up a virtual environment like this:
+
+::
+
+ python3 -m venv .venv
+ source .venv/bin/activate
+ pip install "python-dotenv[cli]"
+ pip install -r requirements.txt
+
+Run
+---
+
+Run the example like this:
+
+::
+
+ dotenv run -- opentelemetry-instrument python main.py
+
+You should see a poem generated by OpenAI while traces and logs export to your
+configured observability tool.
diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/example/main.py b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/example/main.py
new file mode 100644
index 0000000000..d41b1dd933
--- /dev/null
+++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/example/main.py
@@ -0,0 +1,21 @@
+import os
+
+from openai import OpenAI
+
+
+def main():
+ client = OpenAI()
+ chat_completion = client.chat.completions.create(
+ model=os.getenv("CHAT_MODEL", "gpt-4o-mini"),
+ messages=[
+ {
+ "role": "user",
+ "content": "Write a short poem on OpenTelemetry.",
+ },
+ ],
+ )
+ print(chat_completion.choices[0].message.content)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/example/requirements.txt b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/example/requirements.txt
new file mode 100644
index 0000000000..9ec9bff320
--- /dev/null
+++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/example/requirements.txt
@@ -0,0 +1,6 @@
+openai~=1.54.4
+
+opentelemetry-sdk~=1.28.2
+opentelemetry-exporter-otlp-proto-http~=1.28.2
+opentelemetry-distro~=0.49b2
+opentelemetry-instrumentation-openai-v2~=2.0b0
diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/pyproject.toml b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/pyproject.toml
index eddd85e5f0..e28611d0c5 100644
--- a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/pyproject.toml
+++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/pyproject.toml
@@ -32,7 +32,7 @@ dependencies = [
[project.optional-dependencies]
instruments = [
- "openai >= 1.0.0",
+ "openai >= 1.26.0",
]
[project.entry-points.opentelemetry_instrumentor]
diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/src/opentelemetry/instrumentation/openai_v2/__init__.py b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/src/opentelemetry/instrumentation/openai_v2/__init__.py
index e8a782e404..ee3bbfdb73 100644
--- a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/src/opentelemetry/instrumentation/openai_v2/__init__.py
+++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/src/opentelemetry/instrumentation/openai_v2/__init__.py
@@ -52,7 +52,7 @@
from opentelemetry.semconv.schemas import Schemas
from opentelemetry.trace import get_tracer
-from .patch import chat_completions_create
+from .patch import async_chat_completions_create, chat_completions_create
class OpenAIInstrumentor(BaseInstrumentor):
@@ -84,7 +84,16 @@ def _instrument(self, **kwargs):
),
)
+ wrap_function_wrapper(
+ module="openai.resources.chat.completions",
+ name="AsyncCompletions.create",
+ wrapper=async_chat_completions_create(
+ tracer, event_logger, is_content_enabled()
+ ),
+ )
+
def _uninstrument(self, **kwargs):
import openai # pylint: disable=import-outside-toplevel
unwrap(openai.resources.chat.completions.Completions, "create")
+ unwrap(openai.resources.chat.completions.AsyncCompletions, "create")
diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/src/opentelemetry/instrumentation/openai_v2/patch.py b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/src/opentelemetry/instrumentation/openai_v2/patch.py
index 8540bff219..cd284473ce 100644
--- a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/src/opentelemetry/instrumentation/openai_v2/patch.py
+++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/src/opentelemetry/instrumentation/openai_v2/patch.py
@@ -21,15 +21,12 @@
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 (
choice_to_event,
get_llm_request_attributes,
+ handle_span_exception,
is_streaming,
message_to_event,
set_span_attribute,
@@ -72,12 +69,49 @@ def traced_method(wrapped, instance, args, kwargs):
return result
except Exception as error:
- span.set_status(Status(StatusCode.ERROR, str(error)))
+ handle_span_exception(span, error)
+ raise
+
+ return traced_method
+
+
+def async_chat_completions_create(
+ tracer: Tracer, event_logger: EventLogger, capture_content: bool
+):
+ """Wrap the `create` method of the `AsyncChatCompletion` class to trace it."""
+
+ async def traced_method(wrapped, instance, args, kwargs):
+ span_attributes = {**get_llm_request_attributes(kwargs, instance)}
+
+ span_name = f"{span_attributes[GenAIAttributes.GEN_AI_OPERATION_NAME]} {span_attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL]}"
+ with tracer.start_as_current_span(
+ name=span_name,
+ kind=SpanKind.CLIENT,
+ attributes=span_attributes,
+ end_on_exit=False,
+ ) as span:
+ if span.is_recording():
+ for message in kwargs.get("messages", []):
+ event_logger.emit(
+ message_to_event(message, capture_content)
+ )
+
+ try:
+ result = await wrapped(*args, **kwargs)
+ if is_streaming(kwargs):
+ return StreamWrapper(
+ result, span, event_logger, capture_content
+ )
+
if span.is_recording():
- span.set_attribute(
- ErrorAttributes.ERROR_TYPE, type(error).__qualname__
+ _set_response_attributes(
+ span, result, event_logger, capture_content
)
span.end()
+ return result
+
+ except Exception as error:
+ handle_span_exception(span, error)
raise
return traced_method
@@ -286,10 +320,19 @@ def __enter__(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__
- )
+ handle_span_exception(self.span, exc_val)
+ finally:
+ self.cleanup()
+ return False # Propagate the exception
+
+ async def __aenter__(self):
+ self.setup()
+ return self
+
+ async def __aexit__(self, exc_type, exc_val, exc_tb):
+ try:
+ if exc_type is not None:
+ handle_span_exception(self.span, exc_val)
finally:
self.cleanup()
return False # Propagate the exception
@@ -301,6 +344,9 @@ def close(self):
def __iter__(self):
return self
+ def __aiter__(self):
+ return self
+
def __next__(self):
try:
chunk = next(self.stream)
@@ -310,10 +356,20 @@ def __next__(self):
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__
- )
+ handle_span_exception(self.span, error)
+ self.cleanup()
+ raise
+
+ async def __anext__(self):
+ try:
+ chunk = await self.stream.__anext__()
+ self.process_chunk(chunk)
+ return chunk
+ except StopAsyncIteration:
+ self.cleanup()
+ raise
+ except Exception as error:
+ handle_span_exception(self.span, error)
self.cleanup()
raise
diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/src/opentelemetry/instrumentation/openai_v2/utils.py b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/src/opentelemetry/instrumentation/openai_v2/utils.py
index a3a2d317ce..cf920c17ee 100644
--- a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/src/opentelemetry/instrumentation/openai_v2/utils.py
+++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/src/opentelemetry/instrumentation/openai_v2/utils.py
@@ -26,6 +26,10 @@
from opentelemetry.semconv._incubating.attributes import (
server_attributes as ServerAttributes,
)
+from opentelemetry.semconv.attributes import (
+ error_attributes as ErrorAttributes,
+)
+from opentelemetry.trace.status import Status, StatusCode
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT = (
"OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT"
@@ -138,9 +142,11 @@ def choice_to_event(choice, capture_content):
if choice.message:
message = {
- "role": choice.message.role
- if choice.message and choice.message.role
- else None
+ "role": (
+ choice.message.role
+ if choice.message and choice.message.role
+ else None
+ )
}
tool_calls = extract_tool_calls(choice.message, capture_content)
if tool_calls:
@@ -210,3 +216,12 @@ def get_llm_request_attributes(
# filter out None values
return {k: v for k, v in attributes.items() if v is not None}
+
+
+def handle_span_exception(span, error):
+ span.set_status(Status(StatusCode.ERROR, str(error)))
+ if span.is_recording():
+ span.set_attribute(
+ ErrorAttributes.ERROR_TYPE, type(error).__qualname__
+ )
+ span.end()
diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/test-requirements-0.txt b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/test-requirements-0.txt
index 7a15734872..5e1693b69a 100644
--- a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/test-requirements-0.txt
+++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/test-requirements-0.txt
@@ -5,6 +5,7 @@ importlib-metadata==6.11.0
packaging==24.0
pytest==7.4.4
pytest-vcr==1.0.2
+pytest-asyncio==0.21.0
wrapt==1.16.0
opentelemetry-api==1.28 # when updating, also update in pyproject.toml
opentelemetry-sdk==1.28 # when updating, also update in pyproject.toml
diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/test-requirements-1.txt b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/test-requirements-1.txt
index ded849c8ee..618410edd3 100644
--- a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/test-requirements-1.txt
+++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/test-requirements-1.txt
@@ -5,6 +5,7 @@ importlib-metadata==6.11.0
packaging==24.0
pytest==7.4.4
pytest-vcr==1.0.2
+pytest-asyncio==0.21.0
wrapt==1.16.0
# test with the latest version of opentelemetry-api, sdk, and semantic conventions
diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_async_chat_completion_404.yaml b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_async_chat_completion_404.yaml
new file mode 100644
index 0000000000..e055e68f20
--- /dev/null
+++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_async_chat_completion_404.yaml
@@ -0,0 +1,89 @@
+interactions:
+- request:
+ body: |-
+ {
+ "messages": [
+ {
+ "role": "user",
+ "content": "Say this is a test"
+ }
+ ],
+ "model": "this-model-does-not-exist"
+ }
+ headers:
+ accept:
+ - application/json
+ accept-encoding:
+ - gzip, deflate
+ authorization:
+ - Bearer test_openai_api_key
+ connection:
+ - keep-alive
+ content-length:
+ - '103'
+ content-type:
+ - application/json
+ host:
+ - api.openai.com
+ user-agent:
+ - AsyncOpenAI/Python 1.26.0
+ x-stainless-arch:
+ - arm64
+ x-stainless-async:
+ - async:asyncio
+ x-stainless-lang:
+ - python
+ x-stainless-os:
+ - MacOS
+ x-stainless-package-version:
+ - 1.26.0
+ x-stainless-runtime:
+ - CPython
+ x-stainless-runtime-version:
+ - 3.12.5
+ method: POST
+ uri: https://api.openai.com/v1/chat/completions
+ response:
+ body:
+ string: |-
+ {
+ "error": {
+ "message": "The model `this-model-does-not-exist` does not exist or you do not have access to it.",
+ "type": "invalid_request_error",
+ "param": null,
+ "code": "model_not_found"
+ }
+ }
+ headers:
+ CF-Cache-Status:
+ - DYNAMIC
+ CF-RAY:
+ - 8e1a80827a861852-MRS
+ Connection:
+ - keep-alive
+ Content-Type:
+ - application/json; charset=utf-8
+ Date:
+ - Wed, 13 Nov 2024 00:04:01 GMT
+ Server:
+ - cloudflare
+ Set-Cookie: test_set_cookie
+ Transfer-Encoding:
+ - chunked
+ X-Content-Type-Options:
+ - nosniff
+ alt-svc:
+ - h3=":443"; ma=86400
+ content-length:
+ - '231'
+ openai-organization: test_openai_org_id
+ strict-transport-security:
+ - max-age=31536000; includeSubDomains; preload
+ vary:
+ - Origin
+ x-request-id:
+ - req_5cf06a7fabd45ebe21ee38c14c5b2f76
+ status:
+ code: 404
+ message: Not Found
+version: 1
diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_async_chat_completion_extra_params.yaml b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_async_chat_completion_extra_params.yaml
new file mode 100644
index 0000000000..3d13c9344e
--- /dev/null
+++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_async_chat_completion_extra_params.yaml
@@ -0,0 +1,137 @@
+interactions:
+- request:
+ body: |-
+ {
+ "messages": [
+ {
+ "role": "user",
+ "content": "Say this is a test"
+ }
+ ],
+ "model": "gpt-4o-mini",
+ "max_tokens": 50,
+ "seed": 42,
+ "stream": false,
+ "temperature": 0.5,
+ "service_tier": "default"
+ }
+ headers:
+ accept:
+ - application/json
+ accept-encoding:
+ - gzip, deflate
+ authorization:
+ - Bearer test_openai_api_key
+ connection:
+ - keep-alive
+ content-length:
+ - '183'
+ content-type:
+ - application/json
+ host:
+ - api.openai.com
+ user-agent:
+ - AsyncOpenAI/Python 1.26.0
+ x-stainless-arch:
+ - arm64
+ x-stainless-async:
+ - async:asyncio
+ x-stainless-lang:
+ - python
+ x-stainless-os:
+ - MacOS
+ x-stainless-package-version:
+ - 1.26.0
+ x-stainless-runtime:
+ - CPython
+ x-stainless-runtime-version:
+ - 3.12.5
+ method: POST
+ uri: https://api.openai.com/v1/chat/completions
+ response:
+ body:
+ string: |-
+ {
+ "id": "chatcmpl-ASv9WMTAMZY4O1EImv3csZa6Ch7KI",
+ "object": "chat.completion",
+ "created": 1731456242,
+ "model": "gpt-4o-mini-2024-07-18",
+ "choices": [
+ {
+ "index": 0,
+ "message": {
+ "role": "assistant",
+ "content": "This is a test. How can I assist you further?",
+ "refusal": null
+ },
+ "logprobs": null,
+ "finish_reason": "stop"
+ }
+ ],
+ "usage": {
+ "prompt_tokens": 12,
+ "completion_tokens": 12,
+ "total_tokens": 24,
+ "prompt_tokens_details": {
+ "cached_tokens": 0,
+ "audio_tokens": 0
+ },
+ "completion_tokens_details": {
+ "reasoning_tokens": 0,
+ "audio_tokens": 0,
+ "accepted_prediction_tokens": 0,
+ "rejected_prediction_tokens": 0
+ }
+ },
+ "service_tier": "default",
+ "system_fingerprint": "fp_0ba0d124f1"
+ }
+ headers:
+ CF-Cache-Status:
+ - DYNAMIC
+ CF-RAY:
+ - 8e1a8088f867e167-MRS
+ Connection:
+ - keep-alive
+ Content-Type:
+ - application/json
+ Date:
+ - Wed, 13 Nov 2024 00:04:02 GMT
+ Server:
+ - cloudflare
+ Set-Cookie: test_set_cookie
+ Transfer-Encoding:
+ - chunked
+ X-Content-Type-Options:
+ - nosniff
+ access-control-expose-headers:
+ - X-Request-ID
+ alt-svc:
+ - h3=":443"; ma=86400
+ content-length:
+ - '825'
+ openai-organization: test_openai_org_id
+ openai-processing-ms:
+ - '488'
+ openai-version:
+ - '2020-10-01'
+ strict-transport-security:
+ - max-age=31536000; includeSubDomains; preload
+ x-ratelimit-limit-requests:
+ - '30000'
+ x-ratelimit-limit-tokens:
+ - '150000000'
+ x-ratelimit-remaining-requests:
+ - '29999'
+ x-ratelimit-remaining-tokens:
+ - '149999943'
+ x-ratelimit-reset-requests:
+ - 2ms
+ x-ratelimit-reset-tokens:
+ - 0s
+ x-request-id:
+ - req_6df08d6267415e8f5db3628a6757edad
+ status:
+ code: 200
+ message: OK
+version: 1
diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_async_chat_completion_multiple_choices.yaml b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_async_chat_completion_multiple_choices.yaml
new file mode 100644
index 0000000000..1404b8163a
--- /dev/null
+++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_async_chat_completion_multiple_choices.yaml
@@ -0,0 +1,143 @@
+interactions:
+- request:
+ body: |-
+ {
+ "messages": [
+ {
+ "role": "user",
+ "content": "Say this is a test"
+ }
+ ],
+ "model": "gpt-4o-mini",
+ "n": 2,
+ "stream": false
+ }
+ headers:
+ accept:
+ - application/json
+ accept-encoding:
+ - gzip, deflate
+ authorization:
+ - Bearer test_openai_api_key
+ connection:
+ - keep-alive
+ content-length:
+ - '114'
+ content-type:
+ - application/json
+ host:
+ - api.openai.com
+ user-agent:
+ - AsyncOpenAI/Python 1.26.0
+ x-stainless-arch:
+ - arm64
+ x-stainless-async:
+ - async:asyncio
+ x-stainless-lang:
+ - python
+ x-stainless-os:
+ - MacOS
+ x-stainless-package-version:
+ - 1.26.0
+ x-stainless-runtime:
+ - CPython
+ x-stainless-runtime-version:
+ - 3.12.5
+ method: POST
+ uri: https://api.openai.com/v1/chat/completions
+ response:
+ body:
+ string: |-
+ {
+ "id": "chatcmpl-ASv9XLlMmT7H3cf50dNTesHDBDwX5",
+ "object": "chat.completion",
+ "created": 1731456243,
+ "model": "gpt-4o-mini-2024-07-18",
+ "choices": [
+ {
+ "index": 0,
+ "message": {
+ "role": "assistant",
+ "content": "This is a test.",
+ "refusal": null
+ },
+ "logprobs": null,
+ "finish_reason": "stop"
+ },
+ {
+ "index": 1,
+ "message": {
+ "role": "assistant",
+ "content": "This is a test.",
+ "refusal": null
+ },
+ "logprobs": null,
+ "finish_reason": "stop"
+ }
+ ],
+ "usage": {
+ "prompt_tokens": 12,
+ "completion_tokens": 10,
+ "total_tokens": 22,
+ "prompt_tokens_details": {
+ "cached_tokens": 0,
+ "audio_tokens": 0
+ },
+ "completion_tokens_details": {
+ "reasoning_tokens": 0,
+ "audio_tokens": 0,
+ "accepted_prediction_tokens": 0,
+ "rejected_prediction_tokens": 0
+ }
+ },
+ "system_fingerprint": "fp_0ba0d124f1"
+ }
+ headers:
+ CF-Cache-Status:
+ - DYNAMIC
+ CF-RAY:
+ - 8e1a808f6d8e0d8b-MRS
+ Connection:
+ - keep-alive
+ Content-Type:
+ - application/json
+ Date:
+ - Wed, 13 Nov 2024 00:04:04 GMT
+ Server:
+ - cloudflare
+ Set-Cookie: test_set_cookie
+ Transfer-Encoding:
+ - chunked
+ X-Content-Type-Options:
+ - nosniff
+ access-control-expose-headers:
+ - X-Request-ID
+ alt-svc:
+ - h3=":443"; ma=86400
+ content-length:
+ - '970'
+ openai-organization: test_openai_org_id
+ openai-processing-ms:
+ - '306'
+ openai-version:
+ - '2020-10-01'
+ strict-transport-security:
+ - max-age=31536000; includeSubDomains; preload
+ x-ratelimit-limit-requests:
+ - '30000'
+ x-ratelimit-limit-tokens:
+ - '150000000'
+ x-ratelimit-remaining-requests:
+ - '29999'
+ x-ratelimit-remaining-tokens:
+ - '149999962'
+ x-ratelimit-reset-requests:
+ - 2ms
+ x-ratelimit-reset-tokens:
+ - 0s
+ x-request-id:
+ - req_1317908e0f9b73276b57d4e171c533ea
+ status:
+ code: 200
+ message: OK
+version: 1
diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_async_chat_completion_multiple_choices_streaming.yaml b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_async_chat_completion_multiple_choices_streaming.yaml
new file mode 100644
index 0000000000..4bca03a9e8
--- /dev/null
+++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_async_chat_completion_multiple_choices_streaming.yaml
@@ -0,0 +1,382 @@
+interactions:
+- request:
+ body: |-
+ {
+ "messages": [
+ {
+ "role": "system",
+ "content": "You're a helpful assistant."
+ },
+ {
+ "role": "user",
+ "content": "What's the weather in Seattle and San Francisco today?"
+ }
+ ],
+ "model": "gpt-4o-mini",
+ "n": 2,
+ "stream": true,
+ "stream_options": {
+ "include_usage": true
+ }
+ }
+ headers:
+ accept:
+ - application/json
+ accept-encoding:
+ - gzip, deflate
+ authorization:
+ - Bearer test_openai_api_key
+ connection:
+ - keep-alive
+ content-length:
+ - '254'
+ content-type:
+ - application/json
+ host:
+ - api.openai.com
+ user-agent:
+ - AsyncOpenAI/Python 1.26.0
+ x-stainless-arch:
+ - arm64
+ x-stainless-async:
+ - async:asyncio
+ x-stainless-lang:
+ - python
+ x-stainless-os:
+ - MacOS
+ x-stainless-package-version:
+ - 1.26.0
+ x-stainless-runtime:
+ - CPython
+ x-stainless-runtime-version:
+ - 3.12.5
+ method: POST
+ uri: https://api.openai.com/v1/chat/completions
+ response:
+ body:
+ string: |+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":"I'm"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":"I'm"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" unable"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" unable"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" to"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" to"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" provide"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" provide"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" real"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" real"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":"-time"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":"-time"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" weather"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" weather"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" updates"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" updates"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" as"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" as"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" my"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" my"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" knowledge"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" knowledge"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" was"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" only"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" last"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" extends"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" until"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" updated"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" in"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" October"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" October"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" "},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" "},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":"202"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":"202"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":"3"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":"1"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":","},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":","},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" and"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" and"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" I"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" I"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" don't"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" have"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" access"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" to"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" don't"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" have"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" access"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" to"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" live"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" live"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" data"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":"."},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" data"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":"."},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" However"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":","},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" However"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":","},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" you"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" you"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" can"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" can"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" easily"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" easily"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" check"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" check"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" the"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" the"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" current"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" current"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" weather"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" weather"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" in"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" for"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" Seattle"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" Seattle"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" and"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" and"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" San"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" San"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" Francisco"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" Francisco"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" by"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" using"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" visiting"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" a"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" weather"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" a"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" weather"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" website"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" website"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" or"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" or"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" a"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" using"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" mobile"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" a"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" app"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" weather"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" for"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" app"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" the"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":"."},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" most"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" If"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" accurate"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" you"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" and"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" need"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" up"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" historical"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" weather"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" information"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" or"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" general"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" climate"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" data"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" for"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" those"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" cities"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":","},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" feel"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" free"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" to"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" ask"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":"!"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":"-to"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":"-date"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" information"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":"."},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9hB9He94oQyZr1CDC8coqvmn5U","object":"chat.completion.chunk","created":1731456253,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[],"usage":{"prompt_tokens":26,"completion_tokens":133,"total_tokens":159,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}}}
+
+ data: [DONE]
+
+ headers:
+ CF-Cache-Status:
+ - DYNAMIC
+ CF-RAY:
+ - 8e1a80ceac3ce19a-MRS
+ Connection:
+ - keep-alive
+ Content-Type:
+ - text/event-stream; charset=utf-8
+ Date:
+ - Wed, 13 Nov 2024 00:04:13 GMT
+ Server:
+ - cloudflare
+ Set-Cookie: test_set_cookie
+ Transfer-Encoding:
+ - chunked
+ X-Content-Type-Options:
+ - nosniff
+ access-control-expose-headers:
+ - X-Request-ID
+ alt-svc:
+ - h3=":443"; ma=86400
+ openai-organization: test_openai_org_id
+ openai-processing-ms:
+ - '126'
+ openai-version:
+ - '2020-10-01'
+ strict-transport-security:
+ - max-age=31536000; includeSubDomains; preload
+ x-ratelimit-limit-requests:
+ - '30000'
+ x-ratelimit-limit-tokens:
+ - '150000000'
+ x-ratelimit-remaining-requests:
+ - '29999'
+ x-ratelimit-remaining-tokens:
+ - '149999945'
+ x-ratelimit-reset-requests:
+ - 2ms
+ x-ratelimit-reset-tokens:
+ - 0s
+ x-request-id:
+ - req_5dd8b6845db59fa55cf226eda1f5a2c6
+ status:
+ code: 200
+ message: OK
+version: 1
diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_async_chat_completion_multiple_tools_streaming_no_content.yaml b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_async_chat_completion_multiple_tools_streaming_no_content.yaml
new file mode 100644
index 0000000000..19319de476
--- /dev/null
+++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_async_chat_completion_multiple_tools_streaming_no_content.yaml
@@ -0,0 +1,164 @@
+interactions:
+- request:
+ body: |-
+ {
+ "messages": [
+ {
+ "role": "system",
+ "content": "You're a helpful assistant."
+ },
+ {
+ "role": "user",
+ "content": "What's the weather in Seattle and San Francisco today?"
+ }
+ ],
+ "model": "gpt-4o-mini",
+ "stream": true,
+ "stream_options": {
+ "include_usage": true
+ },
+ "tool_choice": "auto",
+ "tools": [
+ {
+ "type": "function",
+ "function": {
+ "name": "get_current_weather",
+ "description": "Get the current weather in a given location",
+ "parameters": {
+ "type": "object",
+ "properties": {
+ "location": {
+ "type": "string",
+ "description": "The city and state, e.g. Boston, MA"
+ }
+ },
+ "required": [
+ "location"
+ ],
+ "additionalProperties": false
+ }
+ }
+ }
+ ]
+ }
+ headers:
+ accept:
+ - application/json
+ accept-encoding:
+ - gzip, deflate
+ authorization:
+ - Bearer test_openai_api_key
+ connection:
+ - keep-alive
+ content-length:
+ - '602'
+ content-type:
+ - application/json
+ host:
+ - api.openai.com
+ user-agent:
+ - AsyncOpenAI/Python 1.26.0
+ x-stainless-arch:
+ - arm64
+ x-stainless-async:
+ - async:asyncio
+ x-stainless-lang:
+ - python
+ x-stainless-os:
+ - MacOS
+ x-stainless-package-version:
+ - 1.26.0
+ x-stainless-runtime:
+ - CPython
+ x-stainless-runtime-version:
+ - 3.12.5
+ method: POST
+ uri: https://api.openai.com/v1/chat/completions
+ response:
+ body:
+ string: |+
+ data: {"id":"chatcmpl-ASv9l0RKJrq2fTx2dK5jhJoIr4rMI","object":"chat.completion.chunk","created":1731456257,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"role":"assistant","content":null},"logprobs":null,"finish_reason":null}]}
+
+ data: {"id":"chatcmpl-ASv9l0RKJrq2fTx2dK5jhJoIr4rMI","object":"chat.completion.chunk","created":1731456257,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"id":"call_hqkL24CLEwnniv4GDrjk14Iu","type":"function","function":{"name":"get_current_weather","arguments":""}}]},"logprobs":null,"finish_reason":null}]}
+
+ data: {"id":"chatcmpl-ASv9l0RKJrq2fTx2dK5jhJoIr4rMI","object":"chat.completion.chunk","created":1731456257,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\"lo"}}]},"logprobs":null,"finish_reason":null}]}
+
+ data: {"id":"chatcmpl-ASv9l0RKJrq2fTx2dK5jhJoIr4rMI","object":"chat.completion.chunk","created":1731456257,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"catio"}}]},"logprobs":null,"finish_reason":null}]}
+
+ data: {"id":"chatcmpl-ASv9l0RKJrq2fTx2dK5jhJoIr4rMI","object":"chat.completion.chunk","created":1731456257,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"n\": \"S"}}]},"logprobs":null,"finish_reason":null}]}
+
+ data: {"id":"chatcmpl-ASv9l0RKJrq2fTx2dK5jhJoIr4rMI","object":"chat.completion.chunk","created":1731456257,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"eatt"}}]},"logprobs":null,"finish_reason":null}]}
+
+ data: {"id":"chatcmpl-ASv9l0RKJrq2fTx2dK5jhJoIr4rMI","object":"chat.completion.chunk","created":1731456257,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"le, W"}}]},"logprobs":null,"finish_reason":null}]}
+
+ data: {"id":"chatcmpl-ASv9l0RKJrq2fTx2dK5jhJoIr4rMI","object":"chat.completion.chunk","created":1731456257,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"A\"}"}}]},"logprobs":null,"finish_reason":null}]}
+
+ data: {"id":"chatcmpl-ASv9l0RKJrq2fTx2dK5jhJoIr4rMI","object":"chat.completion.chunk","created":1731456257,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"id":"call_0s1enkFttXjIR7ozHoGMcnUu","type":"function","function":{"name":"get_current_weather","arguments":""}}]},"logprobs":null,"finish_reason":null}]}
+
+ data: {"id":"chatcmpl-ASv9l0RKJrq2fTx2dK5jhJoIr4rMI","object":"chat.completion.chunk","created":1731456257,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"{\"lo"}}]},"logprobs":null,"finish_reason":null}]}
+
+ data: {"id":"chatcmpl-ASv9l0RKJrq2fTx2dK5jhJoIr4rMI","object":"chat.completion.chunk","created":1731456257,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"catio"}}]},"logprobs":null,"finish_reason":null}]}
+
+ data: {"id":"chatcmpl-ASv9l0RKJrq2fTx2dK5jhJoIr4rMI","object":"chat.completion.chunk","created":1731456257,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"n\": \"S"}}]},"logprobs":null,"finish_reason":null}]}
+
+ data: {"id":"chatcmpl-ASv9l0RKJrq2fTx2dK5jhJoIr4rMI","object":"chat.completion.chunk","created":1731456257,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"an F"}}]},"logprobs":null,"finish_reason":null}]}
+
+ data: {"id":"chatcmpl-ASv9l0RKJrq2fTx2dK5jhJoIr4rMI","object":"chat.completion.chunk","created":1731456257,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"ranci"}}]},"logprobs":null,"finish_reason":null}]}
+
+ data: {"id":"chatcmpl-ASv9l0RKJrq2fTx2dK5jhJoIr4rMI","object":"chat.completion.chunk","created":1731456257,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"sco, C"}}]},"logprobs":null,"finish_reason":null}]}
+
+ data: {"id":"chatcmpl-ASv9l0RKJrq2fTx2dK5jhJoIr4rMI","object":"chat.completion.chunk","created":1731456257,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"A\"}"}}]},"logprobs":null,"finish_reason":null}]}
+
+ data: {"id":"chatcmpl-ASv9l0RKJrq2fTx2dK5jhJoIr4rMI","object":"chat.completion.chunk","created":1731456257,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"tool_calls"}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9l0RKJrq2fTx2dK5jhJoIr4rMI","object":"chat.completion.chunk","created":1731456257,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[],"usage":{"prompt_tokens":75,"completion_tokens":51,"total_tokens":126,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}}}
+
+ data: [DONE]
+
+ headers:
+ CF-Cache-Status:
+ - DYNAMIC
+ CF-RAY:
+ - 8e1a80e4cfb00d86-MRS
+ Connection:
+ - keep-alive
+ Content-Type:
+ - text/event-stream; charset=utf-8
+ Date:
+ - Wed, 13 Nov 2024 00:04:19 GMT
+ Server:
+ - cloudflare
+ Set-Cookie: test_set_cookie
+ Transfer-Encoding:
+ - chunked
+ X-Content-Type-Options:
+ - nosniff
+ access-control-expose-headers:
+ - X-Request-ID
+ alt-svc:
+ - h3=":443"; ma=86400
+ openai-organization: test_openai_org_id
+ openai-processing-ms:
+ - '1597'
+ openai-version:
+ - '2020-10-01'
+ strict-transport-security:
+ - max-age=31536000; includeSubDomains; preload
+ x-ratelimit-limit-requests:
+ - '30000'
+ x-ratelimit-limit-tokens:
+ - '150000000'
+ x-ratelimit-remaining-requests:
+ - '29999'
+ x-ratelimit-remaining-tokens:
+ - '149999960'
+ x-ratelimit-reset-requests:
+ - 2ms
+ x-ratelimit-reset-tokens:
+ - 0s
+ x-request-id:
+ - req_487aef2347cb4d1f97077c488dd93628
+ status:
+ code: 200
+ message: OK
+version: 1
diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_async_chat_completion_multiple_tools_streaming_with_content.yaml b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_async_chat_completion_multiple_tools_streaming_with_content.yaml
new file mode 100644
index 0000000000..a026912ee1
--- /dev/null
+++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_async_chat_completion_multiple_tools_streaming_with_content.yaml
@@ -0,0 +1,164 @@
+interactions:
+- request:
+ body: |-
+ {
+ "messages": [
+ {
+ "role": "system",
+ "content": "You're a helpful assistant."
+ },
+ {
+ "role": "user",
+ "content": "What's the weather in Seattle and San Francisco today?"
+ }
+ ],
+ "model": "gpt-4o-mini",
+ "stream": true,
+ "stream_options": {
+ "include_usage": true
+ },
+ "tool_choice": "auto",
+ "tools": [
+ {
+ "type": "function",
+ "function": {
+ "name": "get_current_weather",
+ "description": "Get the current weather in a given location",
+ "parameters": {
+ "type": "object",
+ "properties": {
+ "location": {
+ "type": "string",
+ "description": "The city and state, e.g. Boston, MA"
+ }
+ },
+ "required": [
+ "location"
+ ],
+ "additionalProperties": false
+ }
+ }
+ }
+ ]
+ }
+ headers:
+ accept:
+ - application/json
+ accept-encoding:
+ - gzip, deflate
+ authorization:
+ - Bearer test_openai_api_key
+ connection:
+ - keep-alive
+ content-length:
+ - '602'
+ content-type:
+ - application/json
+ host:
+ - api.openai.com
+ user-agent:
+ - AsyncOpenAI/Python 1.26.0
+ x-stainless-arch:
+ - arm64
+ x-stainless-async:
+ - async:asyncio
+ x-stainless-lang:
+ - python
+ x-stainless-os:
+ - MacOS
+ x-stainless-package-version:
+ - 1.26.0
+ x-stainless-runtime:
+ - CPython
+ x-stainless-runtime-version:
+ - 3.12.5
+ method: POST
+ uri: https://api.openai.com/v1/chat/completions
+ response:
+ body:
+ string: |+
+ data: {"id":"chatcmpl-ASv9jfgm5JguNGaR9o9u94HpuhV7T","object":"chat.completion.chunk","created":1731456255,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"role":"assistant","content":null},"logprobs":null,"finish_reason":null}]}
+
+ data: {"id":"chatcmpl-ASv9jfgm5JguNGaR9o9u94HpuhV7T","object":"chat.completion.chunk","created":1731456255,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"id":"call_oJL2dc4GjWVxqBtWlGLwjbsR","type":"function","function":{"name":"get_current_weather","arguments":""}}]},"logprobs":null,"finish_reason":null}]}
+
+ data: {"id":"chatcmpl-ASv9jfgm5JguNGaR9o9u94HpuhV7T","object":"chat.completion.chunk","created":1731456255,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\"lo"}}]},"logprobs":null,"finish_reason":null}]}
+
+ data: {"id":"chatcmpl-ASv9jfgm5JguNGaR9o9u94HpuhV7T","object":"chat.completion.chunk","created":1731456255,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"catio"}}]},"logprobs":null,"finish_reason":null}]}
+
+ data: {"id":"chatcmpl-ASv9jfgm5JguNGaR9o9u94HpuhV7T","object":"chat.completion.chunk","created":1731456255,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"n\": \"S"}}]},"logprobs":null,"finish_reason":null}]}
+
+ data: {"id":"chatcmpl-ASv9jfgm5JguNGaR9o9u94HpuhV7T","object":"chat.completion.chunk","created":1731456255,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"eatt"}}]},"logprobs":null,"finish_reason":null}]}
+
+ data: {"id":"chatcmpl-ASv9jfgm5JguNGaR9o9u94HpuhV7T","object":"chat.completion.chunk","created":1731456255,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"le, W"}}]},"logprobs":null,"finish_reason":null}]}
+
+ data: {"id":"chatcmpl-ASv9jfgm5JguNGaR9o9u94HpuhV7T","object":"chat.completion.chunk","created":1731456255,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"A\"}"}}]},"logprobs":null,"finish_reason":null}]}
+
+ data: {"id":"chatcmpl-ASv9jfgm5JguNGaR9o9u94HpuhV7T","object":"chat.completion.chunk","created":1731456255,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"id":"call_ON3lp1OWsbw2obNRD43KVDp6","type":"function","function":{"name":"get_current_weather","arguments":""}}]},"logprobs":null,"finish_reason":null}]}
+
+ data: {"id":"chatcmpl-ASv9jfgm5JguNGaR9o9u94HpuhV7T","object":"chat.completion.chunk","created":1731456255,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"{\"lo"}}]},"logprobs":null,"finish_reason":null}]}
+
+ data: {"id":"chatcmpl-ASv9jfgm5JguNGaR9o9u94HpuhV7T","object":"chat.completion.chunk","created":1731456255,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"catio"}}]},"logprobs":null,"finish_reason":null}]}
+
+ data: {"id":"chatcmpl-ASv9jfgm5JguNGaR9o9u94HpuhV7T","object":"chat.completion.chunk","created":1731456255,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"n\": \"S"}}]},"logprobs":null,"finish_reason":null}]}
+
+ data: {"id":"chatcmpl-ASv9jfgm5JguNGaR9o9u94HpuhV7T","object":"chat.completion.chunk","created":1731456255,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"an F"}}]},"logprobs":null,"finish_reason":null}]}
+
+ data: {"id":"chatcmpl-ASv9jfgm5JguNGaR9o9u94HpuhV7T","object":"chat.completion.chunk","created":1731456255,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"ranci"}}]},"logprobs":null,"finish_reason":null}]}
+
+ data: {"id":"chatcmpl-ASv9jfgm5JguNGaR9o9u94HpuhV7T","object":"chat.completion.chunk","created":1731456255,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"sco, C"}}]},"logprobs":null,"finish_reason":null}]}
+
+ data: {"id":"chatcmpl-ASv9jfgm5JguNGaR9o9u94HpuhV7T","object":"chat.completion.chunk","created":1731456255,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"A\"}"}}]},"logprobs":null,"finish_reason":null}]}
+
+ data: {"id":"chatcmpl-ASv9jfgm5JguNGaR9o9u94HpuhV7T","object":"chat.completion.chunk","created":1731456255,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"tool_calls"}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9jfgm5JguNGaR9o9u94HpuhV7T","object":"chat.completion.chunk","created":1731456255,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[],"usage":{"prompt_tokens":75,"completion_tokens":51,"total_tokens":126,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}}}
+
+ data: [DONE]
+
+ headers:
+ CF-Cache-Status:
+ - DYNAMIC
+ CF-RAY:
+ - 8e1a80d8efb9e1c8-MRS
+ Connection:
+ - keep-alive
+ Content-Type:
+ - text/event-stream; charset=utf-8
+ Date:
+ - Wed, 13 Nov 2024 00:04:16 GMT
+ Server:
+ - cloudflare
+ Set-Cookie: test_set_cookie
+ Transfer-Encoding:
+ - chunked
+ X-Content-Type-Options:
+ - nosniff
+ access-control-expose-headers:
+ - X-Request-ID
+ alt-svc:
+ - h3=":443"; ma=86400
+ openai-organization: test_openai_org_id
+ openai-processing-ms:
+ - '1162'
+ openai-version:
+ - '2020-10-01'
+ strict-transport-security:
+ - max-age=31536000; includeSubDomains; preload
+ x-ratelimit-limit-requests:
+ - '30000'
+ x-ratelimit-limit-tokens:
+ - '150000000'
+ x-ratelimit-remaining-requests:
+ - '29999'
+ x-ratelimit-remaining-tokens:
+ - '149999960'
+ x-ratelimit-reset-requests:
+ - 2ms
+ x-ratelimit-reset-tokens:
+ - 0s
+ x-request-id:
+ - req_0b6729aef347cecd61ba3b7b7a8d4719
+ status:
+ code: 200
+ message: OK
+version: 1
diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_async_chat_completion_streaming.yaml b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_async_chat_completion_streaming.yaml
new file mode 100644
index 0000000000..efffcd7423
--- /dev/null
+++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_async_chat_completion_streaming.yaml
@@ -0,0 +1,117 @@
+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
+ authorization:
+ - Bearer test_openai_api_key
+ connection:
+ - keep-alive
+ content-length:
+ - '142'
+ content-type:
+ - application/json
+ host:
+ - api.openai.com
+ user-agent:
+ - AsyncOpenAI/Python 1.26.0
+ x-stainless-arch:
+ - arm64
+ x-stainless-async:
+ - async:asyncio
+ x-stainless-lang:
+ - python
+ x-stainless-os:
+ - MacOS
+ x-stainless-package-version:
+ - 1.26.0
+ x-stainless-runtime:
+ - CPython
+ x-stainless-runtime-version:
+ - 3.12.5
+ method: POST
+ uri: https://api.openai.com/v1/chat/completions
+ response:
+ body:
+ string: |+
+ data: {"id":"chatcmpl-ASv9ejXDUtAhGOJJxWuw026zdinc4","object":"chat.completion.chunk","created":1731456250,"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-ASv9ejXDUtAhGOJJxWuw026zdinc4","object":"chat.completion.chunk","created":1731456250,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"This"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9ejXDUtAhGOJJxWuw026zdinc4","object":"chat.completion.chunk","created":1731456250,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" is"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9ejXDUtAhGOJJxWuw026zdinc4","object":"chat.completion.chunk","created":1731456250,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" a"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9ejXDUtAhGOJJxWuw026zdinc4","object":"chat.completion.chunk","created":1731456250,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" test"},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9ejXDUtAhGOJJxWuw026zdinc4","object":"chat.completion.chunk","created":1731456250,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"."},"logprobs":null,"finish_reason":null}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9ejXDUtAhGOJJxWuw026zdinc4","object":"chat.completion.chunk","created":1731456250,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null}
+
+ data: {"id":"chatcmpl-ASv9ejXDUtAhGOJJxWuw026zdinc4","object":"chat.completion.chunk","created":1731456250,"model":"gpt-4-0613","system_fingerprint":null,"choices":[],"usage":{"prompt_tokens":12,"completion_tokens":5,"total_tokens":17,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}}}
+
+ data: [DONE]
+
+ headers:
+ CF-Cache-Status:
+ - DYNAMIC
+ CF-RAY:
+ - 8e1a80bd2f31e1e5-MRS
+ Connection:
+ - keep-alive
+ Content-Type:
+ - text/event-stream; charset=utf-8
+ Date:
+ - Wed, 13 Nov 2024 00:04:11 GMT
+ Server:
+ - cloudflare
+ Set-Cookie: test_set_cookie
+ Transfer-Encoding:
+ - chunked
+ X-Content-Type-Options:
+ - nosniff
+ access-control-expose-headers:
+ - X-Request-ID
+ alt-svc:
+ - h3=":443"; ma=86400
+ openai-organization: test_openai_org_id
+ openai-processing-ms:
+ - '196'
+ 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_cc9204ae23338b130df11c8c5b5f31af
+ status:
+ code: 200
+ message: OK
+version: 1
diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_async_chat_completion_streaming_not_complete.yaml b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_async_chat_completion_streaming_not_complete.yaml
new file mode 100644
index 0000000000..9ef5613d17
--- /dev/null
+++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_async_chat_completion_streaming_not_complete.yaml
@@ -0,0 +1,112 @@
+interactions:
+- request:
+ body: |-
+ {
+ "messages": [
+ {
+ "role": "user",
+ "content": "Say this is a test"
+ }
+ ],
+ "model": "gpt-4",
+ "stream": true
+ }
+ headers:
+ accept:
+ - application/json
+ accept-encoding:
+ - gzip, deflate
+ authorization:
+ - Bearer test_openai_api_key
+ connection:
+ - keep-alive
+ content-length:
+ - '99'
+ content-type:
+ - application/json
+ host:
+ - api.openai.com
+ user-agent:
+ - AsyncOpenAI/Python 1.26.0
+ x-stainless-arch:
+ - arm64
+ x-stainless-async:
+ - async:asyncio
+ x-stainless-lang:
+ - python
+ x-stainless-os:
+ - MacOS
+ x-stainless-package-version:
+ - 1.26.0
+ x-stainless-runtime:
+ - CPython
+ x-stainless-runtime-version:
+ - 3.12.5
+ method: POST
+ uri: https://api.openai.com/v1/chat/completions
+ response:
+ body:
+ string: |+
+ data: {"id":"chatcmpl-ASv9gROIIAvRs9QnmLP8Nzs3PGMCX","object":"chat.completion.chunk","created":1731456252,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}]}
+
+ data: {"id":"chatcmpl-ASv9gROIIAvRs9QnmLP8Nzs3PGMCX","object":"chat.completion.chunk","created":1731456252,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"This"},"logprobs":null,"finish_reason":null}]}
+
+ data: {"id":"chatcmpl-ASv9gROIIAvRs9QnmLP8Nzs3PGMCX","object":"chat.completion.chunk","created":1731456252,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" is"},"logprobs":null,"finish_reason":null}]}
+
+ data: {"id":"chatcmpl-ASv9gROIIAvRs9QnmLP8Nzs3PGMCX","object":"chat.completion.chunk","created":1731456252,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" a"},"logprobs":null,"finish_reason":null}]}
+
+ data: {"id":"chatcmpl-ASv9gROIIAvRs9QnmLP8Nzs3PGMCX","object":"chat.completion.chunk","created":1731456252,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" test"},"logprobs":null,"finish_reason":null}]}
+
+ data: {"id":"chatcmpl-ASv9gROIIAvRs9QnmLP8Nzs3PGMCX","object":"chat.completion.chunk","created":1731456252,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"."},"logprobs":null,"finish_reason":null}]}
+
+ data: {"id":"chatcmpl-ASv9gROIIAvRs9QnmLP8Nzs3PGMCX","object":"chat.completion.chunk","created":1731456252,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}]}
+
+ data: [DONE]
+
+ headers:
+ CF-Cache-Status:
+ - DYNAMIC
+ CF-RAY:
+ - 8e1a80c54d00e288-MRS
+ Connection:
+ - keep-alive
+ Content-Type:
+ - text/event-stream; charset=utf-8
+ Date:
+ - Wed, 13 Nov 2024 00:04:12 GMT
+ Server:
+ - cloudflare
+ Set-Cookie: test_set_cookie
+ Transfer-Encoding:
+ - chunked
+ X-Content-Type-Options:
+ - nosniff
+ access-control-expose-headers:
+ - X-Request-ID
+ alt-svc:
+ - h3=":443"; ma=86400
+ openai-organization: test_openai_org_id
+ openai-processing-ms:
+ - '283'
+ 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_e9e4ea6fd060391e8cc8cfea78ad9a15
+ status:
+ code: 200
+ message: OK
+version: 1
diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_async_chat_completion_tool_calls_no_content.yaml b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_async_chat_completion_tool_calls_no_content.yaml
new file mode 100644
index 0000000000..053e271d45
--- /dev/null
+++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_async_chat_completion_tool_calls_no_content.yaml
@@ -0,0 +1,342 @@
+interactions:
+- request:
+ body: |-
+ {
+ "messages": [
+ {
+ "role": "system",
+ "content": "You're a helpful assistant."
+ },
+ {
+ "role": "user",
+ "content": "What's the weather in Seattle and San Francisco today?"
+ }
+ ],
+ "model": "gpt-4o-mini",
+ "tool_choice": "auto",
+ "tools": [
+ {
+ "type": "function",
+ "function": {
+ "name": "get_current_weather",
+ "description": "Get the current weather in a given location",
+ "parameters": {
+ "type": "object",
+ "properties": {
+ "location": {
+ "type": "string",
+ "description": "The city and state, e.g. Boston, MA"
+ }
+ },
+ "required": [
+ "location"
+ ],
+ "additionalProperties": false
+ }
+ }
+ }
+ ]
+ }
+ headers:
+ accept:
+ - application/json
+ accept-encoding:
+ - gzip, deflate
+ authorization:
+ - Bearer test_openai_api_key
+ connection:
+ - keep-alive
+ content-length:
+ - '543'
+ content-type:
+ - application/json
+ host:
+ - api.openai.com
+ user-agent:
+ - AsyncOpenAI/Python 1.26.0
+ x-stainless-arch:
+ - arm64
+ x-stainless-async:
+ - async:asyncio
+ x-stainless-lang:
+ - python
+ x-stainless-os:
+ - MacOS
+ x-stainless-package-version:
+ - 1.26.0
+ x-stainless-runtime:
+ - CPython
+ x-stainless-runtime-version:
+ - 3.12.5
+ method: POST
+ uri: https://api.openai.com/v1/chat/completions
+ response:
+ body:
+ string: |-
+ {
+ "id": "chatcmpl-ASv9bJqWatpvCC0YMsYRcTSIiXoxk",
+ "object": "chat.completion",
+ "created": 1731456247,
+ "model": "gpt-4o-mini-2024-07-18",
+ "choices": [
+ {
+ "index": 0,
+ "message": {
+ "role": "assistant",
+ "content": null,
+ "tool_calls": [
+ {
+ "id": "call_vwOezSsB5j9ei1SSMlZjqx7g",
+ "type": "function",
+ "function": {
+ "name": "get_current_weather",
+ "arguments": "{\"location\": \"Seattle, WA\"}"
+ }
+ },
+ {
+ "id": "call_LzeIYcKhHnVF60u4LmBpT1tv",
+ "type": "function",
+ "function": {
+ "name": "get_current_weather",
+ "arguments": "{\"location\": \"San Francisco, CA\"}"
+ }
+ }
+ ],
+ "refusal": null
+ },
+ "logprobs": null,
+ "finish_reason": "tool_calls"
+ }
+ ],
+ "usage": {
+ "prompt_tokens": 75,
+ "completion_tokens": 51,
+ "total_tokens": 126,
+ "prompt_tokens_details": {
+ "cached_tokens": 0,
+ "audio_tokens": 0
+ },
+ "completion_tokens_details": {
+ "reasoning_tokens": 0,
+ "audio_tokens": 0,
+ "accepted_prediction_tokens": 0,
+ "rejected_prediction_tokens": 0
+ }
+ },
+ "system_fingerprint": "fp_0ba0d124f1"
+ }
+ headers:
+ CF-Cache-Status:
+ - DYNAMIC
+ CF-RAY:
+ - 8e1a80a9f8fbe1c9-MRS
+ Connection:
+ - keep-alive
+ Content-Type:
+ - application/json
+ Date:
+ - Wed, 13 Nov 2024 00:04:08 GMT
+ Server:
+ - cloudflare
+ Set-Cookie: test_set_cookie
+ Transfer-Encoding:
+ - chunked
+ X-Content-Type-Options:
+ - nosniff
+ access-control-expose-headers:
+ - X-Request-ID
+ alt-svc:
+ - h3=":443"; ma=86400
+ content-length:
+ - '1308'
+ openai-organization: test_openai_org_id
+ openai-processing-ms:
+ - '808'
+ openai-version:
+ - '2020-10-01'
+ strict-transport-security:
+ - max-age=31536000; includeSubDomains; preload
+ x-ratelimit-limit-requests:
+ - '30000'
+ x-ratelimit-limit-tokens:
+ - '150000000'
+ x-ratelimit-remaining-requests:
+ - '29999'
+ x-ratelimit-remaining-tokens:
+ - '149999960'
+ x-ratelimit-reset-requests:
+ - 2ms
+ x-ratelimit-reset-tokens:
+ - 0s
+ x-request-id:
+ - req_f1b9b75e4a73b542c9b1b992cd52c66f
+ status:
+ code: 200
+ message: OK
+- request:
+ body: |-
+ {
+ "messages": [
+ {
+ "role": "system",
+ "content": "You're a helpful assistant."
+ },
+ {
+ "role": "user",
+ "content": "What's the weather in Seattle and San Francisco today?"
+ },
+ {
+ "role": "assistant",
+ "tool_calls": [
+ {
+ "id": "call_vwOezSsB5j9ei1SSMlZjqx7g",
+ "function": {
+ "arguments": "{\"location\": \"Seattle, WA\"}",
+ "name": "get_current_weather"
+ },
+ "type": "function"
+ },
+ {
+ "id": "call_LzeIYcKhHnVF60u4LmBpT1tv",
+ "function": {
+ "arguments": "{\"location\": \"San Francisco, CA\"}",
+ "name": "get_current_weather"
+ },
+ "type": "function"
+ }
+ ]
+ },
+ {
+ "role": "tool",
+ "content": "50 degrees and raining",
+ "tool_call_id": "call_vwOezSsB5j9ei1SSMlZjqx7g"
+ },
+ {
+ "role": "tool",
+ "content": "70 degrees and sunny",
+ "tool_call_id": "call_LzeIYcKhHnVF60u4LmBpT1tv"
+ }
+ ],
+ "model": "gpt-4o-mini"
+ }
+ headers:
+ accept:
+ - application/json
+ accept-encoding:
+ - gzip, deflate
+ authorization:
+ - Bearer test_openai_api_key
+ connection:
+ - keep-alive
+ content-length:
+ - '746'
+ content-type:
+ - application/json
+ cookie:
+ - test_cookie
+ host:
+ - api.openai.com
+ user-agent:
+ - AsyncOpenAI/Python 1.26.0
+ x-stainless-arch:
+ - arm64
+ x-stainless-async:
+ - async:asyncio
+ x-stainless-lang:
+ - python
+ x-stainless-os:
+ - MacOS
+ x-stainless-package-version:
+ - 1.26.0
+ x-stainless-runtime:
+ - CPython
+ x-stainless-runtime-version:
+ - 3.12.5
+ method: POST
+ uri: https://api.openai.com/v1/chat/completions
+ response:
+ body:
+ string: |-
+ {
+ "id": "chatcmpl-ASv9dfXfIwGCZgeWzDTbCh0FuU9kh",
+ "object": "chat.completion",
+ "created": 1731456249,
+ "model": "gpt-4o-mini-2024-07-18",
+ "choices": [
+ {
+ "index": 0,
+ "message": {
+ "role": "assistant",
+ "content": "Today, the weather in Seattle is 50 degrees and raining, while in San Francisco, it's 70 degrees and sunny.",
+ "refusal": null
+ },
+ "logprobs": null,
+ "finish_reason": "stop"
+ }
+ ],
+ "usage": {
+ "prompt_tokens": 99,
+ "completion_tokens": 25,
+ "total_tokens": 124,
+ "prompt_tokens_details": {
+ "cached_tokens": 0,
+ "audio_tokens": 0
+ },
+ "completion_tokens_details": {
+ "reasoning_tokens": 0,
+ "audio_tokens": 0,
+ "accepted_prediction_tokens": 0,
+ "rejected_prediction_tokens": 0
+ }
+ },
+ "system_fingerprint": "fp_0ba0d124f1"
+ }
+ headers:
+ CF-Cache-Status:
+ - DYNAMIC
+ CF-RAY:
+ - 8e1a80b3baade1c9-MRS
+ Connection:
+ - keep-alive
+ Content-Type:
+ - application/json
+ Date:
+ - Wed, 13 Nov 2024 00:04:10 GMT
+ Server:
+ - cloudflare
+ Set-Cookie: test_set_cookie
+ Transfer-Encoding:
+ - chunked
+ X-Content-Type-Options:
+ - nosniff
+ access-control-expose-headers:
+ - X-Request-ID
+ alt-svc:
+ - h3=":443"; ma=86400
+ content-length:
+ - '859'
+ openai-organization: test_openai_org_id
+ openai-processing-ms:
+ - '972'
+ openai-version:
+ - '2020-10-01'
+ strict-transport-security:
+ - max-age=31536000; includeSubDomains; preload
+ x-ratelimit-limit-requests:
+ - '30000'
+ x-ratelimit-limit-tokens:
+ - '150000000'
+ x-ratelimit-remaining-requests:
+ - '29999'
+ x-ratelimit-remaining-tokens:
+ - '149999948'
+ x-ratelimit-reset-requests:
+ - 2ms
+ x-ratelimit-reset-tokens:
+ - 0s
+ x-request-id:
+ - req_754e6b59f1d3da727e2210e3d8c56243
+ status:
+ code: 200
+ message: OK
+version: 1
diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_async_chat_completion_tool_calls_with_content.yaml b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_async_chat_completion_tool_calls_with_content.yaml
new file mode 100644
index 0000000000..ebebb20603
--- /dev/null
+++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_async_chat_completion_tool_calls_with_content.yaml
@@ -0,0 +1,342 @@
+interactions:
+- request:
+ body: |-
+ {
+ "messages": [
+ {
+ "role": "system",
+ "content": "You're a helpful assistant."
+ },
+ {
+ "role": "user",
+ "content": "What's the weather in Seattle and San Francisco today?"
+ }
+ ],
+ "model": "gpt-4o-mini",
+ "tool_choice": "auto",
+ "tools": [
+ {
+ "type": "function",
+ "function": {
+ "name": "get_current_weather",
+ "description": "Get the current weather in a given location",
+ "parameters": {
+ "type": "object",
+ "properties": {
+ "location": {
+ "type": "string",
+ "description": "The city and state, e.g. Boston, MA"
+ }
+ },
+ "required": [
+ "location"
+ ],
+ "additionalProperties": false
+ }
+ }
+ }
+ ]
+ }
+ headers:
+ accept:
+ - application/json
+ accept-encoding:
+ - gzip, deflate
+ authorization:
+ - Bearer test_openai_api_key
+ connection:
+ - keep-alive
+ content-length:
+ - '543'
+ content-type:
+ - application/json
+ host:
+ - api.openai.com
+ user-agent:
+ - AsyncOpenAI/Python 1.26.0
+ x-stainless-arch:
+ - arm64
+ x-stainless-async:
+ - async:asyncio
+ x-stainless-lang:
+ - python
+ x-stainless-os:
+ - MacOS
+ x-stainless-package-version:
+ - 1.26.0
+ x-stainless-runtime:
+ - CPython
+ x-stainless-runtime-version:
+ - 3.12.5
+ method: POST
+ uri: https://api.openai.com/v1/chat/completions
+ response:
+ body:
+ string: |-
+ {
+ "id": "chatcmpl-ASv9ZqgNAOJAOLYMgdmxouatKXJlk",
+ "object": "chat.completion",
+ "created": 1731456245,
+ "model": "gpt-4o-mini-2024-07-18",
+ "choices": [
+ {
+ "index": 0,
+ "message": {
+ "role": "assistant",
+ "content": null,
+ "tool_calls": [
+ {
+ "id": "call_O8NOz8VlxosSASEsOY7LDUcP",
+ "type": "function",
+ "function": {
+ "name": "get_current_weather",
+ "arguments": "{\"location\": \"Seattle, WA\"}"
+ }
+ },
+ {
+ "id": "call_3m7cyuckijnpiWr6tq0Tl8Mg",
+ "type": "function",
+ "function": {
+ "name": "get_current_weather",
+ "arguments": "{\"location\": \"San Francisco, CA\"}"
+ }
+ }
+ ],
+ "refusal": null
+ },
+ "logprobs": null,
+ "finish_reason": "tool_calls"
+ }
+ ],
+ "usage": {
+ "prompt_tokens": 75,
+ "completion_tokens": 51,
+ "total_tokens": 126,
+ "prompt_tokens_details": {
+ "cached_tokens": 0,
+ "audio_tokens": 0
+ },
+ "completion_tokens_details": {
+ "reasoning_tokens": 0,
+ "audio_tokens": 0,
+ "accepted_prediction_tokens": 0,
+ "rejected_prediction_tokens": 0
+ }
+ },
+ "system_fingerprint": "fp_0ba0d124f1"
+ }
+ headers:
+ CF-Cache-Status:
+ - DYNAMIC
+ CF-RAY:
+ - 8e1a8098ac5ae167-MRS
+ Connection:
+ - keep-alive
+ Content-Type:
+ - application/json
+ Date:
+ - Wed, 13 Nov 2024 00:04:06 GMT
+ Server:
+ - cloudflare
+ Set-Cookie: test_set_cookie
+ Transfer-Encoding:
+ - chunked
+ X-Content-Type-Options:
+ - nosniff
+ access-control-expose-headers:
+ - X-Request-ID
+ alt-svc:
+ - h3=":443"; ma=86400
+ content-length:
+ - '1308'
+ openai-organization: test_openai_org_id
+ openai-processing-ms:
+ - '937'
+ openai-version:
+ - '2020-10-01'
+ strict-transport-security:
+ - max-age=31536000; includeSubDomains; preload
+ x-ratelimit-limit-requests:
+ - '30000'
+ x-ratelimit-limit-tokens:
+ - '150000000'
+ x-ratelimit-remaining-requests:
+ - '29999'
+ x-ratelimit-remaining-tokens:
+ - '149999960'
+ x-ratelimit-reset-requests:
+ - 2ms
+ x-ratelimit-reset-tokens:
+ - 0s
+ x-request-id:
+ - req_3cd7152d2c8c10b4f354b27165f6c2b5
+ status:
+ code: 200
+ message: OK
+- request:
+ body: |-
+ {
+ "messages": [
+ {
+ "role": "system",
+ "content": "You're a helpful assistant."
+ },
+ {
+ "role": "user",
+ "content": "What's the weather in Seattle and San Francisco today?"
+ },
+ {
+ "role": "assistant",
+ "tool_calls": [
+ {
+ "id": "call_O8NOz8VlxosSASEsOY7LDUcP",
+ "function": {
+ "arguments": "{\"location\": \"Seattle, WA\"}",
+ "name": "get_current_weather"
+ },
+ "type": "function"
+ },
+ {
+ "id": "call_3m7cyuckijnpiWr6tq0Tl8Mg",
+ "function": {
+ "arguments": "{\"location\": \"San Francisco, CA\"}",
+ "name": "get_current_weather"
+ },
+ "type": "function"
+ }
+ ]
+ },
+ {
+ "role": "tool",
+ "content": "50 degrees and raining",
+ "tool_call_id": "call_O8NOz8VlxosSASEsOY7LDUcP"
+ },
+ {
+ "role": "tool",
+ "content": "70 degrees and sunny",
+ "tool_call_id": "call_3m7cyuckijnpiWr6tq0Tl8Mg"
+ }
+ ],
+ "model": "gpt-4o-mini"
+ }
+ headers:
+ accept:
+ - application/json
+ accept-encoding:
+ - gzip, deflate
+ authorization:
+ - Bearer test_openai_api_key
+ connection:
+ - keep-alive
+ content-length:
+ - '746'
+ content-type:
+ - application/json
+ cookie:
+ - test_cookie
+ host:
+ - api.openai.com
+ user-agent:
+ - AsyncOpenAI/Python 1.26.0
+ x-stainless-arch:
+ - arm64
+ x-stainless-async:
+ - async:asyncio
+ x-stainless-lang:
+ - python
+ x-stainless-os:
+ - MacOS
+ x-stainless-package-version:
+ - 1.26.0
+ x-stainless-runtime:
+ - CPython
+ x-stainless-runtime-version:
+ - 3.12.5
+ method: POST
+ uri: https://api.openai.com/v1/chat/completions
+ response:
+ body:
+ string: |-
+ {
+ "id": "chatcmpl-ASv9aQnGndy04lqKoPRagym1eEaQK",
+ "object": "chat.completion",
+ "created": 1731456246,
+ "model": "gpt-4o-mini-2024-07-18",
+ "choices": [
+ {
+ "index": 0,
+ "message": {
+ "role": "assistant",
+ "content": "Today, Seattle is experiencing 50 degrees and raining, while San Francisco has a pleasant 70 degrees and sunny weather.",
+ "refusal": null
+ },
+ "logprobs": null,
+ "finish_reason": "stop"
+ }
+ ],
+ "usage": {
+ "prompt_tokens": 99,
+ "completion_tokens": 24,
+ "total_tokens": 123,
+ "prompt_tokens_details": {
+ "cached_tokens": 0,
+ "audio_tokens": 0
+ },
+ "completion_tokens_details": {
+ "reasoning_tokens": 0,
+ "audio_tokens": 0,
+ "accepted_prediction_tokens": 0,
+ "rejected_prediction_tokens": 0
+ }
+ },
+ "system_fingerprint": "fp_f59a81427f"
+ }
+ headers:
+ CF-Cache-Status:
+ - DYNAMIC
+ CF-RAY:
+ - 8e1a80a39c71e167-MRS
+ Connection:
+ - keep-alive
+ Content-Type:
+ - application/json
+ Date:
+ - Wed, 13 Nov 2024 00:04:07 GMT
+ Server:
+ - cloudflare
+ Set-Cookie: test_set_cookie
+ Transfer-Encoding:
+ - chunked
+ X-Content-Type-Options:
+ - nosniff
+ access-control-expose-headers:
+ - X-Request-ID
+ alt-svc:
+ - h3=":443"; ma=86400
+ content-length:
+ - '871'
+ openai-organization: test_openai_org_id
+ openai-processing-ms:
+ - '477'
+ openai-version:
+ - '2020-10-01'
+ strict-transport-security:
+ - max-age=31536000; includeSubDomains; preload
+ x-ratelimit-limit-requests:
+ - '30000'
+ x-ratelimit-limit-tokens:
+ - '150000000'
+ x-ratelimit-remaining-requests:
+ - '29999'
+ x-ratelimit-remaining-tokens:
+ - '149999948'
+ x-ratelimit-reset-requests:
+ - 2ms
+ x-ratelimit-reset-tokens:
+ - 0s
+ x-request-id:
+ - req_193c74758ea30e77e55afe931e89fd6c
+ status:
+ code: 200
+ message: OK
+version: 1
diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_async_chat_completion_with_content.yaml b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_async_chat_completion_with_content.yaml
new file mode 100644
index 0000000000..61ec4a646e
--- /dev/null
+++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_async_chat_completion_with_content.yaml
@@ -0,0 +1,132 @@
+interactions:
+- request:
+ body: |-
+ {
+ "messages": [
+ {
+ "role": "user",
+ "content": "Say this is a test"
+ }
+ ],
+ "model": "gpt-4o-mini",
+ "stream": false
+ }
+ headers:
+ accept:
+ - application/json
+ accept-encoding:
+ - gzip, deflate
+ authorization:
+ - Bearer test_openai_api_key
+ connection:
+ - keep-alive
+ content-length:
+ - '106'
+ content-type:
+ - application/json
+ host:
+ - api.openai.com
+ user-agent:
+ - AsyncOpenAI/Python 1.26.0
+ x-stainless-arch:
+ - arm64
+ x-stainless-async:
+ - async:asyncio
+ x-stainless-lang:
+ - python
+ x-stainless-os:
+ - MacOS
+ x-stainless-package-version:
+ - 1.26.0
+ x-stainless-runtime:
+ - CPython
+ x-stainless-runtime-version:
+ - 3.12.5
+ method: POST
+ uri: https://api.openai.com/v1/chat/completions
+ response:
+ body:
+ string: |-
+ {
+ "id": "chatcmpl-ASv9R2E7Yhb2e7bj4Xl0qm9s3J42Y",
+ "object": "chat.completion",
+ "created": 1731456237,
+ "model": "gpt-4o-mini-2024-07-18",
+ "choices": [
+ {
+ "index": 0,
+ "message": {
+ "role": "assistant",
+ "content": "This is a test. How can I assist you further?",
+ "refusal": null
+ },
+ "logprobs": null,
+ "finish_reason": "stop"
+ }
+ ],
+ "usage": {
+ "prompt_tokens": 12,
+ "completion_tokens": 12,
+ "total_tokens": 24,
+ "prompt_tokens_details": {
+ "cached_tokens": 0,
+ "audio_tokens": 0
+ },
+ "completion_tokens_details": {
+ "reasoning_tokens": 0,
+ "audio_tokens": 0,
+ "accepted_prediction_tokens": 0,
+ "rejected_prediction_tokens": 0
+ }
+ },
+ "system_fingerprint": "fp_0ba0d124f1"
+ }
+ headers:
+ CF-Cache-Status:
+ - DYNAMIC
+ CF-RAY:
+ - 8e1a80679a8311a6-MRS
+ Connection:
+ - keep-alive
+ Content-Type:
+ - application/json
+ Date:
+ - Wed, 13 Nov 2024 00:03:58 GMT
+ Server:
+ - cloudflare
+ Set-Cookie: test_set_cookie
+ Transfer-Encoding:
+ - chunked
+ X-Content-Type-Options:
+ - nosniff
+ access-control-expose-headers:
+ - X-Request-ID
+ alt-svc:
+ - h3=":443"; ma=86400
+ content-length:
+ - '796'
+ openai-organization: test_openai_org_id
+ openai-processing-ms:
+ - '359'
+ openai-version:
+ - '2020-10-01'
+ strict-transport-security:
+ - max-age=31536000; includeSubDomains; preload
+ x-ratelimit-limit-requests:
+ - '30000'
+ x-ratelimit-limit-tokens:
+ - '150000000'
+ x-ratelimit-remaining-requests:
+ - '29999'
+ x-ratelimit-remaining-tokens:
+ - '149999978'
+ x-ratelimit-reset-requests:
+ - 2ms
+ x-ratelimit-reset-tokens:
+ - 0s
+ x-request-id:
+ - req_41ea134c1fc450d4ca4cf8d0c6a7c53a
+ status:
+ code: 200
+ message: OK
+version: 1
diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_404.yaml b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_404.yaml
index 0782cba71d..fb713363d5 100644
--- a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_404.yaml
+++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_404.yaml
@@ -15,6 +15,8 @@ interactions:
- application/json
accept-encoding:
- gzip, deflate
+ authorization:
+ - Bearer test_openai_api_key
connection:
- keep-alive
content-length:
@@ -58,13 +60,13 @@ interactions:
CF-Cache-Status:
- DYNAMIC
CF-RAY:
- - 8e0ca7056be15f93-SIN
+ - 8e1225a16c283d93-SIN
Connection:
- keep-alive
Content-Type:
- application/json; charset=utf-8
Date:
- - Mon, 11 Nov 2024 07:43:38 GMT
+ - Mon, 11 Nov 2024 23:43:52 GMT
Server:
- cloudflare
Set-Cookie: test_set_cookie
@@ -76,13 +78,13 @@ interactions:
- h3=":443"; ma=86400
content-length:
- '231'
- openai-organization: test_organization
+ openai-organization: test_openai_org_id
strict-transport-security:
- max-age=31536000; includeSubDomains; preload
vary:
- Origin
x-request-id:
- - req_75175efff56c313161c136c479e082ac
+ - req_c3e0f92d7b5426d1a4a17bb3d39953ea
status:
code: 404
message: Not Found
diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_extra_params.yaml b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_extra_params.yaml
index cfcd27074a..7cc89ad9b8 100644
--- a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_extra_params.yaml
+++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_extra_params.yaml
@@ -20,6 +20,8 @@ interactions:
- application/json
accept-encoding:
- gzip, deflate
+ authorization:
+ - Bearer test_openai_api_key
connection:
- keep-alive
content-length:
@@ -29,7 +31,7 @@ interactions:
host:
- api.openai.com
user-agent:
- - OpenAI/Python 1.26.0
+ - OpenAI/Python 1.54.3
x-stainless-arch:
- arm64
x-stainless-async:
@@ -39,7 +41,9 @@ interactions:
x-stainless-os:
- MacOS
x-stainless-package-version:
- - 1.26.0
+ - 1.54.3
+ x-stainless-retry-count:
+ - '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
@@ -50,9 +54,9 @@ interactions:
body:
string: |-
{
- "id": "chatcmpl-APfFNvBVQx43PNOIf1dWnEUT5u5fA",
+ "id": "chatcmpl-ASYMT7913Sp58qhZqQgY7g7Ia2J4M",
"object": "chat.completion",
- "created": 1730680117,
+ "created": 1731368633,
"model": "gpt-4o-mini-2024-07-18",
"choices": [
{
@@ -71,10 +75,14 @@ interactions:
"completion_tokens": 12,
"total_tokens": 24,
"prompt_tokens_details": {
- "cached_tokens": 0
+ "cached_tokens": 0,
+ "audio_tokens": 0
},
"completion_tokens_details": {
- "reasoning_tokens": 0
+ "reasoning_tokens": 0,
+ "audio_tokens": 0,
+ "accepted_prediction_tokens": 0,
+ "rejected_prediction_tokens": 0
}
},
"service_tier": "default",
@@ -84,13 +92,13 @@ interactions:
CF-Cache-Status:
- DYNAMIC
CF-RAY:
- - 8dd07c2d0a5a9f98-SIN
+ - 8e1225a3f8e9ce65-SIN
Connection:
- keep-alive
Content-Type:
- application/json
Date:
- - Mon, 04 Nov 2024 00:28:37 GMT
+ - Mon, 11 Nov 2024 23:43:53 GMT
Server:
- cloudflare
Set-Cookie: test_set_cookie
@@ -103,10 +111,10 @@ interactions:
alt-svc:
- h3=":443"; ma=86400
content-length:
- - '697'
- openai-organization: test_organization
+ - '825'
+ openai-organization: test_openai_org_id
openai-processing-ms:
- - '228'
+ - '431'
openai-version:
- '2020-10-01'
strict-transport-security:
@@ -120,11 +128,11 @@ interactions:
x-ratelimit-remaining-tokens:
- '199943'
x-ratelimit-reset-requests:
- - 13.724s
+ - 14.746s
x-ratelimit-reset-tokens:
- 16ms
x-request-id:
- - req_0ded46a4535c24c36ef58363b7538421
+ - req_81e29a8992ea8001c0240bd990acf0ab
status:
code: 200
message: OK
diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_multiple_choices.yaml b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_multiple_choices.yaml
index 9518e41225..23828e98f4 100644
--- a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_multiple_choices.yaml
+++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_multiple_choices.yaml
@@ -17,6 +17,8 @@ interactions:
- application/json
accept-encoding:
- gzip, deflate
+ authorization:
+ - Bearer test_openai_api_key
connection:
- keep-alive
content-length:
@@ -26,7 +28,7 @@ interactions:
host:
- api.openai.com
user-agent:
- - OpenAI/Python 1.26.0
+ - OpenAI/Python 1.54.3
x-stainless-arch:
- arm64
x-stainless-async:
@@ -36,7 +38,9 @@ interactions:
x-stainless-os:
- MacOS
x-stainless-package-version:
- - 1.26.0
+ - 1.54.3
+ x-stainless-retry-count:
+ - '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
@@ -47,16 +51,16 @@ interactions:
body:
string: |-
{
- "id": "chatcmpl-APfFO3w0cNVOphe5Lk9EaYyRaS2pm",
+ "id": "chatcmpl-ASYMUBq69UHDarAz2fsd0O50rv0r1",
"object": "chat.completion",
- "created": 1730680118,
+ "created": 1731368634,
"model": "gpt-4o-mini-2024-07-18",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
- "content": "This is a test.",
+ "content": "This is a test. How can I assist you further?",
"refusal": null
},
"logprobs": null,
@@ -66,7 +70,7 @@ interactions:
"index": 1,
"message": {
"role": "assistant",
- "content": "This is a test! How can I assist you further?",
+ "content": "This is a test. How can I assist you further?",
"refusal": null
},
"logprobs": null,
@@ -75,13 +79,17 @@ interactions:
],
"usage": {
"prompt_tokens": 12,
- "completion_tokens": 17,
- "total_tokens": 29,
+ "completion_tokens": 24,
+ "total_tokens": 36,
"prompt_tokens_details": {
- "cached_tokens": 0
+ "cached_tokens": 0,
+ "audio_tokens": 0
},
"completion_tokens_details": {
- "reasoning_tokens": 0
+ "reasoning_tokens": 0,
+ "audio_tokens": 0,
+ "accepted_prediction_tokens": 0,
+ "rejected_prediction_tokens": 0
}
},
"system_fingerprint": "fp_0ba0d124f1"
@@ -90,13 +98,13 @@ interactions:
CF-Cache-Status:
- DYNAMIC
CF-RAY:
- - 8dd07c30beda3dd4-SIN
+ - 8e1225a91a253e53-SIN
Connection:
- keep-alive
Content-Type:
- application/json
Date:
- - Mon, 04 Nov 2024 00:28:38 GMT
+ - Mon, 11 Nov 2024 23:43:54 GMT
Server:
- cloudflare
Set-Cookie: test_set_cookie
@@ -109,10 +117,10 @@ interactions:
alt-svc:
- h3=":443"; ma=86400
content-length:
- - '872'
- openai-organization: test_organization
+ - '1030'
+ openai-organization: test_openai_org_id
openai-processing-ms:
- - '261'
+ - '399'
openai-version:
- '2020-10-01'
strict-transport-security:
@@ -126,11 +134,11 @@ interactions:
x-ratelimit-remaining-tokens:
- '199962'
x-ratelimit-reset-requests:
- - 21.785s
+ - 22.564s
x-ratelimit-reset-tokens:
- 11ms
x-request-id:
- - req_86ab6a7a85f95e2a001cfeb89e0827b1
+ - req_01290a92a1a3d787c7a00bb3836da597
status:
code: 200
message: OK
diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_multiple_choices_streaming.yaml b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_multiple_choices_streaming.yaml
index e587ce5a38..ea06ca5984 100644
--- a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_multiple_choices_streaming.yaml
+++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_multiple_choices_streaming.yaml
@@ -24,6 +24,8 @@ interactions:
- application/json
accept-encoding:
- gzip, deflate
+ authorization:
+ - Bearer test_openai_api_key
connection:
- keep-alive
content-length:
@@ -33,7 +35,7 @@ interactions:
host:
- api.openai.com
user-agent:
- - OpenAI/Python 1.26.0
+ - OpenAI/Python 1.54.3
x-stainless-arch:
- arm64
x-stainless-async:
@@ -43,7 +45,9 @@ interactions:
x-stainless-os:
- MacOS
x-stainless-package-version:
- - 1.26.0
+ - 1.54.3
+ x-stainless-retry-count:
+ - '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
@@ -53,237 +57,223 @@ interactions:
response:
body:
string: |+
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":"I'm"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":"I'm"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":"I"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":"I'm"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" unable"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" unable"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" don't"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" unable"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" to"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" to"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" have"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" to"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" provide"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" provide"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" real"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" provide"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" real"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" real"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":"-time"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" real"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":"-time"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":"-time"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" weather"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":"-time"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" weather"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" weather"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" data"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" weather"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" updates"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" updates"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":"."},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" updates"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":"."},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":"."},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" For"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" as"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" However"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" To"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" the"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" my"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":","},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" get"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" most"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" capabilities"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" you"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" the"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" accurate"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" do"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" can"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" latest"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" and"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" not"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" check"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" weather"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" up"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" include"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" the"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" information"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" current"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" accessing"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" weather"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" for"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" in"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" live"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" Seattle"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" Seattle"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" and"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" data"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" San"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" and"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":"-to"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":"."},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":"-date"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" San"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" weather"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" However"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" information"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" Francisco"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":","},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":","},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" please"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":","},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" check"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" you"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" Francisco"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" I"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" a"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" can"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" by"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" recommend"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" reliable"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" easily"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" using"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" checking"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" weather"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" check"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" a"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" a"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" website"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" the"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" weather"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" reliable"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" or"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" current"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" app"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" weather"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" website"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" weather"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" or"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" website"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":"."},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" in"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" app"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" or"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" You"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" Seattle"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" like"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" using"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" can"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" and"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" the"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" a"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" also"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" San"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" Weather"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" weather"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" use"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" Francisco"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" Channel"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" app"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" a"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" using"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":","},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":"."},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" search"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" a"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" Acc"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" You"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" engine"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" weather"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":"u"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" can"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" or"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" also"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":"Weather"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" website"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" a"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":","},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":","},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" ask"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" weather"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" app"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" service"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" a"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" for"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":","},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" immediate"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" voice"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" updates"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" or"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" or"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" assistant"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" a"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" service"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" local"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" or"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" news"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":"."},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" station"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" search"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" on"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" Would"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":"'s"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" online"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" Seattle"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" you"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" website"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" for"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" and"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" like"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":"."},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" the"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" San"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" some"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" If"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" current"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" Francisco"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" tips"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" there's"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" weather"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":"'s"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" on"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" anything"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" conditions"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" weather"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" where"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" else"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":"."},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" you'd"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" to"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" today"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" find"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":"."},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" this"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" like"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":" information"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" to"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{"content":"?"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" know"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":","},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null}
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" feel"},"logprobs":null,"finish_reason":null}],"usage":null}
-
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" free"},"logprobs":null,"finish_reason":null}],"usage":null}
-
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" to"},"logprobs":null,"finish_reason":null}],"usage":null}
-
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":" ask"},"logprobs":null,"finish_reason":null}],"usage":null}
-
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{"content":"!"},"logprobs":null,"finish_reason":null}],"usage":null}
-
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null}
-
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":1,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null}
-
- data: {"id":"chatcmpl-APfFT3JSFkuTVECTo0DfULAD8vftU","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[],"usage":{"prompt_tokens":26,"completion_tokens":111,"total_tokens":137,"prompt_tokens_details":{"cached_tokens":0},"completion_tokens_details":{"reasoning_tokens":0}}}
+ data: {"id":"chatcmpl-ASYMaNc7XmbGRUNREnmvhyyISBHsv","object":"chat.completion.chunk","created":1731368640,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[],"usage":{"prompt_tokens":26,"completion_tokens":104,"total_tokens":130,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}}}
data: [DONE]
@@ -291,13 +281,13 @@ interactions:
CF-Cache-Status:
- DYNAMIC
CF-RAY:
- - 8dd07c55783bce06-SIN
+ - 8e1225d0fa1481e4-SIN
Connection:
- keep-alive
Content-Type:
- text/event-stream; charset=utf-8
Date:
- - Mon, 04 Nov 2024 00:28:44 GMT
+ - Mon, 11 Nov 2024 23:44:00 GMT
Server:
- cloudflare
Set-Cookie: test_set_cookie
@@ -309,9 +299,9 @@ interactions:
- X-Request-ID
alt-svc:
- h3=":443"; ma=86400
- openai-organization: test_organization
+ openai-organization: test_openai_org_id
openai-processing-ms:
- - '127'
+ - '176'
openai-version:
- '2020-10-01'
strict-transport-security:
@@ -325,11 +315,11 @@ interactions:
x-ratelimit-remaining-tokens:
- '199945'
x-ratelimit-reset-requests:
- - 59.105s
+ - 59.369s
x-ratelimit-reset-tokens:
- 16ms
x-request-id:
- - req_4d50387aa59e08f2dc486aa5c62613f5
+ - req_892a6021b1acc00254d8ff80adcd82fb
status:
code: 200
message: OK
diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_multiple_tools_streaming_no_content.yaml b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_multiple_tools_streaming_no_content.yaml
index 8989eb9cfa..951aa52259 100644
--- a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_multiple_tools_streaming_no_content.yaml
+++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_multiple_tools_streaming_no_content.yaml
@@ -46,6 +46,8 @@ interactions:
- application/json
accept-encoding:
- gzip, deflate
+ authorization:
+ - Bearer test_openai_api_key
connection:
- keep-alive
content-length:
@@ -55,7 +57,7 @@ interactions:
host:
- api.openai.com
user-agent:
- - OpenAI/Python 1.26.0
+ - OpenAI/Python 1.54.3
x-stainless-arch:
- arm64
x-stainless-async:
@@ -65,7 +67,9 @@ interactions:
x-stainless-os:
- MacOS
x-stainless-package-version:
- - 1.26.0
+ - 1.54.3
+ x-stainless-retry-count:
+ - '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
@@ -75,41 +79,41 @@ interactions:
response:
body:
string: |+
- data: {"id":"chatcmpl-APfFYyp9joT2Wwh01iYvcm6iDYtV3","object":"chat.completion.chunk","created":1730680128,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"role":"assistant","content":null},"logprobs":null,"finish_reason":null}]}
+ data: {"id":"chatcmpl-ASYMdbuQwnGMCODejEnbp2ufs6WgR","object":"chat.completion.chunk","created":1731368643,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_9b78b61c52","usage":null,"choices":[{"index":0,"delta":{"role":"assistant","content":null},"logprobs":null,"finish_reason":null}]}
- data: {"id":"chatcmpl-APfFYyp9joT2Wwh01iYvcm6iDYtV3","object":"chat.completion.chunk","created":1730680128,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"id":"call_H7ADtKo1DKIzNyrCSBt1jKdw","type":"function","function":{"name":"get_current_weather","arguments":""}}]},"logprobs":null,"finish_reason":null}]}
+ data: {"id":"chatcmpl-ASYMdbuQwnGMCODejEnbp2ufs6WgR","object":"chat.completion.chunk","created":1731368643,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_9b78b61c52","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"id":"call_j7L00WV19wwQCvKOIVZewXZm","type":"function","function":{"name":"get_current_weather","arguments":""}}]},"logprobs":null,"finish_reason":null}]}
- data: {"id":"chatcmpl-APfFYyp9joT2Wwh01iYvcm6iDYtV3","object":"chat.completion.chunk","created":1730680128,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\"lo"}}]},"logprobs":null,"finish_reason":null}]}
+ data: {"id":"chatcmpl-ASYMdbuQwnGMCODejEnbp2ufs6WgR","object":"chat.completion.chunk","created":1731368643,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_9b78b61c52","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\"lo"}}]},"logprobs":null,"finish_reason":null}]}
- data: {"id":"chatcmpl-APfFYyp9joT2Wwh01iYvcm6iDYtV3","object":"chat.completion.chunk","created":1730680128,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"catio"}}]},"logprobs":null,"finish_reason":null}]}
+ data: {"id":"chatcmpl-ASYMdbuQwnGMCODejEnbp2ufs6WgR","object":"chat.completion.chunk","created":1731368643,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_9b78b61c52","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"catio"}}]},"logprobs":null,"finish_reason":null}]}
- data: {"id":"chatcmpl-APfFYyp9joT2Wwh01iYvcm6iDYtV3","object":"chat.completion.chunk","created":1730680128,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"n\": \"S"}}]},"logprobs":null,"finish_reason":null}]}
+ data: {"id":"chatcmpl-ASYMdbuQwnGMCODejEnbp2ufs6WgR","object":"chat.completion.chunk","created":1731368643,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_9b78b61c52","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"n\": \"S"}}]},"logprobs":null,"finish_reason":null}]}
- data: {"id":"chatcmpl-APfFYyp9joT2Wwh01iYvcm6iDYtV3","object":"chat.completion.chunk","created":1730680128,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"eatt"}}]},"logprobs":null,"finish_reason":null}]}
+ data: {"id":"chatcmpl-ASYMdbuQwnGMCODejEnbp2ufs6WgR","object":"chat.completion.chunk","created":1731368643,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_9b78b61c52","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"eatt"}}]},"logprobs":null,"finish_reason":null}]}
- data: {"id":"chatcmpl-APfFYyp9joT2Wwh01iYvcm6iDYtV3","object":"chat.completion.chunk","created":1730680128,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"le, W"}}]},"logprobs":null,"finish_reason":null}]}
+ data: {"id":"chatcmpl-ASYMdbuQwnGMCODejEnbp2ufs6WgR","object":"chat.completion.chunk","created":1731368643,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_9b78b61c52","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"le, W"}}]},"logprobs":null,"finish_reason":null}]}
- data: {"id":"chatcmpl-APfFYyp9joT2Wwh01iYvcm6iDYtV3","object":"chat.completion.chunk","created":1730680128,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"A\"}"}}]},"logprobs":null,"finish_reason":null}]}
+ data: {"id":"chatcmpl-ASYMdbuQwnGMCODejEnbp2ufs6WgR","object":"chat.completion.chunk","created":1731368643,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_9b78b61c52","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"A\"}"}}]},"logprobs":null,"finish_reason":null}]}
- data: {"id":"chatcmpl-APfFYyp9joT2Wwh01iYvcm6iDYtV3","object":"chat.completion.chunk","created":1730680128,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"id":"call_Dmv04Iin9mOpBKWSwdb5DbpS","type":"function","function":{"name":"get_current_weather","arguments":""}}]},"logprobs":null,"finish_reason":null}]}
+ data: {"id":"chatcmpl-ASYMdbuQwnGMCODejEnbp2ufs6WgR","object":"chat.completion.chunk","created":1731368643,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_9b78b61c52","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"id":"call_sAIOI3dvcd1YMsEqD8DI3l8B","type":"function","function":{"name":"get_current_weather","arguments":""}}]},"logprobs":null,"finish_reason":null}]}
- data: {"id":"chatcmpl-APfFYyp9joT2Wwh01iYvcm6iDYtV3","object":"chat.completion.chunk","created":1730680128,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"{\"lo"}}]},"logprobs":null,"finish_reason":null}]}
+ data: {"id":"chatcmpl-ASYMdbuQwnGMCODejEnbp2ufs6WgR","object":"chat.completion.chunk","created":1731368643,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_9b78b61c52","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"{\"lo"}}]},"logprobs":null,"finish_reason":null}]}
- data: {"id":"chatcmpl-APfFYyp9joT2Wwh01iYvcm6iDYtV3","object":"chat.completion.chunk","created":1730680128,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"catio"}}]},"logprobs":null,"finish_reason":null}]}
+ data: {"id":"chatcmpl-ASYMdbuQwnGMCODejEnbp2ufs6WgR","object":"chat.completion.chunk","created":1731368643,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_9b78b61c52","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"catio"}}]},"logprobs":null,"finish_reason":null}]}
- data: {"id":"chatcmpl-APfFYyp9joT2Wwh01iYvcm6iDYtV3","object":"chat.completion.chunk","created":1730680128,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"n\": \"S"}}]},"logprobs":null,"finish_reason":null}]}
+ data: {"id":"chatcmpl-ASYMdbuQwnGMCODejEnbp2ufs6WgR","object":"chat.completion.chunk","created":1731368643,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_9b78b61c52","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"n\": \"S"}}]},"logprobs":null,"finish_reason":null}]}
- data: {"id":"chatcmpl-APfFYyp9joT2Wwh01iYvcm6iDYtV3","object":"chat.completion.chunk","created":1730680128,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"an F"}}]},"logprobs":null,"finish_reason":null}]}
+ data: {"id":"chatcmpl-ASYMdbuQwnGMCODejEnbp2ufs6WgR","object":"chat.completion.chunk","created":1731368643,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_9b78b61c52","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"an F"}}]},"logprobs":null,"finish_reason":null}]}
- data: {"id":"chatcmpl-APfFYyp9joT2Wwh01iYvcm6iDYtV3","object":"chat.completion.chunk","created":1730680128,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"ranci"}}]},"logprobs":null,"finish_reason":null}]}
+ data: {"id":"chatcmpl-ASYMdbuQwnGMCODejEnbp2ufs6WgR","object":"chat.completion.chunk","created":1731368643,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_9b78b61c52","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"ranci"}}]},"logprobs":null,"finish_reason":null}]}
- data: {"id":"chatcmpl-APfFYyp9joT2Wwh01iYvcm6iDYtV3","object":"chat.completion.chunk","created":1730680128,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"sco, C"}}]},"logprobs":null,"finish_reason":null}]}
+ data: {"id":"chatcmpl-ASYMdbuQwnGMCODejEnbp2ufs6WgR","object":"chat.completion.chunk","created":1731368643,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_9b78b61c52","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"sco, C"}}]},"logprobs":null,"finish_reason":null}]}
- data: {"id":"chatcmpl-APfFYyp9joT2Wwh01iYvcm6iDYtV3","object":"chat.completion.chunk","created":1730680128,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"A\"}"}}]},"logprobs":null,"finish_reason":null}]}
+ data: {"id":"chatcmpl-ASYMdbuQwnGMCODejEnbp2ufs6WgR","object":"chat.completion.chunk","created":1731368643,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_9b78b61c52","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"A\"}"}}]},"logprobs":null,"finish_reason":null}]}
- data: {"id":"chatcmpl-APfFYyp9joT2Wwh01iYvcm6iDYtV3","object":"chat.completion.chunk","created":1730680128,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"tool_calls"}],"usage":null}
+ data: {"id":"chatcmpl-ASYMdbuQwnGMCODejEnbp2ufs6WgR","object":"chat.completion.chunk","created":1731368643,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_9b78b61c52","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"tool_calls"}],"usage":null}
- data: {"id":"chatcmpl-APfFYyp9joT2Wwh01iYvcm6iDYtV3","object":"chat.completion.chunk","created":1730680128,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[],"usage":{"prompt_tokens":75,"completion_tokens":51,"total_tokens":126,"prompt_tokens_details":{"cached_tokens":0},"completion_tokens_details":{"reasoning_tokens":0}}}
+ data: {"id":"chatcmpl-ASYMdbuQwnGMCODejEnbp2ufs6WgR","object":"chat.completion.chunk","created":1731368643,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_9b78b61c52","choices":[],"usage":{"prompt_tokens":75,"completion_tokens":51,"total_tokens":126,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}}}
data: [DONE]
@@ -117,13 +121,13 @@ interactions:
CF-Cache-Status:
- DYNAMIC
CF-RAY:
- - 8dd07c715fd66beb-SIN
+ - 8e1225e40bed40c8-SIN
Connection:
- keep-alive
Content-Type:
- text/event-stream; charset=utf-8
Date:
- - Mon, 04 Nov 2024 00:28:49 GMT
+ - Mon, 11 Nov 2024 23:44:04 GMT
Server:
- cloudflare
Set-Cookie: test_set_cookie
@@ -135,9 +139,9 @@ interactions:
- X-Request-ID
alt-svc:
- h3=":443"; ma=86400
- openai-organization: test_organization
+ openai-organization: test_openai_org_id
openai-processing-ms:
- - '647'
+ - '1225'
openai-version:
- '2020-10-01'
strict-transport-security:
@@ -151,11 +155,11 @@ interactions:
x-ratelimit-remaining-tokens:
- '199961'
x-ratelimit-reset-requests:
- - 1m11.934s
+ - 1m13.588s
x-ratelimit-reset-tokens:
- 11ms
x-request-id:
- - req_66ecdeba3a9e89bbc2aa60243fb1fdfb
+ - req_102cd878d03c1cec0c12b95f928d03ee
status:
code: 200
message: OK
diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_multiple_tools_streaming_with_content.yaml b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_multiple_tools_streaming_with_content.yaml
index c39facccc5..d42ac86e37 100644
--- a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_multiple_tools_streaming_with_content.yaml
+++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_multiple_tools_streaming_with_content.yaml
@@ -46,6 +46,8 @@ interactions:
- application/json
accept-encoding:
- gzip, deflate
+ authorization:
+ - Bearer test_openai_api_key
connection:
- keep-alive
content-length:
@@ -55,7 +57,7 @@ interactions:
host:
- api.openai.com
user-agent:
- - OpenAI/Python 1.26.0
+ - OpenAI/Python 1.54.3
x-stainless-arch:
- arm64
x-stainless-async:
@@ -65,7 +67,9 @@ interactions:
x-stainless-os:
- MacOS
x-stainless-package-version:
- - 1.26.0
+ - 1.54.3
+ x-stainless-retry-count:
+ - '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
@@ -75,41 +79,41 @@ interactions:
response:
body:
string: |+
- data: {"id":"chatcmpl-APfFVrgZUKVR18p3BuIQN3OYWjFIM","object":"chat.completion.chunk","created":1730680125,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"role":"assistant","content":null},"logprobs":null,"finish_reason":null}]}
+ data: {"id":"chatcmpl-ASYMbACebDoWcuraMEWQhU48q4dAp","object":"chat.completion.chunk","created":1731368641,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_9b78b61c52","usage":null,"choices":[{"index":0,"delta":{"role":"assistant","content":null},"logprobs":null,"finish_reason":null}]}
- data: {"id":"chatcmpl-APfFVrgZUKVR18p3BuIQN3OYWjFIM","object":"chat.completion.chunk","created":1730680125,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"id":"call_CqwFQqzbiNttzDzEXiUitRos","type":"function","function":{"name":"get_current_weather","arguments":""}}]},"logprobs":null,"finish_reason":null}]}
+ data: {"id":"chatcmpl-ASYMbACebDoWcuraMEWQhU48q4dAp","object":"chat.completion.chunk","created":1731368641,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_9b78b61c52","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"id":"call_fHCjJqt9Pysde6vcJcvbXGBx","type":"function","function":{"name":"get_current_weather","arguments":""}}]},"logprobs":null,"finish_reason":null}]}
- data: {"id":"chatcmpl-APfFVrgZUKVR18p3BuIQN3OYWjFIM","object":"chat.completion.chunk","created":1730680125,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\"lo"}}]},"logprobs":null,"finish_reason":null}]}
+ data: {"id":"chatcmpl-ASYMbACebDoWcuraMEWQhU48q4dAp","object":"chat.completion.chunk","created":1731368641,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_9b78b61c52","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\"lo"}}]},"logprobs":null,"finish_reason":null}]}
- data: {"id":"chatcmpl-APfFVrgZUKVR18p3BuIQN3OYWjFIM","object":"chat.completion.chunk","created":1730680125,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"catio"}}]},"logprobs":null,"finish_reason":null}]}
+ data: {"id":"chatcmpl-ASYMbACebDoWcuraMEWQhU48q4dAp","object":"chat.completion.chunk","created":1731368641,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_9b78b61c52","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"catio"}}]},"logprobs":null,"finish_reason":null}]}
- data: {"id":"chatcmpl-APfFVrgZUKVR18p3BuIQN3OYWjFIM","object":"chat.completion.chunk","created":1730680125,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"n\": \"S"}}]},"logprobs":null,"finish_reason":null}]}
+ data: {"id":"chatcmpl-ASYMbACebDoWcuraMEWQhU48q4dAp","object":"chat.completion.chunk","created":1731368641,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_9b78b61c52","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"n\": \"S"}}]},"logprobs":null,"finish_reason":null}]}
- data: {"id":"chatcmpl-APfFVrgZUKVR18p3BuIQN3OYWjFIM","object":"chat.completion.chunk","created":1730680125,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"eatt"}}]},"logprobs":null,"finish_reason":null}]}
+ data: {"id":"chatcmpl-ASYMbACebDoWcuraMEWQhU48q4dAp","object":"chat.completion.chunk","created":1731368641,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_9b78b61c52","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"eatt"}}]},"logprobs":null,"finish_reason":null}]}
- data: {"id":"chatcmpl-APfFVrgZUKVR18p3BuIQN3OYWjFIM","object":"chat.completion.chunk","created":1730680125,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"le, W"}}]},"logprobs":null,"finish_reason":null}]}
+ data: {"id":"chatcmpl-ASYMbACebDoWcuraMEWQhU48q4dAp","object":"chat.completion.chunk","created":1731368641,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_9b78b61c52","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"le, W"}}]},"logprobs":null,"finish_reason":null}]}
- data: {"id":"chatcmpl-APfFVrgZUKVR18p3BuIQN3OYWjFIM","object":"chat.completion.chunk","created":1730680125,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"A\"}"}}]},"logprobs":null,"finish_reason":null}]}
+ data: {"id":"chatcmpl-ASYMbACebDoWcuraMEWQhU48q4dAp","object":"chat.completion.chunk","created":1731368641,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_9b78b61c52","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"A\"}"}}]},"logprobs":null,"finish_reason":null}]}
- data: {"id":"chatcmpl-APfFVrgZUKVR18p3BuIQN3OYWjFIM","object":"chat.completion.chunk","created":1730680125,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"id":"call_SGVgEhhsqfE7s6MOHSXwKSGG","type":"function","function":{"name":"get_current_weather","arguments":""}}]},"logprobs":null,"finish_reason":null}]}
+ data: {"id":"chatcmpl-ASYMbACebDoWcuraMEWQhU48q4dAp","object":"chat.completion.chunk","created":1731368641,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_9b78b61c52","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"id":"call_3J9foSw3CUb48lrqIXoTky6U","type":"function","function":{"name":"get_current_weather","arguments":""}}]},"logprobs":null,"finish_reason":null}]}
- data: {"id":"chatcmpl-APfFVrgZUKVR18p3BuIQN3OYWjFIM","object":"chat.completion.chunk","created":1730680125,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"{\"lo"}}]},"logprobs":null,"finish_reason":null}]}
+ data: {"id":"chatcmpl-ASYMbACebDoWcuraMEWQhU48q4dAp","object":"chat.completion.chunk","created":1731368641,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_9b78b61c52","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"{\"lo"}}]},"logprobs":null,"finish_reason":null}]}
- data: {"id":"chatcmpl-APfFVrgZUKVR18p3BuIQN3OYWjFIM","object":"chat.completion.chunk","created":1730680125,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"catio"}}]},"logprobs":null,"finish_reason":null}]}
+ data: {"id":"chatcmpl-ASYMbACebDoWcuraMEWQhU48q4dAp","object":"chat.completion.chunk","created":1731368641,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_9b78b61c52","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"catio"}}]},"logprobs":null,"finish_reason":null}]}
- data: {"id":"chatcmpl-APfFVrgZUKVR18p3BuIQN3OYWjFIM","object":"chat.completion.chunk","created":1730680125,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"n\": \"S"}}]},"logprobs":null,"finish_reason":null}]}
+ data: {"id":"chatcmpl-ASYMbACebDoWcuraMEWQhU48q4dAp","object":"chat.completion.chunk","created":1731368641,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_9b78b61c52","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"n\": \"S"}}]},"logprobs":null,"finish_reason":null}]}
- data: {"id":"chatcmpl-APfFVrgZUKVR18p3BuIQN3OYWjFIM","object":"chat.completion.chunk","created":1730680125,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"an F"}}]},"logprobs":null,"finish_reason":null}]}
+ data: {"id":"chatcmpl-ASYMbACebDoWcuraMEWQhU48q4dAp","object":"chat.completion.chunk","created":1731368641,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_9b78b61c52","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"an F"}}]},"logprobs":null,"finish_reason":null}]}
- data: {"id":"chatcmpl-APfFVrgZUKVR18p3BuIQN3OYWjFIM","object":"chat.completion.chunk","created":1730680125,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"ranci"}}]},"logprobs":null,"finish_reason":null}]}
+ data: {"id":"chatcmpl-ASYMbACebDoWcuraMEWQhU48q4dAp","object":"chat.completion.chunk","created":1731368641,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_9b78b61c52","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"ranci"}}]},"logprobs":null,"finish_reason":null}]}
- data: {"id":"chatcmpl-APfFVrgZUKVR18p3BuIQN3OYWjFIM","object":"chat.completion.chunk","created":1730680125,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"sco, C"}}]},"logprobs":null,"finish_reason":null}]}
+ data: {"id":"chatcmpl-ASYMbACebDoWcuraMEWQhU48q4dAp","object":"chat.completion.chunk","created":1731368641,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_9b78b61c52","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"sco, C"}}]},"logprobs":null,"finish_reason":null}]}
- data: {"id":"chatcmpl-APfFVrgZUKVR18p3BuIQN3OYWjFIM","object":"chat.completion.chunk","created":1730680125,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"A\"}"}}]},"logprobs":null,"finish_reason":null}]}
+ data: {"id":"chatcmpl-ASYMbACebDoWcuraMEWQhU48q4dAp","object":"chat.completion.chunk","created":1731368641,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_9b78b61c52","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"A\"}"}}]},"logprobs":null,"finish_reason":null}]}
- data: {"id":"chatcmpl-APfFVrgZUKVR18p3BuIQN3OYWjFIM","object":"chat.completion.chunk","created":1730680125,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"tool_calls"}],"usage":null}
+ data: {"id":"chatcmpl-ASYMbACebDoWcuraMEWQhU48q4dAp","object":"chat.completion.chunk","created":1731368641,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_9b78b61c52","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"tool_calls"}],"usage":null}
- data: {"id":"chatcmpl-APfFVrgZUKVR18p3BuIQN3OYWjFIM","object":"chat.completion.chunk","created":1730680125,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_0ba0d124f1","choices":[],"usage":{"prompt_tokens":75,"completion_tokens":51,"total_tokens":126,"prompt_tokens_details":{"cached_tokens":0},"completion_tokens_details":{"reasoning_tokens":0}}}
+ data: {"id":"chatcmpl-ASYMbACebDoWcuraMEWQhU48q4dAp","object":"chat.completion.chunk","created":1731368641,"model":"gpt-4o-mini-2024-07-18","system_fingerprint":"fp_9b78b61c52","choices":[],"usage":{"prompt_tokens":75,"completion_tokens":51,"total_tokens":126,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}}}
data: [DONE]
@@ -117,13 +121,13 @@ interactions:
CF-Cache-Status:
- DYNAMIC
CF-RAY:
- - 8dd07c5d48f0ce22-SIN
+ - 8e1225d8af0c3d93-SIN
Connection:
- keep-alive
Content-Type:
- text/event-stream; charset=utf-8
Date:
- - Mon, 04 Nov 2024 00:28:48 GMT
+ - Mon, 11 Nov 2024 23:44:03 GMT
Server:
- cloudflare
Set-Cookie: test_set_cookie
@@ -135,9 +139,9 @@ interactions:
- X-Request-ID
alt-svc:
- h3=":443"; ma=86400
- openai-organization: test_organization
+ openai-organization: test_openai_org_id
openai-processing-ms:
- - '2886'
+ - '1399'
openai-version:
- '2020-10-01'
strict-transport-security:
@@ -151,11 +155,11 @@ interactions:
x-ratelimit-remaining-tokens:
- '199961'
x-ratelimit-reset-requests:
- - 1m6.499s
+ - 1m6.779s
x-ratelimit-reset-tokens:
- 11ms
x-request-id:
- - req_c887b8540fec8e4eadca5d56c78cc4e1
+ - req_d745d48bf030ac78e4790ee49848d05f
status:
code: 200
message: OK
diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_streaming.yaml b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_streaming.yaml
index 713ea762e0..db482a440c 100644
--- a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_streaming.yaml
+++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_streaming.yaml
@@ -19,6 +19,8 @@ interactions:
- application/json
accept-encoding:
- gzip, deflate
+ authorization:
+ - Bearer test_openai_api_key
connection:
- keep-alive
content-length:
@@ -28,7 +30,7 @@ interactions:
host:
- api.openai.com
user-agent:
- - OpenAI/Python 1.26.0
+ - OpenAI/Python 1.54.3
x-stainless-arch:
- arm64
x-stainless-async:
@@ -38,7 +40,9 @@ interactions:
x-stainless-os:
- MacOS
x-stainless-package-version:
- - 1.26.0
+ - 1.54.3
+ x-stainless-retry-count:
+ - '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
@@ -48,21 +52,21 @@ interactions:
response:
body:
string: |+
- data: {"id":"chatcmpl-APfFSQXvyhxafsCMim55E7utaYINv","object":"chat.completion.chunk","created":1730680122,"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-ASYMZ4oSykiIFK4lXLReDiKyAjsQl","object":"chat.completion.chunk","created":1731368639,"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-APfFSQXvyhxafsCMim55E7utaYINv","object":"chat.completion.chunk","created":1730680122,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"This"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMZ4oSykiIFK4lXLReDiKyAjsQl","object":"chat.completion.chunk","created":1731368639,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"\"This"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFSQXvyhxafsCMim55E7utaYINv","object":"chat.completion.chunk","created":1730680122,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" is"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMZ4oSykiIFK4lXLReDiKyAjsQl","object":"chat.completion.chunk","created":1731368639,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" is"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFSQXvyhxafsCMim55E7utaYINv","object":"chat.completion.chunk","created":1730680122,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" a"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMZ4oSykiIFK4lXLReDiKyAjsQl","object":"chat.completion.chunk","created":1731368639,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" a"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFSQXvyhxafsCMim55E7utaYINv","object":"chat.completion.chunk","created":1730680122,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" test"},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMZ4oSykiIFK4lXLReDiKyAjsQl","object":"chat.completion.chunk","created":1731368639,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" test"},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFSQXvyhxafsCMim55E7utaYINv","object":"chat.completion.chunk","created":1730680122,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"."},"logprobs":null,"finish_reason":null}],"usage":null}
+ data: {"id":"chatcmpl-ASYMZ4oSykiIFK4lXLReDiKyAjsQl","object":"chat.completion.chunk","created":1731368639,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":".\""},"logprobs":null,"finish_reason":null}],"usage":null}
- data: {"id":"chatcmpl-APfFSQXvyhxafsCMim55E7utaYINv","object":"chat.completion.chunk","created":1730680122,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null}
+ data: {"id":"chatcmpl-ASYMZ4oSykiIFK4lXLReDiKyAjsQl","object":"chat.completion.chunk","created":1731368639,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null}
- data: {"id":"chatcmpl-APfFSQXvyhxafsCMim55E7utaYINv","object":"chat.completion.chunk","created":1730680122,"model":"gpt-4-0613","system_fingerprint":null,"choices":[],"usage":{"prompt_tokens":12,"completion_tokens":5,"total_tokens":17,"prompt_tokens_details":{"cached_tokens":0},"completion_tokens_details":{"reasoning_tokens":0}}}
+ data: {"id":"chatcmpl-ASYMZ4oSykiIFK4lXLReDiKyAjsQl","object":"chat.completion.chunk","created":1731368639,"model":"gpt-4-0613","system_fingerprint":null,"choices":[],"usage":{"prompt_tokens":12,"completion_tokens":5,"total_tokens":17,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}}}
data: [DONE]
@@ -70,13 +74,13 @@ interactions:
CF-Cache-Status:
- DYNAMIC
CF-RAY:
- - 8dd07c4b99b74927-SIN
+ - 8e1225c87b273e53-SIN
Connection:
- keep-alive
Content-Type:
- text/event-stream; charset=utf-8
Date:
- - Mon, 04 Nov 2024 00:28:42 GMT
+ - Mon, 11 Nov 2024 23:43:59 GMT
Server:
- cloudflare
Set-Cookie: test_set_cookie
@@ -88,9 +92,9 @@ interactions:
- X-Request-ID
alt-svc:
- h3=":443"; ma=86400
- openai-organization: test_organization
+ openai-organization: test_openai_org_id
openai-processing-ms:
- - '157'
+ - '207'
openai-version:
- '2020-10-01'
strict-transport-security:
@@ -108,7 +112,7 @@ interactions:
x-ratelimit-reset-tokens:
- 132ms
x-request-id:
- - req_72de20dac77a9535e3f47a6ec3a39ddc
+ - req_c367cf360ee88481fb7cd6c5d45bf9dc
status:
code: 200
message: OK
diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_streaming_not_complete.yaml b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_streaming_not_complete.yaml
index bec0658770..4d56e51a06 100644
--- a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_streaming_not_complete.yaml
+++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_streaming_not_complete.yaml
@@ -16,6 +16,8 @@ interactions:
- application/json
accept-encoding:
- gzip, deflate
+ authorization:
+ - Bearer test_openai_api_key
connection:
- keep-alive
content-length:
@@ -25,7 +27,7 @@ interactions:
host:
- api.openai.com
user-agent:
- - OpenAI/Python 1.26.0
+ - OpenAI/Python 1.54.3
x-stainless-arch:
- arm64
x-stainless-async:
@@ -35,7 +37,9 @@ interactions:
x-stainless-os:
- MacOS
x-stainless-package-version:
- - 1.26.0
+ - 1.54.3
+ x-stainless-retry-count:
+ - '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
@@ -45,19 +49,19 @@ interactions:
response:
body:
string: |+
- data: {"id":"chatcmpl-APfFTxI7bvaTTeQd32CHwpV6GKo7x","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}]}
+ data: {"id":"chatcmpl-ASYMZbRqo8Bkz53FVzaTj7W7feOn4","object":"chat.completion.chunk","created":1731368639,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}]}
- data: {"id":"chatcmpl-APfFTxI7bvaTTeQd32CHwpV6GKo7x","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"This"},"logprobs":null,"finish_reason":null}]}
+ data: {"id":"chatcmpl-ASYMZbRqo8Bkz53FVzaTj7W7feOn4","object":"chat.completion.chunk","created":1731368639,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"This"},"logprobs":null,"finish_reason":null}]}
- data: {"id":"chatcmpl-APfFTxI7bvaTTeQd32CHwpV6GKo7x","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" is"},"logprobs":null,"finish_reason":null}]}
+ data: {"id":"chatcmpl-ASYMZbRqo8Bkz53FVzaTj7W7feOn4","object":"chat.completion.chunk","created":1731368639,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" is"},"logprobs":null,"finish_reason":null}]}
- data: {"id":"chatcmpl-APfFTxI7bvaTTeQd32CHwpV6GKo7x","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" a"},"logprobs":null,"finish_reason":null}]}
+ data: {"id":"chatcmpl-ASYMZbRqo8Bkz53FVzaTj7W7feOn4","object":"chat.completion.chunk","created":1731368639,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" a"},"logprobs":null,"finish_reason":null}]}
- data: {"id":"chatcmpl-APfFTxI7bvaTTeQd32CHwpV6GKo7x","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" test"},"logprobs":null,"finish_reason":null}]}
+ data: {"id":"chatcmpl-ASYMZbRqo8Bkz53FVzaTj7W7feOn4","object":"chat.completion.chunk","created":1731368639,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" test"},"logprobs":null,"finish_reason":null}]}
- data: {"id":"chatcmpl-APfFTxI7bvaTTeQd32CHwpV6GKo7x","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"."},"logprobs":null,"finish_reason":null}]}
+ data: {"id":"chatcmpl-ASYMZbRqo8Bkz53FVzaTj7W7feOn4","object":"chat.completion.chunk","created":1731368639,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"."},"logprobs":null,"finish_reason":null}]}
- data: {"id":"chatcmpl-APfFTxI7bvaTTeQd32CHwpV6GKo7x","object":"chat.completion.chunk","created":1730680123,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}]}
+ data: {"id":"chatcmpl-ASYMZbRqo8Bkz53FVzaTj7W7feOn4","object":"chat.completion.chunk","created":1731368639,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}]}
data: [DONE]
@@ -65,13 +69,13 @@ interactions:
CF-Cache-Status:
- DYNAMIC
CF-RAY:
- - 8dd07c505e24cdf2-SIN
+ - 8e1225ccb98e823b-SIN
Connection:
- keep-alive
Content-Type:
- text/event-stream; charset=utf-8
Date:
- - Mon, 04 Nov 2024 00:28:43 GMT
+ - Mon, 11 Nov 2024 23:43:59 GMT
Server:
- cloudflare
Set-Cookie: test_set_cookie
@@ -83,9 +87,9 @@ interactions:
- X-Request-ID
alt-svc:
- h3=":443"; ma=86400
- openai-organization: test_organization
+ openai-organization: test_openai_org_id
openai-processing-ms:
- - '269'
+ - '205'
openai-version:
- '2020-10-01'
strict-transport-security:
@@ -99,11 +103,11 @@ interactions:
x-ratelimit-remaining-tokens:
- '9978'
x-ratelimit-reset-requests:
- - 16.502s
+ - 16.601s
x-ratelimit-reset-tokens:
- 132ms
x-request-id:
- - req_04c174debe2eace86b1e2777d7ac7265
+ - req_d13225164a822ec3ebab5591ed0b6d6a
status:
code: 200
message: OK
diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_tool_calls_no_content.yaml b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_tool_calls_no_content.yaml
index b4d5acca4a..4731f202c3 100644
--- a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_tool_calls_no_content.yaml
+++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_tool_calls_no_content.yaml
@@ -42,6 +42,8 @@ interactions:
- application/json
accept-encoding:
- gzip, deflate
+ authorization:
+ - Bearer test_openai_api_key
connection:
- keep-alive
content-length:
@@ -51,7 +53,7 @@ interactions:
host:
- api.openai.com
user-agent:
- - OpenAI/Python 1.26.0
+ - OpenAI/Python 1.54.3
x-stainless-arch:
- arm64
x-stainless-async:
@@ -61,7 +63,9 @@ interactions:
x-stainless-os:
- MacOS
x-stainless-package-version:
- - 1.26.0
+ - 1.54.3
+ x-stainless-retry-count:
+ - '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
@@ -72,9 +76,9 @@ interactions:
body:
string: |-
{
- "id": "chatcmpl-APfFQZB7CuqkWhGyMZegJZRX2Mqv7",
+ "id": "chatcmpl-ASYMW6w3m9qqpHUVhYTbQbw61zMqA",
"object": "chat.completion",
- "created": 1730680120,
+ "created": 1731368636,
"model": "gpt-4o-mini-2024-07-18",
"choices": [
{
@@ -84,7 +88,7 @@ interactions:
"content": null,
"tool_calls": [
{
- "id": "call_SBoEJuTov3qHLothPvvgZyO6",
+ "id": "call_eqbDFUdPqay2WjsSzZEiAn0U",
"type": "function",
"function": {
"name": "get_current_weather",
@@ -92,7 +96,7 @@ interactions:
}
},
{
- "id": "call_2nL8HxSquLkKxpTENiZ17ynv",
+ "id": "call_tn3sgasg6GaftTdancBYJNJN",
"type": "function",
"function": {
"name": "get_current_weather",
@@ -111,10 +115,14 @@ interactions:
"completion_tokens": 51,
"total_tokens": 126,
"prompt_tokens_details": {
- "cached_tokens": 0
+ "cached_tokens": 0,
+ "audio_tokens": 0
},
"completion_tokens_details": {
- "reasoning_tokens": 0
+ "reasoning_tokens": 0,
+ "audio_tokens": 0,
+ "accepted_prediction_tokens": 0,
+ "rejected_prediction_tokens": 0
}
},
"system_fingerprint": "fp_0ba0d124f1"
@@ -123,13 +131,13 @@ interactions:
CF-Cache-Status:
- DYNAMIC
CF-RAY:
- - 8dd07c3f4ba7ce35-SIN
+ - 8e1225ba6a3440b0-SIN
Connection:
- keep-alive
Content-Type:
- application/json
Date:
- - Mon, 04 Nov 2024 00:28:41 GMT
+ - Mon, 11 Nov 2024 23:43:57 GMT
Server:
- cloudflare
Set-Cookie: test_set_cookie
@@ -142,10 +150,10 @@ interactions:
alt-svc:
- h3=":443"; ma=86400
content-length:
- - '1180'
- openai-organization: test_organization
+ - '1308'
+ openai-organization: test_openai_org_id
openai-processing-ms:
- - '984'
+ - '761'
openai-version:
- '2020-10-01'
strict-transport-security:
@@ -159,11 +167,11 @@ interactions:
x-ratelimit-remaining-tokens:
- '199961'
x-ratelimit-reset-requests:
- - 45.38s
+ - 45.694s
x-ratelimit-reset-tokens:
- 11ms
x-request-id:
- - req_af3dca7532583ed0a68645314bcc9be0
+ - req_f98710550c77b43865572fc1a7a0bc53
status:
code: 200
message: OK
@@ -183,7 +191,7 @@ interactions:
"role": "assistant",
"tool_calls": [
{
- "id": "call_SBoEJuTov3qHLothPvvgZyO6",
+ "id": "call_eqbDFUdPqay2WjsSzZEiAn0U",
"function": {
"arguments": "{\"location\": \"Seattle, WA\"}",
"name": "get_current_weather"
@@ -191,7 +199,7 @@ interactions:
"type": "function"
},
{
- "id": "call_2nL8HxSquLkKxpTENiZ17ynv",
+ "id": "call_tn3sgasg6GaftTdancBYJNJN",
"function": {
"arguments": "{\"location\": \"San Francisco, CA\"}",
"name": "get_current_weather"
@@ -203,12 +211,12 @@ interactions:
{
"role": "tool",
"content": "50 degrees and raining",
- "tool_call_id": "call_SBoEJuTov3qHLothPvvgZyO6"
+ "tool_call_id": "call_eqbDFUdPqay2WjsSzZEiAn0U"
},
{
"role": "tool",
"content": "70 degrees and sunny",
- "tool_call_id": "call_2nL8HxSquLkKxpTENiZ17ynv"
+ "tool_call_id": "call_tn3sgasg6GaftTdancBYJNJN"
}
],
"model": "gpt-4o-mini"
@@ -218,6 +226,8 @@ interactions:
- application/json
accept-encoding:
- gzip, deflate
+ authorization:
+ - Bearer test_openai_api_key
connection:
- keep-alive
content-length:
@@ -225,12 +235,11 @@ interactions:
content-type:
- application/json
cookie:
- - __cf_bm=moy9FTa50Ug99_ZQaP2atn.PgzKoQyF7pvWqG_CIf54-1730680121-1.0.1.1-mczyecbBSU5hWl8uat1lcU6ya1g6MY.Oso_vHVilj7O8C2RJrObTEyzD5DAMphUCFqBYVGHMurXg16CMssvuNw;
- _cfuvid=FpMMQOb0sz4wVuQI7b1RY2KJKVNyHctKOqsWAL4tph0-1730680121454-0.0.1.1-604800000
+ - test_cookie
host:
- api.openai.com
user-agent:
- - OpenAI/Python 1.26.0
+ - OpenAI/Python 1.54.3
x-stainless-arch:
- arm64
x-stainless-async:
@@ -240,7 +249,9 @@ interactions:
x-stainless-os:
- MacOS
x-stainless-package-version:
- - 1.26.0
+ - 1.54.3
+ x-stainless-retry-count:
+ - '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
@@ -251,16 +262,16 @@ interactions:
body:
string: |-
{
- "id": "chatcmpl-APfFRbb22UJc07TGY9KcrrWO5fs9c",
+ "id": "chatcmpl-ASYMYObbcUyZ77rbvypWmcZPIVSf1",
"object": "chat.completion",
- "created": 1730680121,
+ "created": 1731368638,
"model": "gpt-4o-mini-2024-07-18",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
- "content": "Today, the weather in Seattle is 50 degrees and raining, while in San Francisco, it's 70 degrees and sunny.",
+ "content": "Today, the weather in Seattle is 50 degrees and raining, while San Francisco is enjoying 70 degrees and sunny weather.",
"refusal": null
},
"logprobs": null,
@@ -272,10 +283,14 @@ interactions:
"completion_tokens": 25,
"total_tokens": 124,
"prompt_tokens_details": {
- "cached_tokens": 0
+ "cached_tokens": 0,
+ "audio_tokens": 0
},
"completion_tokens_details": {
- "reasoning_tokens": 0
+ "reasoning_tokens": 0,
+ "audio_tokens": 0,
+ "accepted_prediction_tokens": 0,
+ "rejected_prediction_tokens": 0
}
},
"system_fingerprint": "fp_0ba0d124f1"
@@ -284,13 +299,13 @@ interactions:
CF-Cache-Status:
- DYNAMIC
CF-RAY:
- - 8dd07c473cc4ce35-SIN
+ - 8e1225c12f6340b0-SIN
Connection:
- keep-alive
Content-Type:
- application/json
Date:
- - Mon, 04 Nov 2024 00:28:42 GMT
+ - Mon, 11 Nov 2024 23:43:58 GMT
Server:
- cloudflare
Set-Cookie: test_set_cookie
@@ -303,10 +318,10 @@ interactions:
alt-svc:
- h3=":443"; ma=86400
content-length:
- - '731'
- openai-organization: test_organization
+ - '870'
+ openai-organization: test_openai_org_id
openai-processing-ms:
- - '380'
+ - '722'
openai-version:
- '2020-10-01'
strict-transport-security:
@@ -318,13 +333,13 @@ interactions:
x-ratelimit-remaining-requests:
- '9993'
x-ratelimit-remaining-tokens:
- - '199947'
+ - '199948'
x-ratelimit-reset-requests:
- - 52.749s
+ - 53.254s
x-ratelimit-reset-tokens:
- 15ms
x-request-id:
- - req_f56de3d8b168900542a01b971b367a9f
+ - req_2bb3d10a2a75f5d64a24aef595a0d8dd
status:
code: 200
message: OK
diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_tool_calls_with_content.yaml b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_tool_calls_with_content.yaml
index fbf1abd640..6ceb618d24 100644
--- a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_tool_calls_with_content.yaml
+++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_tool_calls_with_content.yaml
@@ -42,6 +42,8 @@ interactions:
- application/json
accept-encoding:
- gzip, deflate
+ authorization:
+ - Bearer test_openai_api_key
connection:
- keep-alive
content-length:
@@ -51,7 +53,7 @@ interactions:
host:
- api.openai.com
user-agent:
- - OpenAI/Python 1.26.0
+ - OpenAI/Python 1.54.3
x-stainless-arch:
- arm64
x-stainless-async:
@@ -61,7 +63,9 @@ interactions:
x-stainless-os:
- MacOS
x-stainless-package-version:
- - 1.26.0
+ - 1.54.3
+ x-stainless-retry-count:
+ - '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
@@ -72,9 +76,9 @@ interactions:
body:
string: |-
{
- "id": "chatcmpl-APfFOuWLsYvVpZYqENRo9rKnifNdD",
+ "id": "chatcmpl-ASYMU9Ntix7ePttk0MSuerJstef6U",
"object": "chat.completion",
- "created": 1730680118,
+ "created": 1731368634,
"model": "gpt-4o-mini-2024-07-18",
"choices": [
{
@@ -84,7 +88,7 @@ interactions:
"content": null,
"tool_calls": [
{
- "id": "call_6YvurIMPOgMo2q6V6KGJDA6g",
+ "id": "call_JpNb8OiAkbIbHzDggfpdDHpi",
"type": "function",
"function": {
"name": "get_current_weather",
@@ -92,7 +96,7 @@ interactions:
}
},
{
- "id": "call_QSiqEulo25M3NtTLVbMGqY91",
+ "id": "call_vaFQc3zK6hHTRZKXRI5Eo2cJ",
"type": "function",
"function": {
"name": "get_current_weather",
@@ -111,10 +115,14 @@ interactions:
"completion_tokens": 51,
"total_tokens": 126,
"prompt_tokens_details": {
- "cached_tokens": 0
+ "cached_tokens": 0,
+ "audio_tokens": 0
},
"completion_tokens_details": {
- "reasoning_tokens": 0
+ "reasoning_tokens": 0,
+ "audio_tokens": 0,
+ "accepted_prediction_tokens": 0,
+ "rejected_prediction_tokens": 0
}
},
"system_fingerprint": "fp_0ba0d124f1"
@@ -123,13 +131,13 @@ interactions:
CF-Cache-Status:
- DYNAMIC
CF-RAY:
- - 8dd07c349cb38bcb-SIN
+ - 8e1225ae3ea281e4-SIN
Connection:
- keep-alive
Content-Type:
- application/json
Date:
- - Mon, 04 Nov 2024 00:28:39 GMT
+ - Mon, 11 Nov 2024 23:43:55 GMT
Server:
- cloudflare
Set-Cookie: test_set_cookie
@@ -142,10 +150,10 @@ interactions:
alt-svc:
- h3=":443"; ma=86400
content-length:
- - '1180'
- openai-organization: test_organization
+ - '1308'
+ openai-organization: test_openai_org_id
openai-processing-ms:
- - '631'
+ - '748'
openai-version:
- '2020-10-01'
strict-transport-security:
@@ -159,11 +167,11 @@ interactions:
x-ratelimit-remaining-tokens:
- '199961'
x-ratelimit-reset-requests:
- - 29.791s
+ - 30.375s
x-ratelimit-reset-tokens:
- 11ms
x-request-id:
- - req_a121f023915b3c4a2ca2415663e54dd8
+ - req_a0c3b432eb349a35b6d8dde6e01451e4
status:
code: 200
message: OK
@@ -183,7 +191,7 @@ interactions:
"role": "assistant",
"tool_calls": [
{
- "id": "call_6YvurIMPOgMo2q6V6KGJDA6g",
+ "id": "call_JpNb8OiAkbIbHzDggfpdDHpi",
"function": {
"arguments": "{\"location\": \"Seattle, WA\"}",
"name": "get_current_weather"
@@ -191,7 +199,7 @@ interactions:
"type": "function"
},
{
- "id": "call_QSiqEulo25M3NtTLVbMGqY91",
+ "id": "call_vaFQc3zK6hHTRZKXRI5Eo2cJ",
"function": {
"arguments": "{\"location\": \"San Francisco, CA\"}",
"name": "get_current_weather"
@@ -203,12 +211,12 @@ interactions:
{
"role": "tool",
"content": "50 degrees and raining",
- "tool_call_id": "call_6YvurIMPOgMo2q6V6KGJDA6g"
+ "tool_call_id": "call_JpNb8OiAkbIbHzDggfpdDHpi"
},
{
"role": "tool",
"content": "70 degrees and sunny",
- "tool_call_id": "call_QSiqEulo25M3NtTLVbMGqY91"
+ "tool_call_id": "call_vaFQc3zK6hHTRZKXRI5Eo2cJ"
}
],
"model": "gpt-4o-mini"
@@ -218,6 +226,8 @@ interactions:
- application/json
accept-encoding:
- gzip, deflate
+ authorization:
+ - Bearer test_openai_api_key
connection:
- keep-alive
content-length:
@@ -225,12 +235,11 @@ interactions:
content-type:
- application/json
cookie:
- - __cf_bm=Fyf0tyDn1mwa_82CHRs1nppW_PehJkXoYvNM4ZjPbXY-1730680119-1.0.1.1-yjV4_xtp96WEMEexlzeQsjZfgRKwMtgjBU5ysQffHMNwXbTqmZdE_pCTtQTmJ97xP37rkkAHdzC7O8661FKZ9A;
- _cfuvid=WLvZI_.UlWSOmjux14bNggQUKClph3WCDG.6pjaRbjI-1730680119424-0.0.1.1-604800000
+ - test_cookie
host:
- api.openai.com
user-agent:
- - OpenAI/Python 1.26.0
+ - OpenAI/Python 1.54.3
x-stainless-arch:
- arm64
x-stainless-async:
@@ -240,7 +249,9 @@ interactions:
x-stainless-os:
- MacOS
x-stainless-package-version:
- - 1.26.0
+ - 1.54.3
+ x-stainless-retry-count:
+ - '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
@@ -251,9 +262,9 @@ interactions:
body:
string: |-
{
- "id": "chatcmpl-APfFP2ZYRsgIvw0HuTVbYFDxFs7Si",
+ "id": "chatcmpl-ASYMVzdmBGDbUoHFmt6R16tdtZUzR",
"object": "chat.completion",
- "created": 1730680119,
+ "created": 1731368635,
"model": "gpt-4o-mini-2024-07-18",
"choices": [
{
@@ -272,25 +283,29 @@ interactions:
"completion_tokens": 25,
"total_tokens": 124,
"prompt_tokens_details": {
- "cached_tokens": 0
+ "cached_tokens": 0,
+ "audio_tokens": 0
},
"completion_tokens_details": {
- "reasoning_tokens": 0
+ "reasoning_tokens": 0,
+ "audio_tokens": 0,
+ "accepted_prediction_tokens": 0,
+ "rejected_prediction_tokens": 0
}
},
- "system_fingerprint": "fp_0ba0d124f1"
+ "system_fingerprint": "fp_9b78b61c52"
}
headers:
CF-Cache-Status:
- DYNAMIC
CF-RAY:
- - 8dd07c3ad9138bcb-SIN
+ - 8e1225b4cbf581e4-SIN
Connection:
- keep-alive
Content-Type:
- application/json
Date:
- - Mon, 04 Nov 2024 00:28:40 GMT
+ - Mon, 11 Nov 2024 23:43:56 GMT
Server:
- cloudflare
Set-Cookie: test_set_cookie
@@ -303,10 +318,10 @@ interactions:
alt-svc:
- h3=":443"; ma=86400
content-length:
- - '731'
- openai-organization: test_organization
+ - '859'
+ openai-organization: test_openai_org_id
openai-processing-ms:
- - '390'
+ - '531'
openai-version:
- '2020-10-01'
strict-transport-security:
@@ -320,11 +335,11 @@ interactions:
x-ratelimit-remaining-tokens:
- '199947'
x-ratelimit-reset-requests:
- - 37.448s
+ - 37.973s
x-ratelimit-reset-tokens:
- 15ms
x-request-id:
- - req_525d3b9301fff00a98647143a9c26b6f
+ - req_22b79d2dddb920f55e33727d06724978
status:
code: 200
message: OK
diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_with_content.yaml b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_with_content.yaml
index bb61c001fb..2abb443fe3 100644
--- a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_with_content.yaml
+++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/cassettes/test_chat_completion_with_content.yaml
@@ -16,6 +16,8 @@ interactions:
- application/json
accept-encoding:
- gzip, deflate
+ authorization:
+ - Bearer test_openai_api_key
connection:
- keep-alive
content-length:
@@ -25,7 +27,7 @@ interactions:
host:
- api.openai.com
user-agent:
- - OpenAI/Python 1.26.0
+ - OpenAI/Python 1.54.3
x-stainless-arch:
- arm64
x-stainless-async:
@@ -35,7 +37,9 @@ interactions:
x-stainless-os:
- MacOS
x-stainless-package-version:
- - 1.26.0
+ - 1.54.3
+ x-stainless-retry-count:
+ - '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
@@ -46,16 +50,16 @@ interactions:
body:
string: |-
{
- "id": "chatcmpl-APfFJNBzCZVUpMJMK5KBhu4D6yVAc",
+ "id": "chatcmpl-ASYMQRl3A3DXL9FWCK9tnGRcKIO7q",
"object": "chat.completion",
- "created": 1730680113,
+ "created": 1731368630,
"model": "gpt-4o-mini-2024-07-18",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
- "content": "This is a test! How can I assist you today?",
+ "content": "This is a test.",
"refusal": null
},
"logprobs": null,
@@ -64,13 +68,17 @@ interactions:
],
"usage": {
"prompt_tokens": 12,
- "completion_tokens": 12,
- "total_tokens": 24,
+ "completion_tokens": 5,
+ "total_tokens": 17,
"prompt_tokens_details": {
- "cached_tokens": 0
+ "cached_tokens": 0,
+ "audio_tokens": 0
},
"completion_tokens_details": {
- "reasoning_tokens": 0
+ "reasoning_tokens": 0,
+ "audio_tokens": 0,
+ "accepted_prediction_tokens": 0,
+ "rejected_prediction_tokens": 0
}
},
"system_fingerprint": "fp_0ba0d124f1"
@@ -79,13 +87,13 @@ interactions:
CF-Cache-Status:
- DYNAMIC
CF-RAY:
- - 8dd07c16eae44a1d-SIN
+ - 8e122593ff368bc8-SIN
Connection:
- keep-alive
Content-Type:
- application/json
Date:
- - Mon, 04 Nov 2024 00:28:34 GMT
+ - Mon, 11 Nov 2024 23:43:50 GMT
Server:
- cloudflare
Set-Cookie: test_set_cookie
@@ -98,10 +106,10 @@ interactions:
alt-svc:
- h3=":443"; ma=86400
content-length:
- - '666'
- openai-organization: test_organization
+ - '765'
+ openai-organization: test_openai_org_id
openai-processing-ms:
- - '732'
+ - '287'
openai-version:
- '2020-10-01'
strict-transport-security:
@@ -119,7 +127,7 @@ interactions:
x-ratelimit-reset-tokens:
- 6ms
x-request-id:
- - req_0bb3c9da7d953e477d1947130d2cf1df
+ - req_58cff97afd0e7c0bba910ccf0b044a6f
status:
code: 200
message: OK
diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/conftest.py b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/conftest.py
index 899b2f122c..7ff7e46777 100644
--- a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/conftest.py
+++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/conftest.py
@@ -5,7 +5,7 @@
import pytest
import yaml
-from openai import OpenAI
+from openai import AsyncOpenAI, OpenAI
from opentelemetry.instrumentation.openai_v2 import OpenAIInstrumentor
from opentelemetry.instrumentation.openai_v2.utils import (
@@ -55,7 +55,7 @@ def fixture_event_logger_provider(log_exporter):
@pytest.fixture(autouse=True)
def environment():
if not os.getenv("OPENAI_API_KEY"):
- os.environ["OPENAI_API_KEY"] = "test-api-key"
+ os.environ["OPENAI_API_KEY"] = "test_openai_api_key"
@pytest.fixture
@@ -63,10 +63,20 @@ def openai_client():
return OpenAI()
+@pytest.fixture
+def async_openai_client():
+ return AsyncOpenAI()
+
+
@pytest.fixture(scope="module")
def vcr_config():
return {
- "filter_headers": ["authorization", "api-key"],
+ "filter_headers": [
+ ("cookie", "test_cookie"),
+ ("authorization", "Bearer test_openai_api_key"),
+ ("openai-organization", "test_openai_org_id"),
+ ("openai-project", "test_openai_project_id"),
+ ],
"decode_compressed_response": True,
"before_record_response": scrub_response_headers,
}
@@ -171,6 +181,6 @@ def scrub_response_headers(response):
"""
This scrubs sensitive response headers. Note they are case-sensitive!
"""
- response["headers"]["openai-organization"] = "test_organization"
+ response["headers"]["openai-organization"] = "test_openai_org_id"
response["headers"]["Set-Cookie"] = "test_set_cookie"
return response
diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/test_async_chat_completions.py b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/test_async_chat_completions.py
new file mode 100644
index 0000000000..1c4b3cb7dd
--- /dev/null
+++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/test_async_chat_completions.py
@@ -0,0 +1,847 @@
+# 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.
+# pylint: disable=too-many-locals
+
+from typing import Optional
+
+import pytest
+from openai import APIConnectionError, AsyncOpenAI, NotFoundError
+from openai.resources.chat.completions import ChatCompletion
+
+from opentelemetry.sdk.trace import ReadableSpan
+from opentelemetry.semconv._incubating.attributes import (
+ error_attributes as ErrorAttributes,
+)
+from opentelemetry.semconv._incubating.attributes import (
+ event_attributes as EventAttributes,
+)
+from opentelemetry.semconv._incubating.attributes import (
+ gen_ai_attributes as GenAIAttributes,
+)
+from opentelemetry.semconv._incubating.attributes import (
+ server_attributes as ServerAttributes,
+)
+
+
+@pytest.mark.vcr()
+@pytest.mark.asyncio()
+async def test_async_chat_completion_with_content(
+ span_exporter, log_exporter, async_openai_client, instrument_with_content
+):
+ llm_model_value = "gpt-4o-mini"
+ messages_value = [{"role": "user", "content": "Say this is a test"}]
+
+ response = await async_openai_client.chat.completions.create(
+ messages=messages_value, model=llm_model_value, stream=False
+ )
+
+ spans = span_exporter.get_finished_spans()
+ assert_completion_attributes(spans[0], llm_model_value, response)
+
+ logs = log_exporter.get_finished_logs()
+ assert len(logs) == 2
+
+ user_message = {"content": messages_value[0]["content"]}
+ assert_message_in_logs(
+ logs[0], "gen_ai.user.message", user_message, spans[0]
+ )
+
+ choice_event = {
+ "index": 0,
+ "finish_reason": "stop",
+ "message": {
+ "role": "assistant",
+ "content": response.choices[0].message.content,
+ },
+ }
+ assert_message_in_logs(logs[1], "gen_ai.choice", choice_event, spans[0])
+
+
+@pytest.mark.asyncio()
+async def test_async_chat_completion_bad_endpoint(
+ span_exporter, instrument_no_content
+):
+ llm_model_value = "gpt-4o-mini"
+ messages_value = [{"role": "user", "content": "Say this is a test"}]
+
+ client = AsyncOpenAI(base_url="http://localhost:4242")
+
+ with pytest.raises(APIConnectionError):
+ await client.chat.completions.create(
+ messages=messages_value,
+ model=llm_model_value,
+ timeout=0.1,
+ )
+
+ spans = span_exporter.get_finished_spans()
+ assert_all_attributes(
+ spans[0], llm_model_value, server_address="localhost"
+ )
+ assert 4242 == spans[0].attributes[ServerAttributes.SERVER_PORT]
+ assert (
+ "APIConnectionError" == spans[0].attributes[ErrorAttributes.ERROR_TYPE]
+ )
+
+
+@pytest.mark.vcr()
+@pytest.mark.asyncio()
+async def test_async_chat_completion_404(
+ span_exporter, async_openai_client, instrument_no_content
+):
+ llm_model_value = "this-model-does-not-exist"
+ messages_value = [{"role": "user", "content": "Say this is a test"}]
+
+ with pytest.raises(NotFoundError):
+ await async_openai_client.chat.completions.create(
+ messages=messages_value,
+ model=llm_model_value,
+ )
+
+ spans = span_exporter.get_finished_spans()
+
+ assert_all_attributes(spans[0], llm_model_value)
+ assert "NotFoundError" == spans[0].attributes[ErrorAttributes.ERROR_TYPE]
+
+
+@pytest.mark.vcr()
+@pytest.mark.asyncio()
+async def test_async_chat_completion_extra_params(
+ span_exporter, async_openai_client, instrument_no_content
+):
+ llm_model_value = "gpt-4o-mini"
+ messages_value = [{"role": "user", "content": "Say this is a test"}]
+
+ response = await async_openai_client.chat.completions.create(
+ messages=messages_value,
+ model=llm_model_value,
+ seed=42,
+ temperature=0.5,
+ max_tokens=50,
+ stream=False,
+ extra_body={"service_tier": "default"},
+ )
+
+ spans = span_exporter.get_finished_spans()
+ assert_completion_attributes(spans[0], llm_model_value, response)
+ assert (
+ spans[0].attributes[GenAIAttributes.GEN_AI_OPENAI_REQUEST_SEED] == 42
+ )
+ assert (
+ spans[0].attributes[GenAIAttributes.GEN_AI_REQUEST_TEMPERATURE] == 0.5
+ )
+ assert spans[0].attributes[GenAIAttributes.GEN_AI_REQUEST_MAX_TOKENS] == 50
+ assert (
+ spans[0].attributes[GenAIAttributes.GEN_AI_OPENAI_REQUEST_SERVICE_TIER]
+ == "default"
+ )
+
+
+@pytest.mark.vcr()
+@pytest.mark.asyncio()
+async def test_async_chat_completion_multiple_choices(
+ span_exporter, log_exporter, async_openai_client, instrument_with_content
+):
+ llm_model_value = "gpt-4o-mini"
+ messages_value = [{"role": "user", "content": "Say this is a test"}]
+
+ response = await async_openai_client.chat.completions.create(
+ messages=messages_value, model=llm_model_value, n=2, stream=False
+ )
+
+ spans = span_exporter.get_finished_spans()
+ assert_completion_attributes(spans[0], llm_model_value, response)
+
+ logs = log_exporter.get_finished_logs()
+ assert len(logs) == 3 # 1 user message + 2 choice messages
+
+ user_message = {"content": messages_value[0]["content"]}
+ assert_message_in_logs(
+ logs[0], "gen_ai.user.message", user_message, spans[0]
+ )
+
+ choice_event_0 = {
+ "index": 0,
+ "finish_reason": "stop",
+ "message": {
+ "role": "assistant",
+ "content": response.choices[0].message.content,
+ },
+ }
+ assert_message_in_logs(logs[1], "gen_ai.choice", choice_event_0, spans[0])
+
+ choice_event_1 = {
+ "index": 1,
+ "finish_reason": "stop",
+ "message": {
+ "role": "assistant",
+ "content": response.choices[1].message.content,
+ },
+ }
+ assert_message_in_logs(logs[2], "gen_ai.choice", choice_event_1, spans[0])
+
+
+@pytest.mark.vcr()
+@pytest.mark.asyncio()
+async def test_async_chat_completion_tool_calls_with_content(
+ span_exporter, log_exporter, async_openai_client, instrument_with_content
+):
+ await chat_completion_tool_call(
+ span_exporter, log_exporter, async_openai_client, True
+ )
+
+
+@pytest.mark.vcr()
+@pytest.mark.asyncio()
+async def test_async_chat_completion_tool_calls_no_content(
+ span_exporter, log_exporter, async_openai_client, instrument_no_content
+):
+ await chat_completion_tool_call(
+ span_exporter, log_exporter, async_openai_client, False
+ )
+
+
+async def chat_completion_tool_call(
+ span_exporter, log_exporter, async_openai_client, expect_content
+):
+ llm_model_value = "gpt-4o-mini"
+ messages_value = [
+ {"role": "system", "content": "You're a helpful assistant."},
+ {
+ "role": "user",
+ "content": "What's the weather in Seattle and San Francisco today?",
+ },
+ ]
+
+ response_0 = await async_openai_client.chat.completions.create(
+ messages=messages_value,
+ model=llm_model_value,
+ tool_choice="auto",
+ tools=[get_current_weather_tool_definition()],
+ )
+
+ # sanity check
+ assert "tool_calls" in response_0.choices[0].finish_reason
+
+ # final request
+ messages_value.append(
+ {
+ "role": "assistant",
+ "tool_calls": response_0.choices[0].message.to_dict()[
+ "tool_calls"
+ ],
+ }
+ )
+
+ tool_call_result_0 = {
+ "role": "tool",
+ "content": "50 degrees and raining",
+ "tool_call_id": response_0.choices[0].message.tool_calls[0].id,
+ }
+ tool_call_result_1 = {
+ "role": "tool",
+ "content": "70 degrees and sunny",
+ "tool_call_id": response_0.choices[0].message.tool_calls[1].id,
+ }
+
+ messages_value.append(tool_call_result_0)
+ messages_value.append(tool_call_result_1)
+
+ response_1 = await async_openai_client.chat.completions.create(
+ messages=messages_value, model=llm_model_value
+ )
+
+ # sanity check
+ assert "stop" in response_1.choices[0].finish_reason
+
+ # validate both calls
+ spans = span_exporter.get_finished_spans()
+ assert len(spans) == 2
+ assert_completion_attributes(spans[0], llm_model_value, response_0)
+ assert_completion_attributes(spans[1], llm_model_value, response_1)
+
+ logs = log_exporter.get_finished_logs()
+ assert len(logs) == 9 # 3 logs for first completion, 6 for second
+
+ # call one
+ system_message = (
+ {"content": messages_value[0]["content"]} if expect_content else None
+ )
+ assert_message_in_logs(
+ logs[0], "gen_ai.system.message", system_message, spans[0]
+ )
+
+ user_message = (
+ {"content": messages_value[1]["content"]} if expect_content else None
+ )
+ assert_message_in_logs(
+ logs[1], "gen_ai.user.message", user_message, spans[0]
+ )
+
+ function_call_0 = {"name": "get_current_weather"}
+ function_call_1 = {"name": "get_current_weather"}
+ if expect_content:
+ function_call_0["arguments"] = (
+ response_0.choices[0]
+ .message.tool_calls[0]
+ .function.arguments.replace("\n", "")
+ )
+ function_call_1["arguments"] = (
+ response_0.choices[0]
+ .message.tool_calls[1]
+ .function.arguments.replace("\n", "")
+ )
+
+ choice_event = {
+ "index": 0,
+ "finish_reason": "tool_calls",
+ "message": {
+ "role": "assistant",
+ "tool_calls": [
+ {
+ "id": response_0.choices[0].message.tool_calls[0].id,
+ "type": "function",
+ "function": function_call_0,
+ },
+ {
+ "id": response_0.choices[0].message.tool_calls[1].id,
+ "type": "function",
+ "function": function_call_1,
+ },
+ ],
+ },
+ }
+ assert_message_in_logs(logs[2], "gen_ai.choice", choice_event, spans[0])
+
+ # call two
+ system_message = (
+ {"content": messages_value[0]["content"]} if expect_content else None
+ )
+ assert_message_in_logs(
+ logs[3], "gen_ai.system.message", system_message, spans[1]
+ )
+
+ user_message = (
+ {"content": messages_value[1]["content"]} if expect_content else None
+ )
+ assert_message_in_logs(
+ logs[4], "gen_ai.user.message", user_message, spans[1]
+ )
+
+ assistant_tool_call = {"tool_calls": messages_value[2]["tool_calls"]}
+ if not expect_content:
+ assistant_tool_call["tool_calls"][0]["function"]["arguments"] = None
+ assistant_tool_call["tool_calls"][1]["function"]["arguments"] = None
+
+ assert_message_in_logs(
+ logs[5], "gen_ai.assistant.message", assistant_tool_call, spans[1]
+ )
+
+ tool_message_0 = {
+ "id": tool_call_result_0["tool_call_id"],
+ "content": tool_call_result_0["content"] if expect_content else None,
+ }
+
+ assert_message_in_logs(
+ logs[6], "gen_ai.tool.message", tool_message_0, spans[1]
+ )
+
+ tool_message_1 = {
+ "id": tool_call_result_1["tool_call_id"],
+ "content": tool_call_result_1["content"] if expect_content else None,
+ }
+
+ assert_message_in_logs(
+ logs[7], "gen_ai.tool.message", tool_message_1, spans[1]
+ )
+
+ message = {
+ "role": "assistant",
+ "content": response_1.choices[0].message.content
+ if expect_content
+ else None,
+ }
+ choice = {
+ "index": 0,
+ "finish_reason": "stop",
+ "message": message,
+ }
+ assert_message_in_logs(logs[8], "gen_ai.choice", choice, spans[1])
+
+
+@pytest.mark.vcr()
+@pytest.mark.asyncio()
+async def test_async_chat_completion_streaming(
+ span_exporter, log_exporter, async_openai_client, instrument_with_content
+):
+ 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 = await async_openai_client.chat.completions.create(**kwargs)
+ async 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 = span_exporter.get_finished_spans()
+ assert_all_attributes(
+ spans[0],
+ llm_model_value,
+ response_stream_id,
+ response_stream_model,
+ response_stream_usage.prompt_tokens,
+ response_stream_usage.completion_tokens,
+ )
+
+ logs = log_exporter.get_finished_logs()
+ assert len(logs) == 2
+
+ user_message = {"content": "Say this is a test"}
+ assert_message_in_logs(
+ logs[0], "gen_ai.user.message", user_message, spans[0]
+ )
+
+ choice_event = {
+ "index": 0,
+ "finish_reason": "stop",
+ "message": {"role": "assistant", "content": response_stream_result},
+ }
+ assert_message_in_logs(logs[1], "gen_ai.choice", choice_event, spans[0])
+
+
+@pytest.mark.vcr()
+@pytest.mark.asyncio()
+async def test_async_chat_completion_streaming_not_complete(
+ span_exporter, log_exporter, async_openai_client, instrument_with_content
+):
+ 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,
+ }
+
+ response_stream_model = None
+ response_stream_id = None
+ response_stream_result = ""
+ response = await async_openai_client.chat.completions.create(**kwargs)
+ idx = 0
+ async for chunk in response:
+ if chunk.choices:
+ response_stream_result += chunk.choices[0].delta.content or ""
+ if idx == 1:
+ # fake a stop
+ break
+
+ if chunk.model:
+ response_stream_model = chunk.model
+ if chunk.id:
+ response_stream_id = chunk.id
+ idx += 1
+
+ response.close()
+ spans = span_exporter.get_finished_spans()
+ assert_all_attributes(
+ spans[0], llm_model_value, response_stream_id, response_stream_model
+ )
+
+ logs = log_exporter.get_finished_logs()
+ assert len(logs) == 2
+
+ user_message = {"content": "Say this is a test"}
+ assert_message_in_logs(
+ logs[0], "gen_ai.user.message", user_message, spans[0]
+ )
+
+ choice_event = {
+ "index": 0,
+ "finish_reason": "error",
+ "message": {"role": "assistant", "content": response_stream_result},
+ }
+ assert_message_in_logs(logs[1], "gen_ai.choice", choice_event, spans[0])
+
+
+@pytest.mark.vcr()
+@pytest.mark.asyncio()
+async def test_async_chat_completion_multiple_choices_streaming(
+ span_exporter, log_exporter, async_openai_client, instrument_with_content
+):
+ llm_model_value = "gpt-4o-mini"
+ messages_value = [
+ {"role": "system", "content": "You're a helpful assistant."},
+ {
+ "role": "user",
+ "content": "What's the weather in Seattle and San Francisco today?",
+ },
+ ]
+
+ response_0 = await async_openai_client.chat.completions.create(
+ messages=messages_value,
+ model=llm_model_value,
+ n=2,
+ stream=True,
+ stream_options={"include_usage": True},
+ )
+
+ # two strings for each choice
+ response_stream_result = ["", ""]
+ finish_reasons = ["", ""]
+ async for chunk in response_0:
+ if chunk.choices:
+ for choice in chunk.choices:
+ response_stream_result[choice.index] += (
+ choice.delta.content or ""
+ )
+ if choice.finish_reason:
+ finish_reasons[choice.index] = choice.finish_reason
+
+ # get the last chunk
+ if getattr(chunk, "usage", None):
+ response_stream_usage = chunk.usage
+ response_stream_model = chunk.model
+ response_stream_id = chunk.id
+
+ # sanity check
+ assert "stop" == finish_reasons[0]
+
+ spans = span_exporter.get_finished_spans()
+ assert_all_attributes(
+ spans[0],
+ llm_model_value,
+ response_stream_id,
+ response_stream_model,
+ response_stream_usage.prompt_tokens,
+ response_stream_usage.completion_tokens,
+ )
+
+ logs = log_exporter.get_finished_logs()
+ assert len(logs) == 4
+
+ system_message = {"content": messages_value[0]["content"]}
+ assert_message_in_logs(
+ logs[0], "gen_ai.system.message", system_message, spans[0]
+ )
+
+ user_message = {
+ "content": "What's the weather in Seattle and San Francisco today?"
+ }
+ assert_message_in_logs(
+ logs[1], "gen_ai.user.message", user_message, spans[0]
+ )
+
+ choice_event_0 = {
+ "index": 0,
+ "finish_reason": "stop",
+ "message": {
+ "role": "assistant",
+ "content": "".join(response_stream_result[0]),
+ },
+ }
+ assert_message_in_logs(logs[2], "gen_ai.choice", choice_event_0, spans[0])
+
+ choice_event_1 = {
+ "index": 1,
+ "finish_reason": "stop",
+ "message": {
+ "role": "assistant",
+ "content": "".join(response_stream_result[1]),
+ },
+ }
+ assert_message_in_logs(logs[3], "gen_ai.choice", choice_event_1, spans[0])
+
+
+@pytest.mark.vcr()
+@pytest.mark.asyncio()
+async def test_async_chat_completion_multiple_tools_streaming_with_content(
+ span_exporter, log_exporter, async_openai_client, instrument_with_content
+):
+ await async_chat_completion_multiple_tools_streaming(
+ span_exporter, log_exporter, async_openai_client, True
+ )
+
+
+@pytest.mark.vcr()
+@pytest.mark.asyncio()
+async def test_async_chat_completion_multiple_tools_streaming_no_content(
+ span_exporter, log_exporter, async_openai_client, instrument_no_content
+):
+ await async_chat_completion_multiple_tools_streaming(
+ span_exporter, log_exporter, async_openai_client, False
+ )
+
+
+async def async_chat_completion_multiple_tools_streaming(
+ span_exporter, log_exporter, async_openai_client, expect_content
+):
+ llm_model_value = "gpt-4o-mini"
+ messages_value = [
+ {"role": "system", "content": "You're a helpful assistant."},
+ {
+ "role": "user",
+ "content": "What's the weather in Seattle and San Francisco today?",
+ },
+ ]
+
+ response = await async_openai_client.chat.completions.create(
+ messages=messages_value,
+ model=llm_model_value,
+ tool_choice="auto",
+ tools=[get_current_weather_tool_definition()],
+ stream=True,
+ stream_options={"include_usage": True},
+ )
+
+ finish_reason = None
+ # two tools
+ tool_names = ["", ""]
+ tool_call_ids = ["", ""]
+ tool_args = ["", ""]
+ async for chunk in response:
+ if chunk.choices:
+ if chunk.choices[0].finish_reason:
+ finish_reason = chunk.choices[0].finish_reason
+ for tool_call in chunk.choices[0].delta.tool_calls or []:
+ t_idx = tool_call.index
+ if tool_call.id:
+ tool_call_ids[t_idx] = tool_call.id
+ if tool_call.function:
+ if tool_call.function.arguments:
+ tool_args[t_idx] += tool_call.function.arguments
+ if tool_call.function.name:
+ tool_names[t_idx] = tool_call.function.name
+
+ # get the last chunk
+ if getattr(chunk, "usage", None):
+ response_stream_usage = chunk.usage
+ response_stream_model = chunk.model
+ response_stream_id = chunk.id
+
+ # sanity check
+ assert "tool_calls" == finish_reason
+
+ spans = span_exporter.get_finished_spans()
+ assert_all_attributes(
+ spans[0],
+ llm_model_value,
+ response_stream_id,
+ response_stream_model,
+ response_stream_usage.prompt_tokens,
+ response_stream_usage.completion_tokens,
+ )
+
+ logs = log_exporter.get_finished_logs()
+ assert len(logs) == 3
+
+ system_message = (
+ {"content": messages_value[0]["content"]} if expect_content else None
+ )
+ assert_message_in_logs(
+ logs[0], "gen_ai.system.message", system_message, spans[0]
+ )
+
+ user_message = (
+ {"content": "What's the weather in Seattle and San Francisco today?"}
+ if expect_content
+ else None
+ )
+ assert_message_in_logs(
+ logs[1], "gen_ai.user.message", user_message, spans[0]
+ )
+
+ choice_event = {
+ "index": 0,
+ "finish_reason": "tool_calls",
+ "message": {
+ "role": "assistant",
+ "tool_calls": [
+ {
+ "id": tool_call_ids[0],
+ "type": "function",
+ "function": {
+ "name": tool_names[0],
+ "arguments": (
+ tool_args[0].replace("\n", "")
+ if expect_content
+ else None
+ ),
+ },
+ },
+ {
+ "id": tool_call_ids[1],
+ "type": "function",
+ "function": {
+ "name": tool_names[1],
+ "arguments": (
+ tool_args[1].replace("\n", "")
+ if expect_content
+ else None
+ ),
+ },
+ },
+ ],
+ },
+ }
+ assert_message_in_logs(logs[2], "gen_ai.choice", choice_event, spans[0])
+
+
+def assert_message_in_logs(log, event_name, expected_content, parent_span):
+ assert log.log_record.attributes[EventAttributes.EVENT_NAME] == event_name
+ assert (
+ log.log_record.attributes[GenAIAttributes.GEN_AI_SYSTEM]
+ == GenAIAttributes.GenAiSystemValues.OPENAI.value
+ )
+
+ if not expected_content:
+ assert not log.log_record.body
+ else:
+ assert log.log_record.body
+ assert dict(log.log_record.body) == remove_none_values(
+ expected_content
+ )
+ assert_log_parent(log, parent_span)
+
+
+def remove_none_values(body):
+ result = {}
+ for key, value in body.items():
+ if value is None:
+ continue
+ if isinstance(value, dict):
+ result[key] = remove_none_values(value)
+ elif isinstance(value, list):
+ result[key] = [remove_none_values(i) for i in value]
+ else:
+ result[key] = value
+ return result
+
+
+def assert_completion_attributes(
+ span: ReadableSpan,
+ request_model: str,
+ response: ChatCompletion,
+ operation_name: str = "chat",
+ server_address: str = "api.openai.com",
+):
+ return assert_all_attributes(
+ span,
+ request_model,
+ response.id,
+ response.model,
+ response.usage.prompt_tokens,
+ response.usage.completion_tokens,
+ operation_name,
+ server_address,
+ )
+
+
+def assert_all_attributes(
+ span: ReadableSpan,
+ request_model: str,
+ response_id: str = None,
+ response_model: str = None,
+ input_tokens: Optional[int] = None,
+ output_tokens: Optional[int] = None,
+ operation_name: str = "chat",
+ server_address: str = "api.openai.com",
+):
+ assert span.name == f"{operation_name} {request_model}"
+ assert (
+ operation_name
+ == span.attributes[GenAIAttributes.GEN_AI_OPERATION_NAME]
+ )
+ assert (
+ GenAIAttributes.GenAiSystemValues.OPENAI.value
+ == span.attributes[GenAIAttributes.GEN_AI_SYSTEM]
+ )
+ assert (
+ request_model == span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL]
+ )
+ if response_model:
+ assert (
+ response_model
+ == span.attributes[GenAIAttributes.GEN_AI_RESPONSE_MODEL]
+ )
+ else:
+ assert GenAIAttributes.GEN_AI_RESPONSE_MODEL not in span.attributes
+
+ if response_id:
+ assert (
+ response_id == span.attributes[GenAIAttributes.GEN_AI_RESPONSE_ID]
+ )
+ else:
+ assert GenAIAttributes.GEN_AI_RESPONSE_ID not in span.attributes
+
+ if input_tokens:
+ assert (
+ input_tokens
+ == span.attributes[GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS]
+ )
+ else:
+ assert GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS not in span.attributes
+
+ if output_tokens:
+ assert (
+ output_tokens
+ == span.attributes[GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS]
+ )
+ else:
+ assert (
+ GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS not in span.attributes
+ )
+
+ assert server_address == span.attributes[ServerAttributes.SERVER_ADDRESS]
+
+
+def assert_log_parent(log, span):
+ assert log.log_record.trace_id == span.get_span_context().trace_id
+ assert log.log_record.span_id == span.get_span_context().span_id
+ assert log.log_record.trace_flags == span.get_span_context().trace_flags
+
+
+def get_current_weather_tool_definition():
+ return {
+ "type": "function",
+ "function": {
+ "name": "get_current_weather",
+ "description": "Get the current weather in a given location",
+ "parameters": {
+ "type": "object",
+ "properties": {
+ "location": {
+ "type": "string",
+ "description": "The city and state, e.g. Boston, MA",
+ },
+ },
+ "required": ["location"],
+ "additionalProperties": False,
+ },
+ },
+ }
diff --git a/instrumentation/opentelemetry-instrumentation-aiopg/tests/test_aiopg_integration.py b/instrumentation/opentelemetry-instrumentation-aiopg/tests/test_aiopg_integration.py
index c497ae4564..f32ef3514b 100644
--- a/instrumentation/opentelemetry-instrumentation-aiopg/tests/test_aiopg_integration.py
+++ b/instrumentation/opentelemetry-instrumentation-aiopg/tests/test_aiopg_integration.py
@@ -67,7 +67,7 @@ def test_instrumentor_connect(self):
span = spans_list[0]
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.aiopg
)
@@ -96,7 +96,7 @@ async def _ctx_manager_connect():
span = spans_list[0]
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.aiopg
)
@@ -117,7 +117,7 @@ def test_instrumentor_create_pool(self):
span = spans_list[0]
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.aiopg
)
@@ -148,7 +148,7 @@ async def _ctx_manager_pool():
span = spans_list[0]
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.aiopg
)
diff --git a/instrumentation/opentelemetry-instrumentation-cassandra/tests/test_cassandra_integration.py b/instrumentation/opentelemetry-instrumentation-cassandra/tests/test_cassandra_integration.py
index ed488ab07f..9a36bb9069 100644
--- a/instrumentation/opentelemetry-instrumentation-cassandra/tests/test_cassandra_integration.py
+++ b/instrumentation/opentelemetry-instrumentation-cassandra/tests/test_cassandra_integration.py
@@ -78,7 +78,7 @@ def test_instrumentor(
span = spans_list[0]
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.cassandra
)
self.assertEqual(span.name, "Cassandra")
diff --git a/instrumentation/opentelemetry-instrumentation-confluent-kafka/README.rst b/instrumentation/opentelemetry-instrumentation-confluent-kafka/README.rst
index 163c2a4393..1ce6dcbd26 100644
--- a/instrumentation/opentelemetry-instrumentation-confluent-kafka/README.rst
+++ b/instrumentation/opentelemetry-instrumentation-confluent-kafka/README.rst
@@ -19,5 +19,5 @@ Installation
References
----------
-* `OpenTelemetry confluent-kafka/ Tracing `_
+* `OpenTelemetry confluent-kafka/ Tracing `_
* `OpenTelemetry Project `_
diff --git a/instrumentation/opentelemetry-instrumentation-dbapi/src/opentelemetry/instrumentation/dbapi/__init__.py b/instrumentation/opentelemetry-instrumentation-dbapi/src/opentelemetry/instrumentation/dbapi/__init__.py
index fc3911f744..d8db967f47 100644
--- a/instrumentation/opentelemetry-instrumentation-dbapi/src/opentelemetry/instrumentation/dbapi/__init__.py
+++ b/instrumentation/opentelemetry-instrumentation-dbapi/src/opentelemetry/instrumentation/dbapi/__init__.py
@@ -190,6 +190,7 @@ def instrument_connection(
capture_parameters: bool = False,
enable_commenter: bool = False,
commenter_options: dict = None,
+ connect_module: typing.Callable[..., typing.Any] = None,
):
"""Enable instrumentation in a database connection.
@@ -204,6 +205,7 @@ def instrument_connection(
capture_parameters: Configure if db.statement.parameters should be captured.
enable_commenter: Flag to enable/disable sqlcommenter.
commenter_options: Configurations for tags to be appended at the sql query.
+ connect_module: Module name where connect method is available.
Returns:
An instrumented connection.
@@ -221,6 +223,7 @@ def instrument_connection(
capture_parameters=capture_parameters,
enable_commenter=enable_commenter,
commenter_options=commenter_options,
+ connect_module=connect_module,
)
db_integration.get_connection_attributes(connection)
return get_traced_connection_proxy(connection, db_integration)
@@ -492,49 +495,54 @@ def traced_execution(
with self._db_api_integration._tracer.start_as_current_span(
name, kind=SpanKind.CLIENT
) as span:
- self._populate_span(span, cursor, *args)
- if args and self._commenter_enabled:
- try:
- args_list = list(args)
-
- # lazy capture of mysql-connector client version using cursor
- if (
- self._db_api_integration.database_system == "mysql"
- and self._db_api_integration.connect_module.__name__
- == "mysql.connector"
- and not self._db_api_integration.commenter_data[
- "mysql_client_version"
- ]
- ):
- self._db_api_integration.commenter_data[
- "mysql_client_version"
- ] = cursor._cnx._cmysql.get_client_info()
-
- commenter_data = dict(
- self._db_api_integration.commenter_data
- )
- if self._commenter_options.get(
- "opentelemetry_values", True
- ):
- commenter_data.update(**_get_opentelemetry_values())
-
- # Filter down to just the requested attributes.
- commenter_data = {
- k: v
- for k, v in commenter_data.items()
- if self._commenter_options.get(k, True)
- }
- statement = _add_sql_comment(
- args_list[0], **commenter_data
- )
-
- args_list[0] = statement
- args = tuple(args_list)
-
- except Exception as exc: # pylint: disable=broad-except
- _logger.exception(
- "Exception while generating sql comment: %s", exc
- )
+ if span.is_recording():
+ if args and self._commenter_enabled:
+ try:
+ args_list = list(args)
+
+ # lazy capture of mysql-connector client version using cursor
+ if (
+ self._db_api_integration.database_system == "mysql"
+ and self._db_api_integration.connect_module.__name__
+ == "mysql.connector"
+ and not self._db_api_integration.commenter_data[
+ "mysql_client_version"
+ ]
+ ):
+ self._db_api_integration.commenter_data[
+ "mysql_client_version"
+ ] = cursor._cnx._cmysql.get_client_info()
+
+ commenter_data = dict(
+ self._db_api_integration.commenter_data
+ )
+ if self._commenter_options.get(
+ "opentelemetry_values", True
+ ):
+ commenter_data.update(
+ **_get_opentelemetry_values()
+ )
+
+ # Filter down to just the requested attributes.
+ commenter_data = {
+ k: v
+ for k, v in commenter_data.items()
+ if self._commenter_options.get(k, True)
+ }
+ statement = _add_sql_comment(
+ args_list[0], **commenter_data
+ )
+
+ args_list[0] = statement
+ args = tuple(args_list)
+
+ except Exception as exc: # pylint: disable=broad-except
+ _logger.exception(
+ "Exception while generating sql comment: %s", exc
+ )
+
+ self._populate_span(span, cursor, *args)
+
return query_method(*args, **kwargs)
diff --git a/instrumentation/opentelemetry-instrumentation-dbapi/tests/test_dbapi_integration.py b/instrumentation/opentelemetry-instrumentation-dbapi/tests/test_dbapi_integration.py
index e29a8ad380..2ffa2f3d5b 100644
--- a/instrumentation/opentelemetry-instrumentation-dbapi/tests/test_dbapi_integration.py
+++ b/instrumentation/opentelemetry-instrumentation-dbapi/tests/test_dbapi_integration.py
@@ -14,6 +14,7 @@
import logging
+import re
from unittest import mock
from opentelemetry import context
@@ -306,6 +307,44 @@ def __getattr__(self, name):
r"Select 1 /\*dbapi_level='1.0',dbapi_threadsafety='unknown',driver_paramstyle='unknown',libpq_version=123,traceparent='\d{1,2}-[a-zA-Z0-9_]{32}-[a-zA-Z0-9_]{16}-\d{1,2}'\*/;",
)
+ def test_executemany_comment_matches_db_statement_attribute(self):
+ connect_module = mock.MagicMock()
+ connect_module.__version__ = mock.MagicMock()
+ connect_module.__libpq_version__ = 123
+ connect_module.apilevel = 123
+ connect_module.threadsafety = 123
+ connect_module.paramstyle = "test"
+
+ db_integration = dbapi.DatabaseApiIntegration(
+ "testname",
+ "postgresql",
+ enable_commenter=True,
+ commenter_options={"db_driver": False, "dbapi_level": False},
+ connect_module=connect_module,
+ )
+ mock_connection = db_integration.wrapped_connection(
+ mock_connect, {}, {}
+ )
+ cursor = mock_connection.cursor()
+ cursor.executemany("Select 1;")
+ self.assertRegex(
+ cursor.query,
+ r"Select 1 /\*dbapi_threadsafety=123,driver_paramstyle='test',libpq_version=123,traceparent='\d{1,2}-[a-zA-Z0-9_]{32}-[a-zA-Z0-9_]{16}-\d{1,2}'\*/;",
+ )
+ spans_list = self.memory_exporter.get_finished_spans()
+ self.assertEqual(len(spans_list), 1)
+ span = spans_list[0]
+ self.assertRegex(
+ span.attributes[SpanAttributes.DB_STATEMENT],
+ r"Select 1 /\*dbapi_threadsafety=123,driver_paramstyle='test',libpq_version=123,traceparent='\d{1,2}-[a-zA-Z0-9_]{32}-[a-zA-Z0-9_]{16}-\d{1,2}'\*/",
+ )
+
+ cursor_span_id = re.search(r"[a-zA-Z0-9_]{16}", cursor.query).group()
+ db_statement_span_id = re.search(
+ r"[a-zA-Z0-9_]{16}", span.attributes[SpanAttributes.DB_STATEMENT]
+ ).group()
+ self.assertEqual(cursor_span_id, db_statement_span_id)
+
def test_compatible_build_version_psycopg_psycopg2_libpq(self):
connect_module = mock.MagicMock()
connect_module.__name__ = "test"
@@ -553,6 +592,43 @@ def test_instrument_connection(self):
connection2 = dbapi.instrument_connection(self.tracer, connection, "-")
self.assertIs(connection2.__wrapped__, connection)
+ @mock.patch("opentelemetry.instrumentation.dbapi.DatabaseApiIntegration")
+ def test_instrument_connection_kwargs_defaults(self, mock_dbapiint):
+ dbapi.instrument_connection(self.tracer, mock.Mock(), "foo")
+ kwargs = mock_dbapiint.call_args[1]
+ self.assertEqual(kwargs["connection_attributes"], None)
+ self.assertEqual(kwargs["version"], "")
+ self.assertEqual(kwargs["tracer_provider"], None)
+ self.assertEqual(kwargs["capture_parameters"], False)
+ self.assertEqual(kwargs["enable_commenter"], False)
+ self.assertEqual(kwargs["commenter_options"], None)
+ self.assertEqual(kwargs["connect_module"], None)
+
+ @mock.patch("opentelemetry.instrumentation.dbapi.DatabaseApiIntegration")
+ def test_instrument_connection_kwargs_provided(self, mock_dbapiint):
+ mock_tracer_provider = mock.MagicMock()
+ mock_connect_module = mock.MagicMock()
+ dbapi.instrument_connection(
+ self.tracer,
+ mock.Mock(),
+ "foo",
+ connection_attributes={"foo": "bar"},
+ version="test",
+ tracer_provider=mock_tracer_provider,
+ capture_parameters=True,
+ enable_commenter=True,
+ commenter_options={"foo": "bar"},
+ connect_module=mock_connect_module,
+ )
+ kwargs = mock_dbapiint.call_args[1]
+ self.assertEqual(kwargs["connection_attributes"], {"foo": "bar"})
+ self.assertEqual(kwargs["version"], "test")
+ self.assertIs(kwargs["tracer_provider"], mock_tracer_provider)
+ self.assertEqual(kwargs["capture_parameters"], True)
+ self.assertEqual(kwargs["enable_commenter"], True)
+ self.assertEqual(kwargs["commenter_options"], {"foo": "bar"})
+ self.assertIs(kwargs["connect_module"], mock_connect_module)
+
def test_uninstrument_connection(self):
connection = mock.Mock()
# Set connection.database to avoid a failure because mock can't
diff --git a/instrumentation/opentelemetry-instrumentation-elasticsearch/tests/test_elasticsearch.py b/instrumentation/opentelemetry-instrumentation-elasticsearch/tests/test_elasticsearch.py
index b7e24d87c9..8a707c8c2a 100644
--- a/instrumentation/opentelemetry-instrumentation-elasticsearch/tests/test_elasticsearch.py
+++ b/instrumentation/opentelemetry-instrumentation-elasticsearch/tests/test_elasticsearch.py
@@ -114,7 +114,7 @@ def test_instrumentor(self, request_mock):
span = spans_list[0]
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.elasticsearch
)
@@ -608,7 +608,7 @@ def test_bulk(self, request_mock):
span = spans_list[0]
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.elasticsearch
)
diff --git a/instrumentation/opentelemetry-instrumentation-grpc/tests/test_aio_client_interceptor.py b/instrumentation/opentelemetry-instrumentation-grpc/tests/test_aio_client_interceptor.py
index 7ae1649149..4cd19da4af 100644
--- a/instrumentation/opentelemetry-instrumentation-grpc/tests/test_aio_client_interceptor.py
+++ b/instrumentation/opentelemetry-instrumentation-grpc/tests/test_aio_client_interceptor.py
@@ -114,7 +114,7 @@ async def test_unary_unary(self):
self.assertIs(span.kind, trace.SpanKind.CLIENT)
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.grpc
)
@@ -142,7 +142,7 @@ async def test_unary_stream(self):
self.assertIs(span.kind, trace.SpanKind.CLIENT)
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.grpc
)
@@ -170,7 +170,7 @@ async def test_stream_unary(self):
self.assertIs(span.kind, trace.SpanKind.CLIENT)
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.grpc
)
@@ -200,7 +200,7 @@ async def test_stream_stream(self):
self.assertIs(span.kind, trace.SpanKind.CLIENT)
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.grpc
)
diff --git a/instrumentation/opentelemetry-instrumentation-grpc/tests/test_aio_server_interceptor.py b/instrumentation/opentelemetry-instrumentation-grpc/tests/test_aio_server_interceptor.py
index 050f6f8d13..ee917ca26c 100644
--- a/instrumentation/opentelemetry-instrumentation-grpc/tests/test_aio_server_interceptor.py
+++ b/instrumentation/opentelemetry-instrumentation-grpc/tests/test_aio_server_interceptor.py
@@ -105,7 +105,7 @@ async def request(channel):
self.assertIs(span.kind, trace.SpanKind.SERVER)
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.grpc
)
@@ -164,7 +164,7 @@ async def request(channel):
self.assertIs(span.kind, trace.SpanKind.SERVER)
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.grpc
)
@@ -217,7 +217,7 @@ async def request(channel):
self.assertIs(parent_span.kind, trace.SpanKind.SERVER)
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
parent_span, opentelemetry.instrumentation.grpc
)
@@ -263,7 +263,7 @@ async def request(channel):
self.assertIs(span.kind, trace.SpanKind.SERVER)
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.grpc
)
@@ -318,7 +318,7 @@ async def request(channel):
self.assertIs(parent_span.kind, trace.SpanKind.SERVER)
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
parent_span, opentelemetry.instrumentation.grpc
)
@@ -514,7 +514,7 @@ async def request(channel):
self.assertIs(span.kind, trace.SpanKind.SERVER)
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.grpc
)
@@ -579,7 +579,7 @@ async def request(channel):
self.assertIs(span.kind, trace.SpanKind.SERVER)
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.grpc
)
diff --git a/instrumentation/opentelemetry-instrumentation-grpc/tests/test_client_interceptor.py b/instrumentation/opentelemetry-instrumentation-grpc/tests/test_client_interceptor.py
index 38759352b3..9fb922a615 100644
--- a/instrumentation/opentelemetry-instrumentation-grpc/tests/test_client_interceptor.py
+++ b/instrumentation/opentelemetry-instrumentation-grpc/tests/test_client_interceptor.py
@@ -111,7 +111,7 @@ def test_unary_unary_future(self):
self.assertIs(span.kind, trace.SpanKind.CLIENT)
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.grpc
)
@@ -125,7 +125,7 @@ def test_unary_unary(self):
self.assertIs(span.kind, trace.SpanKind.CLIENT)
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.grpc
)
@@ -151,7 +151,7 @@ def test_unary_stream(self):
self.assertIs(span.kind, trace.SpanKind.CLIENT)
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.grpc
)
@@ -177,7 +177,7 @@ def test_stream_unary(self):
self.assertIs(span.kind, trace.SpanKind.CLIENT)
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.grpc
)
@@ -205,7 +205,7 @@ def test_stream_stream(self):
self.assertIs(span.kind, trace.SpanKind.CLIENT)
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.grpc
)
diff --git a/instrumentation/opentelemetry-instrumentation-grpc/tests/test_client_interceptor_filter.py b/instrumentation/opentelemetry-instrumentation-grpc/tests/test_client_interceptor_filter.py
index b6ae975dff..81e8d708f2 100644
--- a/instrumentation/opentelemetry-instrumentation-grpc/tests/test_client_interceptor_filter.py
+++ b/instrumentation/opentelemetry-instrumentation-grpc/tests/test_client_interceptor_filter.py
@@ -116,7 +116,7 @@ def test_unary_unary_future(self):
self.assertIs(span.kind, trace.SpanKind.CLIENT)
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.grpc
)
@@ -130,7 +130,7 @@ def test_unary_unary(self):
self.assertIs(span.kind, trace.SpanKind.CLIENT)
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.grpc
)
@@ -260,7 +260,7 @@ def test_unary_unary_future(self):
self.assertIs(span.kind, trace.SpanKind.CLIENT)
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.grpc
)
@@ -274,7 +274,7 @@ def test_unary_unary(self):
self.assertIs(span.kind, trace.SpanKind.CLIENT)
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.grpc
)
@@ -443,7 +443,7 @@ def test_unary_unary_future(self):
self.assertIs(span.kind, trace.SpanKind.CLIENT)
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.grpc
)
@@ -457,7 +457,7 @@ def test_unary_unary(self):
self.assertIs(span.kind, trace.SpanKind.CLIENT)
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.grpc
)
@@ -483,7 +483,7 @@ def test_unary_stream(self):
self.assertIs(span.kind, trace.SpanKind.CLIENT)
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.grpc
)
@@ -509,7 +509,7 @@ def test_stream_unary(self):
self.assertIs(span.kind, trace.SpanKind.CLIENT)
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.grpc
)
@@ -537,7 +537,7 @@ def test_stream_stream(self):
self.assertIs(span.kind, trace.SpanKind.CLIENT)
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.grpc
)
diff --git a/instrumentation/opentelemetry-instrumentation-grpc/tests/test_server_interceptor.py b/instrumentation/opentelemetry-instrumentation-grpc/tests/test_server_interceptor.py
index de79269894..08aa16187a 100644
--- a/instrumentation/opentelemetry-instrumentation-grpc/tests/test_server_interceptor.py
+++ b/instrumentation/opentelemetry-instrumentation-grpc/tests/test_server_interceptor.py
@@ -120,7 +120,7 @@ def handler(request, context):
self.assertIs(span.kind, trace.SpanKind.SERVER)
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.grpc
)
@@ -188,7 +188,7 @@ def test_create_span(self):
self.assertIs(span.kind, trace.SpanKind.SERVER)
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.grpc
)
@@ -252,7 +252,7 @@ def SimpleMethod(self, request, context):
self.assertIs(parent_span.kind, trace.SpanKind.SERVER)
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
parent_span, opentelemetry.instrumentation.grpc
)
@@ -307,7 +307,7 @@ def test_create_span_streaming(self):
self.assertIs(span.kind, trace.SpanKind.SERVER)
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.grpc
)
@@ -371,7 +371,7 @@ def ServerStreamingMethod(self, request, context):
self.assertIs(parent_span.kind, trace.SpanKind.SERVER)
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
parent_span, opentelemetry.instrumentation.grpc
)
@@ -594,7 +594,7 @@ def unset_status_handler(request, context):
self.assertIs(span.kind, trace.SpanKind.SERVER)
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.grpc
)
@@ -626,7 +626,7 @@ def unset_status_handler(request, context):
self.assertIs(span.kind, trace.SpanKind.SERVER)
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.grpc
)
diff --git a/instrumentation/opentelemetry-instrumentation-grpc/tests/test_server_interceptor_filter.py b/instrumentation/opentelemetry-instrumentation-grpc/tests/test_server_interceptor_filter.py
index 95e70236cb..6a0081c4af 100644
--- a/instrumentation/opentelemetry-instrumentation-grpc/tests/test_server_interceptor_filter.py
+++ b/instrumentation/opentelemetry-instrumentation-grpc/tests/test_server_interceptor_filter.py
@@ -109,7 +109,7 @@ def handler(request, context):
self.assertIs(span.kind, trace.SpanKind.SERVER)
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.grpc
)
@@ -195,7 +195,7 @@ def test_create_span(self):
self.assertIs(span.kind, trace.SpanKind.SERVER)
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.grpc
)
diff --git a/instrumentation/opentelemetry-instrumentation-httpx/src/opentelemetry/instrumentation/httpx/__init__.py b/instrumentation/opentelemetry-instrumentation-httpx/src/opentelemetry/instrumentation/httpx/__init__.py
index d3a2cecfe6..195c784408 100644
--- a/instrumentation/opentelemetry-instrumentation-httpx/src/opentelemetry/instrumentation/httpx/__init__.py
+++ b/instrumentation/opentelemetry-instrumentation-httpx/src/opentelemetry/instrumentation/httpx/__init__.py
@@ -641,77 +641,6 @@ async def aclose(self) -> None:
await self._transport.aclose()
-class _InstrumentedClient(httpx.Client):
- _tracer_provider = None
- _request_hook = None
- _response_hook = None
-
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
-
- self._original_transport = self._transport
- self._original_mounts = self._mounts.copy()
- self._is_instrumented_by_opentelemetry = True
-
- self._transport = SyncOpenTelemetryTransport(
- self._transport,
- tracer_provider=_InstrumentedClient._tracer_provider,
- request_hook=_InstrumentedClient._request_hook,
- response_hook=_InstrumentedClient._response_hook,
- )
- self._mounts.update(
- {
- url_pattern: (
- SyncOpenTelemetryTransport(
- transport,
- tracer_provider=_InstrumentedClient._tracer_provider,
- request_hook=_InstrumentedClient._request_hook,
- response_hook=_InstrumentedClient._response_hook,
- )
- if transport is not None
- else transport
- )
- for url_pattern, transport in self._original_mounts.items()
- }
- )
-
-
-class _InstrumentedAsyncClient(httpx.AsyncClient):
- _tracer_provider = None
- _request_hook = None
- _response_hook = None
-
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
-
- self._original_transport = self._transport
- self._original_mounts = self._mounts.copy()
- self._is_instrumented_by_opentelemetry = True
-
- self._transport = AsyncOpenTelemetryTransport(
- self._transport,
- tracer_provider=_InstrumentedAsyncClient._tracer_provider,
- request_hook=_InstrumentedAsyncClient._request_hook,
- response_hook=_InstrumentedAsyncClient._response_hook,
- )
-
- self._mounts.update(
- {
- url_pattern: (
- AsyncOpenTelemetryTransport(
- transport,
- tracer_provider=_InstrumentedAsyncClient._tracer_provider,
- request_hook=_InstrumentedAsyncClient._request_hook,
- response_hook=_InstrumentedAsyncClient._response_hook,
- )
- if transport is not None
- else transport
- )
- for url_pattern, transport in self._original_mounts.items()
- }
- )
-
-
class HTTPXClientInstrumentor(BaseInstrumentor):
# pylint: disable=protected-access,attribute-defined-outside-init
"""An instrumentor for httpx Client and AsyncClient
@@ -938,8 +867,9 @@ async def _handle_async_request_wrapper( # pylint: disable=too-many-locals
return response
+ @classmethod
def instrument_client(
- self,
+ cls,
client: typing.Union[httpx.Client, httpx.AsyncClient],
tracer_provider: TracerProvider = None,
request_hook: typing.Union[
@@ -996,7 +926,7 @@ def instrument_client(
client._transport,
"handle_request",
partial(
- self._handle_request_wrapper,
+ cls._handle_request_wrapper,
tracer=tracer,
sem_conv_opt_in_mode=sem_conv_opt_in_mode,
request_hook=request_hook,
@@ -1004,24 +934,25 @@ def instrument_client(
),
)
for transport in client._mounts.values():
- wrap_function_wrapper(
- transport,
- "handle_request",
- partial(
- self._handle_request_wrapper,
- tracer=tracer,
- sem_conv_opt_in_mode=sem_conv_opt_in_mode,
- request_hook=request_hook,
- response_hook=response_hook,
- ),
- )
+ if hasattr(transport, "handle_request"):
+ wrap_function_wrapper(
+ transport,
+ "handle_request",
+ partial(
+ cls._handle_request_wrapper,
+ tracer=tracer,
+ sem_conv_opt_in_mode=sem_conv_opt_in_mode,
+ request_hook=request_hook,
+ response_hook=response_hook,
+ ),
+ )
client._is_instrumented_by_opentelemetry = True
if hasattr(client._transport, "handle_async_request"):
wrap_function_wrapper(
client._transport,
"handle_async_request",
partial(
- self._handle_async_request_wrapper,
+ cls._handle_async_request_wrapper,
tracer=tracer,
sem_conv_opt_in_mode=sem_conv_opt_in_mode,
async_request_hook=async_request_hook,
@@ -1029,17 +960,18 @@ def instrument_client(
),
)
for transport in client._mounts.values():
- wrap_function_wrapper(
- transport,
- "handle_async_request",
- partial(
- self._handle_async_request_wrapper,
- tracer=tracer,
- sem_conv_opt_in_mode=sem_conv_opt_in_mode,
- async_request_hook=async_request_hook,
- async_response_hook=async_response_hook,
- ),
- )
+ if hasattr(transport, "handle_async_request"):
+ wrap_function_wrapper(
+ transport,
+ "handle_async_request",
+ partial(
+ cls._handle_async_request_wrapper,
+ tracer=tracer,
+ sem_conv_opt_in_mode=sem_conv_opt_in_mode,
+ async_request_hook=async_request_hook,
+ async_response_hook=async_response_hook,
+ ),
+ )
client._is_instrumented_by_opentelemetry = True
@staticmethod
diff --git a/instrumentation/opentelemetry-instrumentation-httpx/tests/test_httpx_integration.py b/instrumentation/opentelemetry-instrumentation-httpx/tests/test_httpx_integration.py
index 07699700c4..148fe27893 100644
--- a/instrumentation/opentelemetry-instrumentation-httpx/tests/test_httpx_integration.py
+++ b/instrumentation/opentelemetry-instrumentation-httpx/tests/test_httpx_integration.py
@@ -216,7 +216,7 @@ def test_basic(self):
self.assertIs(span.status.status_code, trace.StatusCode.UNSET)
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.httpx
)
@@ -240,7 +240,7 @@ def test_nonstandard_http_method(self):
self.assertIs(span.status.status_code, trace.StatusCode.ERROR)
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.httpx
)
@@ -269,7 +269,7 @@ def test_nonstandard_http_method_new_semconv(self):
self.assertIs(span.status.status_code, trace.StatusCode.ERROR)
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.httpx
)
@@ -309,7 +309,7 @@ def test_basic_new_semconv(self):
self.assertIs(span.status.status_code, trace.StatusCode.UNSET)
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.httpx
)
@@ -350,7 +350,7 @@ def test_basic_both_semconv(self):
self.assertIs(span.status.status_code, trace.StatusCode.UNSET)
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.httpx
)
@@ -741,6 +741,10 @@ def create_client(
def create_proxy_transport(self, url: str):
pass
+ @abc.abstractmethod
+ def get_transport_handler(self, transport):
+ pass
+
def setUp(self):
super().setUp()
self.client = self.create_client()
@@ -763,17 +767,15 @@ def assert_proxy_mounts(self, mounts, num_mounts, transport_type=None):
self.assertEqual(len(mounts), num_mounts)
for transport in mounts:
with self.subTest(transport):
+ if transport is None:
+ continue
if transport_type:
self.assertIsInstance(
transport,
transport_type,
)
else:
- handler = getattr(transport, "handle_request", None)
- if not handler:
- handler = getattr(
- transport, "handle_async_request"
- )
+ handler = self.get_transport_handler(transport)
self.assertTrue(
isinstance(handler, ObjectProxy)
and getattr(handler, "__wrapped__")
@@ -910,13 +912,20 @@ def test_suppress_instrumentation_new_client(self):
self.assert_span(num_spans=0)
- def test_instrument_client(self):
+ def test_instrument_client_called_on_the_instance(self):
client = self.create_client()
HTTPXClientInstrumentor().instrument_client(client)
result = self.perform_request(self.URL, client=client)
self.assertEqual(result.text, "Hello!")
self.assert_span(num_spans=1)
+ def test_instrument_client_called_on_the_class(self):
+ client = self.create_client()
+ HTTPXClientInstrumentor.instrument_client(client)
+ result = self.perform_request(self.URL, client=client)
+ self.assertEqual(result.text, "Hello!")
+ self.assert_span(num_spans=1)
+
def test_instrumentation_without_client(self):
HTTPXClientInstrumentor().instrument()
results = [
@@ -976,6 +985,21 @@ def test_uninstrument_new_client(self):
self.assertEqual(result.text, "Hello!")
self.assert_span()
+ @mock.patch.dict(
+ "os.environ", {"NO_PROXY": "http://mock/status/200"}, clear=True
+ )
+ def test_instrument_with_no_proxy(self):
+ proxy_mounts = self.create_proxy_mounts()
+ HTTPXClientInstrumentor().instrument()
+ client = self.create_client(mounts=proxy_mounts)
+ result = self.perform_request(self.URL, client=client)
+ self.assert_span(num_spans=1)
+ self.assertEqual(result.text, "Hello!")
+ self.assert_proxy_mounts(
+ client._mounts.values(),
+ 3,
+ )
+
def test_instrument_proxy(self):
proxy_mounts = self.create_proxy_mounts()
HTTPXClientInstrumentor().instrument()
@@ -987,6 +1011,27 @@ def test_instrument_proxy(self):
2,
)
+ @mock.patch.dict(
+ "os.environ", {"NO_PROXY": "http://mock/status/200"}, clear=True
+ )
+ def test_instrument_client_with_no_proxy(self):
+ proxy_mounts = self.create_proxy_mounts()
+ client = self.create_client(mounts=proxy_mounts)
+ self.assert_proxy_mounts(
+ client._mounts.values(),
+ 3,
+ (httpx.HTTPTransport, httpx.AsyncHTTPTransport),
+ )
+ HTTPXClientInstrumentor.instrument_client(client)
+ result = self.perform_request(self.URL, client=client)
+ self.assertEqual(result.text, "Hello!")
+ self.assert_span(num_spans=1)
+ self.assert_proxy_mounts(
+ client._mounts.values(),
+ 3,
+ )
+ HTTPXClientInstrumentor.uninstrument_client(client)
+
def test_instrument_client_with_proxy(self):
proxy_mounts = self.create_proxy_mounts()
client = self.create_client(mounts=proxy_mounts)
@@ -1181,6 +1226,9 @@ def perform_request(
def create_proxy_transport(self, url):
return httpx.HTTPTransport(proxy=httpx.Proxy(url))
+ def get_transport_handler(self, transport):
+ return getattr(transport, "handle_request", None)
+
def test_can_instrument_subclassed_client(self):
class CustomClient(httpx.Client):
pass
@@ -1234,6 +1282,9 @@ async def _perform_request():
def create_proxy_transport(self, url):
return httpx.AsyncHTTPTransport(proxy=httpx.Proxy(url))
+ def get_transport_handler(self, transport):
+ return getattr(transport, "handle_async_request", None)
+
def test_basic_multiple(self):
# We need to create separate clients because in httpx >= 0.19,
# closing the client after "with" means the second http call fails
diff --git a/instrumentation/opentelemetry-instrumentation-mysql/tests/test_mysql_integration.py b/instrumentation/opentelemetry-instrumentation-mysql/tests/test_mysql_integration.py
index 3614febffd..79399cce7f 100644
--- a/instrumentation/opentelemetry-instrumentation-mysql/tests/test_mysql_integration.py
+++ b/instrumentation/opentelemetry-instrumentation-mysql/tests/test_mysql_integration.py
@@ -50,7 +50,7 @@ def test_instrumentor(self, mock_connect):
span = spans_list[0]
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.mysql
)
diff --git a/instrumentation/opentelemetry-instrumentation-mysqlclient/src/opentelemetry/instrumentation/mysqlclient/__init__.py b/instrumentation/opentelemetry-instrumentation-mysqlclient/src/opentelemetry/instrumentation/mysqlclient/__init__.py
index 85083cff2e..5b08b0b50d 100644
--- a/instrumentation/opentelemetry-instrumentation-mysqlclient/src/opentelemetry/instrumentation/mysqlclient/__init__.py
+++ b/instrumentation/opentelemetry-instrumentation-mysqlclient/src/opentelemetry/instrumentation/mysqlclient/__init__.py
@@ -36,6 +36,72 @@
cursor.close()
cnx.close()
+SQLCOMMENTER
+*****************************************
+You can optionally configure MySQLClient instrumentation to enable sqlcommenter which enriches
+the query with contextual information.
+
+.. code:: python
+
+ import MySQLdb
+ from opentelemetry.instrumentation.mysqlclient import MySQLClientInstrumentor
+
+
+ MySQLClientInstrumentor().instrument(enable_commenter=True, commenter_options={})
+
+ cnx = MySQLdb.connect(database="MySQL_Database")
+ cursor = cnx.cursor()
+ cursor.execute("INSERT INTO test (testField) VALUES (123)"
+ cnx.commit()
+ cursor.close()
+ cnx.close()
+
+For example,
+::
+
+ Invoking cursor.execute("INSERT INTO test (testField) VALUES (123)") will lead to sql query "INSERT INTO test (testField) VALUES (123)" but when SQLCommenter is enabled
+ the query will get appended with some configurable tags like "INSERT INTO test (testField) VALUES (123) /*tag=value*/;"
+
+SQLCommenter Configurations
+***************************
+We can configure the tags to be appended to the sqlquery log by adding configuration inside commenter_options(default:{}) keyword
+
+db_driver = True(Default) or False
+
+For example,
+::
+Enabling this flag will add MySQLdb and its version, e.g. /*MySQLdb%%3A1.2.3*/
+
+dbapi_threadsafety = True(Default) or False
+
+For example,
+::
+Enabling this flag will add threadsafety /*dbapi_threadsafety=2*/
+
+dbapi_level = True(Default) or False
+
+For example,
+::
+Enabling this flag will add dbapi_level /*dbapi_level='2.0'*/
+
+mysql_client_version = True(Default) or False
+
+For example,
+::
+Enabling this flag will add mysql_client_version /*mysql_client_version='123'*/
+
+driver_paramstyle = True(Default) or False
+
+For example,
+::
+Enabling this flag will add driver_paramstyle /*driver_paramstyle='pyformat'*/
+
+opentelemetry_values = True(Default) or False
+
+For example,
+::
+Enabling this flag will add traceparent values /*traceparent='00-03afa25236b8cd948fa853d67038ac79-405ff022e8247c46-01'*/
+
API
---
"""
@@ -59,14 +125,16 @@
class MySQLClientInstrumentor(BaseInstrumentor):
- def instrumentation_dependencies(self) -> Collection[str]:
+ def instrumentation_dependencies(self) -> Collection[str]: # pylint: disable=no-self-use
return _instruments
- def _instrument(self, **kwargs):
+ def _instrument(self, **kwargs): # pylint: disable=no-self-use
"""Integrate with the mysqlclient library.
https://github.com/PyMySQL/mysqlclient/
"""
tracer_provider = kwargs.get("tracer_provider")
+ enable_sqlcommenter = kwargs.get("enable_commenter", False)
+ commenter_options = kwargs.get("commenter_options", {})
dbapi.wrap_connect(
__name__,
@@ -76,14 +144,21 @@ def _instrument(self, **kwargs):
_CONNECTION_ATTRIBUTES,
version=__version__,
tracer_provider=tracer_provider,
+ enable_commenter=enable_sqlcommenter,
+ commenter_options=commenter_options,
)
- def _uninstrument(self, **kwargs):
+ def _uninstrument(self, **kwargs): # pylint: disable=no-self-use
""" "Disable mysqlclient instrumentation"""
dbapi.unwrap_connect(MySQLdb, "connect")
@staticmethod
- def instrument_connection(connection, tracer_provider=None):
+ def instrument_connection(
+ connection,
+ tracer_provider=None,
+ enable_commenter=None,
+ commenter_options=None,
+ ):
"""Enable instrumentation in a mysqlclient connection.
Args:
@@ -102,6 +177,9 @@ def instrument_connection(connection, tracer_provider=None):
_CONNECTION_ATTRIBUTES,
version=__version__,
tracer_provider=tracer_provider,
+ enable_commenter=enable_commenter,
+ commenter_options=commenter_options,
+ connect_module=MySQLdb,
)
@staticmethod
diff --git a/instrumentation/opentelemetry-instrumentation-mysqlclient/tests/test_mysqlclient_integration.py b/instrumentation/opentelemetry-instrumentation-mysqlclient/tests/test_mysqlclient_integration.py
index 35fdecc8e1..ae221f68f4 100644
--- a/instrumentation/opentelemetry-instrumentation-mysqlclient/tests/test_mysqlclient_integration.py
+++ b/instrumentation/opentelemetry-instrumentation-mysqlclient/tests/test_mysqlclient_integration.py
@@ -23,6 +23,7 @@
class TestMySQLClientIntegration(TestBase):
+ # pylint: disable=invalid-name
def tearDown(self):
super().tearDown()
with self.disable_logging():
@@ -43,7 +44,7 @@ def test_instrumentor(self, mock_connect):
span = spans_list[0]
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.mysqlclient
)
@@ -96,6 +97,256 @@ def test_instrument_connection(self, mock_connect):
spans_list = self.memory_exporter.get_finished_spans()
self.assertEqual(len(spans_list), 1)
+ @mock.patch("opentelemetry.instrumentation.dbapi.instrument_connection")
+ @mock.patch("MySQLdb.connect")
+ # pylint: disable=unused-argument
+ def test_instrument_connection_enable_commenter_dbapi_kwargs(
+ self,
+ mock_connect,
+ mock_instrument_connection,
+ ):
+ cnx = MySQLdb.connect(database="test")
+ cnx = MySQLClientInstrumentor().instrument_connection(
+ cnx,
+ enable_commenter=True,
+ commenter_options={"foo": True},
+ )
+ cursor = cnx.cursor()
+ cursor.execute("Select 1;")
+ kwargs = mock_instrument_connection.call_args[1]
+ self.assertEqual(kwargs["enable_commenter"], True)
+ self.assertEqual(kwargs["commenter_options"], {"foo": True})
+
+ def test_instrument_connection_with_dbapi_sqlcomment_enabled(self):
+ mock_connect_module = mock.MagicMock(
+ __name__="MySQLdb",
+ threadsafety="123",
+ apilevel="123",
+ paramstyle="test",
+ )
+ mock_connect_module._mysql.get_client_info.return_value = "foobaz"
+ mock_cursor = mock_connect_module.connect().cursor()
+ mock_connection = mock.MagicMock()
+ mock_connection.cursor.return_value = mock_cursor
+
+ with mock.patch(
+ "opentelemetry.instrumentation.mysqlclient.MySQLdb",
+ mock_connect_module,
+ ), mock.patch(
+ "opentelemetry.instrumentation.dbapi.util_version",
+ return_value="foobar",
+ ):
+ cnx_proxy = MySQLClientInstrumentor().instrument_connection(
+ mock_connection,
+ enable_commenter=True,
+ )
+ cnx_proxy.cursor().execute("Select 1;")
+
+ spans_list = self.memory_exporter.get_finished_spans()
+ span = spans_list[0]
+ span_id = format(span.get_span_context().span_id, "016x")
+ trace_id = format(span.get_span_context().trace_id, "032x")
+ self.assertEqual(
+ mock_cursor.execute.call_args[0][0],
+ f"Select 1 /*db_driver='MySQLdb%%3Afoobar',dbapi_level='123',dbapi_threadsafety='123',driver_paramstyle='test',mysql_client_version='foobaz',traceparent='00-{trace_id}-{span_id}-01'*/;",
+ )
+
+ def test_instrument_connection_with_dbapi_sqlcomment_enabled_with_options(
+ self,
+ ):
+ mock_connect_module = mock.MagicMock(
+ __name__="MySQLdb",
+ threadsafety="123",
+ apilevel="123",
+ paramstyle="test",
+ )
+ mock_connect_module._mysql.get_client_info.return_value = "foobaz"
+ mock_cursor = mock_connect_module.connect().cursor()
+ mock_connection = mock.MagicMock()
+ mock_connection.cursor.return_value = mock_cursor
+
+ with mock.patch(
+ "opentelemetry.instrumentation.mysqlclient.MySQLdb",
+ mock_connect_module,
+ ), mock.patch(
+ "opentelemetry.instrumentation.dbapi.util_version",
+ return_value="foobar",
+ ):
+ cnx_proxy = MySQLClientInstrumentor().instrument_connection(
+ mock_connection,
+ enable_commenter=True,
+ commenter_options={
+ "dbapi_level": False,
+ "dbapi_threadsafety": True,
+ "driver_paramstyle": False,
+ },
+ )
+ cnx_proxy.cursor().execute("Select 1;")
+
+ spans_list = self.memory_exporter.get_finished_spans()
+ span = spans_list[0]
+ span_id = format(span.get_span_context().span_id, "016x")
+ trace_id = format(span.get_span_context().trace_id, "032x")
+ self.assertEqual(
+ mock_cursor.execute.call_args[0][0],
+ f"Select 1 /*db_driver='MySQLdb%%3Afoobar',dbapi_threadsafety='123',mysql_client_version='foobaz',traceparent='00-{trace_id}-{span_id}-01'*/;",
+ )
+
+ def test_instrument_connection_with_dbapi_sqlcomment_not_enabled_default(
+ self,
+ ):
+ mock_connect_module = mock.MagicMock(
+ __name__="MySQLdb",
+ threadsafety="123",
+ apilevel="123",
+ paramstyle="test",
+ )
+ mock_connect_module._mysql.get_client_info.return_value = "foobaz"
+ mock_cursor = mock_connect_module.connect().cursor()
+ mock_connection = mock.MagicMock()
+ mock_connection.cursor.return_value = mock_cursor
+
+ with mock.patch(
+ "opentelemetry.instrumentation.mysqlclient.MySQLdb",
+ mock_connect_module,
+ ), mock.patch(
+ "opentelemetry.instrumentation.dbapi.util_version",
+ return_value="foobar",
+ ):
+ cnx_proxy = MySQLClientInstrumentor().instrument_connection(
+ mock_connection,
+ )
+ cnx_proxy.cursor().execute("Select 1;")
+ self.assertEqual(
+ mock_cursor.execute.call_args[0][0],
+ "Select 1;",
+ )
+
+ @mock.patch("opentelemetry.instrumentation.dbapi.wrap_connect")
+ @mock.patch("MySQLdb.connect")
+ # pylint: disable=unused-argument
+ def test_instrument_enable_commenter_dbapi_kwargs(
+ self,
+ mock_connect,
+ mock_wrap_connect,
+ ):
+ MySQLClientInstrumentor()._instrument(
+ enable_commenter=True,
+ commenter_options={"foo": True},
+ )
+ kwargs = mock_wrap_connect.call_args[1]
+ self.assertEqual(kwargs["enable_commenter"], True)
+ self.assertEqual(kwargs["commenter_options"], {"foo": True})
+
+ def test_instrument_with_dbapi_sqlcomment_enabled(
+ self,
+ ):
+ mock_connect_module = mock.MagicMock(
+ __name__="MySQLdb",
+ threadsafety="123",
+ apilevel="123",
+ paramstyle="test",
+ )
+ mock_connect_module._mysql.get_client_info.return_value = "foobaz"
+ mock_cursor = mock_connect_module.connect().cursor()
+ mock_connection = mock.MagicMock()
+ mock_connection.cursor.return_value = mock_cursor
+
+ with mock.patch(
+ "opentelemetry.instrumentation.mysqlclient.MySQLdb",
+ mock_connect_module,
+ ), mock.patch(
+ "opentelemetry.instrumentation.dbapi.util_version",
+ return_value="foobar",
+ ):
+ MySQLClientInstrumentor()._instrument(
+ enable_commenter=True,
+ )
+ cnx = mock_connect_module.connect(database="test")
+ cursor = cnx.cursor()
+ cursor.execute("Select 1;")
+
+ spans_list = self.memory_exporter.get_finished_spans()
+ span = spans_list[0]
+ span_id = format(span.get_span_context().span_id, "016x")
+ trace_id = format(span.get_span_context().trace_id, "032x")
+ self.assertEqual(
+ mock_cursor.execute.call_args[0][0],
+ f"Select 1 /*db_driver='MySQLdb%%3Afoobar',dbapi_level='123',dbapi_threadsafety='123',driver_paramstyle='test',mysql_client_version='foobaz',traceparent='00-{trace_id}-{span_id}-01'*/;",
+ )
+
+ def test_instrument_with_dbapi_sqlcomment_enabled_with_options(
+ self,
+ ):
+ mock_connect_module = mock.MagicMock(
+ __name__="MySQLdb",
+ threadsafety="123",
+ apilevel="123",
+ paramstyle="test",
+ )
+ mock_connect_module._mysql.get_client_info.return_value = "foobaz"
+ mock_cursor = mock_connect_module.connect().cursor()
+ mock_connection = mock.MagicMock()
+ mock_connection.cursor.return_value = mock_cursor
+
+ with mock.patch(
+ "opentelemetry.instrumentation.mysqlclient.MySQLdb",
+ mock_connect_module,
+ ), mock.patch(
+ "opentelemetry.instrumentation.dbapi.util_version",
+ return_value="foobar",
+ ):
+ MySQLClientInstrumentor()._instrument(
+ enable_commenter=True,
+ commenter_options={
+ "dbapi_level": False,
+ "dbapi_threadsafety": True,
+ "driver_paramstyle": False,
+ },
+ )
+ cnx = mock_connect_module.connect(database="test")
+ cursor = cnx.cursor()
+ cursor.execute("Select 1;")
+
+ spans_list = self.memory_exporter.get_finished_spans()
+ span = spans_list[0]
+ span_id = format(span.get_span_context().span_id, "016x")
+ trace_id = format(span.get_span_context().trace_id, "032x")
+ self.assertEqual(
+ mock_cursor.execute.call_args[0][0],
+ f"Select 1 /*db_driver='MySQLdb%%3Afoobar',dbapi_threadsafety='123',mysql_client_version='foobaz',traceparent='00-{trace_id}-{span_id}-01'*/;",
+ )
+
+ def test_instrument_with_dbapi_sqlcomment_not_enabled_default(
+ self,
+ ):
+ mock_connect_module = mock.MagicMock(
+ __name__="MySQLdb",
+ threadsafety="123",
+ apilevel="123",
+ paramstyle="test",
+ )
+ mock_connect_module._mysql.get_client_info.return_value = "foobaz"
+ mock_cursor = mock_connect_module.connect().cursor()
+ mock_connection = mock.MagicMock()
+ mock_connection.cursor.return_value = mock_cursor
+
+ with mock.patch(
+ "opentelemetry.instrumentation.mysqlclient.MySQLdb",
+ mock_connect_module,
+ ), mock.patch(
+ "opentelemetry.instrumentation.dbapi.util_version",
+ return_value="foobar",
+ ):
+ MySQLClientInstrumentor()._instrument()
+ cnx = mock_connect_module.connect(database="test")
+ cursor = cnx.cursor()
+ cursor.execute("Select 1;")
+ self.assertEqual(
+ mock_cursor.execute.call_args[0][0],
+ "Select 1;",
+ )
+
@mock.patch("MySQLdb.connect")
# pylint: disable=unused-argument
def test_uninstrument_connection(self, mock_connect):
diff --git a/instrumentation/opentelemetry-instrumentation-psycopg/tests/test_psycopg_integration.py b/instrumentation/opentelemetry-instrumentation-psycopg/tests/test_psycopg_integration.py
index dc9969ba8c..4ddaad9174 100644
--- a/instrumentation/opentelemetry-instrumentation-psycopg/tests/test_psycopg_integration.py
+++ b/instrumentation/opentelemetry-instrumentation-psycopg/tests/test_psycopg_integration.py
@@ -182,7 +182,7 @@ def test_instrumentor(self):
span = spans_list[0]
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.psycopg
)
@@ -213,7 +213,7 @@ def test_instrumentor_with_connection_class(self):
span = spans_list[0]
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.psycopg
)
@@ -407,7 +407,7 @@ async def test_async_connection():
span = spans_list[0]
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.psycopg
)
@@ -435,7 +435,7 @@ async def test_async_connection():
span = spans_list[0]
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.psycopg
)
diff --git a/instrumentation/opentelemetry-instrumentation-psycopg2/tests/test_psycopg2_integration.py b/instrumentation/opentelemetry-instrumentation-psycopg2/tests/test_psycopg2_integration.py
index 6671073043..9a6a5ff2fa 100644
--- a/instrumentation/opentelemetry-instrumentation-psycopg2/tests/test_psycopg2_integration.py
+++ b/instrumentation/opentelemetry-instrumentation-psycopg2/tests/test_psycopg2_integration.py
@@ -100,7 +100,7 @@ def test_instrumentor(self):
span = spans_list[0]
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.psycopg2
)
diff --git a/instrumentation/opentelemetry-instrumentation-pymysql/src/opentelemetry/instrumentation/pymysql/__init__.py b/instrumentation/opentelemetry-instrumentation-pymysql/src/opentelemetry/instrumentation/pymysql/__init__.py
index c48a5b6b3d..eb4435813d 100644
--- a/instrumentation/opentelemetry-instrumentation-pymysql/src/opentelemetry/instrumentation/pymysql/__init__.py
+++ b/instrumentation/opentelemetry-instrumentation-pymysql/src/opentelemetry/instrumentation/pymysql/__init__.py
@@ -26,7 +26,6 @@
import pymysql
from opentelemetry.instrumentation.pymysql import PyMySQLInstrumentor
-
PyMySQLInstrumentor().instrument()
cnx = pymysql.connect(database="MySQL_Database")
@@ -36,6 +35,76 @@
cursor.close()
cnx.close()
+SQLCOMMENTER
+*****************************************
+You can optionally configure PyMySQL instrumentation to enable sqlcommenter which enriches
+the query with contextual information.
+
+Usage
+-----
+
+.. code:: python
+
+ import pymysql
+ from opentelemetry.instrumentation.pymysql import PyMySQLInstrumentor
+
+ PyMySQLInstrumentor().instrument(enable_commenter=True, commenter_options={})
+
+ cnx = pymysql.connect(database="MySQL_Database")
+ cursor = cnx.cursor()
+ cursor.execute("INSERT INTO test (testField) VALUES (123)"
+ cnx.commit()
+ cursor.close()
+ cnx.close()
+
+
+For example,
+::
+
+ Invoking cursor.execute("INSERT INTO test (testField) VALUES (123)") will lead to sql query "INSERT INTO test (testField) VALUES (123)" but when SQLCommenter is enabled
+ the query will get appended with some configurable tags like "INSERT INTO test (testField) VALUES (123) /*tag=value*/;"
+
+
+SQLCommenter Configurations
+***************************
+We can configure the tags to be appended to the sqlquery log by adding configuration inside commenter_options(default:{}) keyword
+
+db_driver = True(Default) or False
+
+For example,
+::
+Enabling this flag will add pymysql and its version, e.g. /*pymysql%%3A1.2.3*/
+
+dbapi_threadsafety = True(Default) or False
+
+For example,
+::
+Enabling this flag will add threadsafety /*dbapi_threadsafety=2*/
+
+dbapi_level = True(Default) or False
+
+For example,
+::
+Enabling this flag will add dbapi_level /*dbapi_level='2.0'*/
+
+mysql_client_version = True(Default) or False
+
+For example,
+::
+Enabling this flag will add mysql_client_version /*mysql_client_version='123'*/
+
+driver_paramstyle = True(Default) or False
+
+For example,
+::
+Enabling this flag will add driver_paramstyle /*driver_paramstyle='pyformat'*/
+
+opentelemetry_values = True(Default) or False
+
+For example,
+::
+Enabling this flag will add traceparent values /*traceparent='00-03afa25236b8cd948fa853d67038ac79-405ff022e8247c46-01'*/
+
API
---
"""
@@ -59,14 +128,16 @@
class PyMySQLInstrumentor(BaseInstrumentor):
- def instrumentation_dependencies(self) -> Collection[str]:
+ def instrumentation_dependencies(self) -> Collection[str]: # pylint: disable=no-self-use
return _instruments
- def _instrument(self, **kwargs):
+ def _instrument(self, **kwargs): # pylint: disable=no-self-use
"""Integrate with the PyMySQL library.
https://github.com/PyMySQL/PyMySQL/
"""
tracer_provider = kwargs.get("tracer_provider")
+ enable_sqlcommenter = kwargs.get("enable_commenter", False)
+ commenter_options = kwargs.get("commenter_options", {})
dbapi.wrap_connect(
__name__,
@@ -76,14 +147,21 @@ def _instrument(self, **kwargs):
_CONNECTION_ATTRIBUTES,
version=__version__,
tracer_provider=tracer_provider,
+ enable_commenter=enable_sqlcommenter,
+ commenter_options=commenter_options,
)
- def _uninstrument(self, **kwargs):
+ def _uninstrument(self, **kwargs): # pylint: disable=no-self-use
""" "Disable PyMySQL instrumentation"""
dbapi.unwrap_connect(pymysql, "connect")
@staticmethod
- def instrument_connection(connection, tracer_provider=None):
+ def instrument_connection(
+ connection,
+ tracer_provider=None,
+ enable_commenter=None,
+ commenter_options=None,
+ ):
"""Enable instrumentation in a PyMySQL connection.
Args:
@@ -102,6 +180,9 @@ def instrument_connection(connection, tracer_provider=None):
_CONNECTION_ATTRIBUTES,
version=__version__,
tracer_provider=tracer_provider,
+ enable_commenter=enable_commenter,
+ commenter_options=commenter_options,
+ connect_module=pymysql,
)
@staticmethod
diff --git a/instrumentation/opentelemetry-instrumentation-pymysql/tests/test_pymysql_integration.py b/instrumentation/opentelemetry-instrumentation-pymysql/tests/test_pymysql_integration.py
index 6f8af5d8df..82294236f0 100644
--- a/instrumentation/opentelemetry-instrumentation-pymysql/tests/test_pymysql_integration.py
+++ b/instrumentation/opentelemetry-instrumentation-pymysql/tests/test_pymysql_integration.py
@@ -24,6 +24,7 @@
class TestPyMysqlIntegration(TestBase):
+ # pylint: disable=invalid-name
def tearDown(self):
super().tearDown()
with self.disable_logging():
@@ -44,7 +45,7 @@ def test_instrumentor(self, mock_connect):
span = spans_list[0]
# Check version and name in span's instrumentation info
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.pymysql
)
@@ -111,6 +112,244 @@ def test_instrument_connection(self, mock_connect):
spans_list = self.memory_exporter.get_finished_spans()
self.assertEqual(len(spans_list), 1)
+ @mock.patch("opentelemetry.instrumentation.dbapi.instrument_connection")
+ @mock.patch("pymysql.connect")
+ # pylint: disable=unused-argument
+ def test_instrument_connection_enable_commenter_dbapi_kwargs(
+ self,
+ mock_connect,
+ mock_instrument_connection,
+ ):
+ cnx = pymysql.connect(database="test")
+ cnx = PyMySQLInstrumentor().instrument_connection(
+ cnx,
+ enable_commenter=True,
+ commenter_options={"foo": True},
+ )
+ cursor = cnx.cursor()
+ cursor.execute("SELECT * FROM test")
+ kwargs = mock_instrument_connection.call_args[1]
+ self.assertEqual(kwargs["enable_commenter"], True)
+ self.assertEqual(kwargs["commenter_options"], {"foo": True})
+
+ def test_instrument_connection_with_dbapi_sqlcomment_enabled(self):
+ mock_connect_module = mock.MagicMock(
+ __name__="pymysql",
+ __version__="foobar",
+ threadsafety="123",
+ apilevel="123",
+ paramstyle="test",
+ )
+ mock_connect_module.get_client_info.return_value = "foobaz"
+ mock_cursor = mock_connect_module.connect().cursor()
+ mock_connection = mock.MagicMock()
+ mock_connection.cursor.return_value = mock_cursor
+
+ with mock.patch(
+ "opentelemetry.instrumentation.pymysql.pymysql",
+ mock_connect_module,
+ ):
+ cnx_proxy = PyMySQLInstrumentor().instrument_connection(
+ mock_connection,
+ enable_commenter=True,
+ )
+ cnx_proxy.cursor().execute("Select 1;")
+
+ spans_list = self.memory_exporter.get_finished_spans()
+ span = spans_list[0]
+ span_id = format(span.get_span_context().span_id, "016x")
+ trace_id = format(span.get_span_context().trace_id, "032x")
+ self.assertEqual(
+ mock_cursor.execute.call_args[0][0],
+ f"Select 1 /*db_driver='pymysql%%3Afoobar',dbapi_level='123',dbapi_threadsafety='123',driver_paramstyle='test',mysql_client_version='foobaz',traceparent='00-{trace_id}-{span_id}-01'*/;",
+ )
+
+ def test_instrument_connection_with_dbapi_sqlcomment_enabled_with_options(
+ self,
+ ):
+ mock_connect_module = mock.MagicMock(
+ __name__="pymysql",
+ __version__="foobar",
+ threadsafety="123",
+ apilevel="123",
+ paramstyle="test",
+ )
+ mock_connect_module.get_client_info.return_value = "foobaz"
+ mock_cursor = mock_connect_module.connect().cursor()
+ mock_connection = mock.MagicMock()
+ mock_connection.cursor.return_value = mock_cursor
+
+ with mock.patch(
+ "opentelemetry.instrumentation.pymysql.pymysql",
+ mock_connect_module,
+ ):
+ cnx_proxy = PyMySQLInstrumentor().instrument_connection(
+ mock_connection,
+ enable_commenter=True,
+ commenter_options={
+ "dbapi_level": False,
+ "dbapi_threadsafety": True,
+ "driver_paramstyle": False,
+ },
+ )
+ cnx_proxy.cursor().execute("Select 1;")
+
+ spans_list = self.memory_exporter.get_finished_spans()
+ span = spans_list[0]
+ span_id = format(span.get_span_context().span_id, "016x")
+ trace_id = format(span.get_span_context().trace_id, "032x")
+ self.assertEqual(
+ mock_cursor.execute.call_args[0][0],
+ f"Select 1 /*db_driver='pymysql%%3Afoobar',dbapi_threadsafety='123',mysql_client_version='foobaz',traceparent='00-{trace_id}-{span_id}-01'*/;",
+ )
+
+ def test_instrument_connection_with_dbapi_sqlcomment_not_enabled_default(
+ self,
+ ):
+ mock_connect_module = mock.MagicMock(
+ __name__="pymysql",
+ __version__="foobar",
+ threadsafety="123",
+ apilevel="123",
+ paramstyle="test",
+ )
+ mock_connect_module.get_client_info.return_value = "foobaz"
+ mock_cursor = mock_connect_module.connect().cursor()
+ mock_connection = mock.MagicMock()
+ mock_connection.cursor.return_value = mock_cursor
+
+ with mock.patch(
+ "opentelemetry.instrumentation.pymysql.pymysql",
+ mock_connect_module,
+ ):
+ cnx_proxy = PyMySQLInstrumentor().instrument_connection(
+ mock_connection,
+ )
+ cnx_proxy.cursor().execute("Select 1;")
+ self.assertEqual(
+ mock_cursor.execute.call_args[0][0],
+ "Select 1;",
+ )
+
+ @mock.patch("opentelemetry.instrumentation.dbapi.wrap_connect")
+ @mock.patch("pymysql.connect")
+ # pylint: disable=unused-argument
+ def test_instrument_enable_commenter_dbapi_kwargs(
+ self,
+ mock_connect,
+ mock_wrap_connect,
+ ):
+ PyMySQLInstrumentor()._instrument(
+ enable_commenter=True,
+ commenter_options={"foo": True},
+ )
+ kwargs = mock_wrap_connect.call_args[1]
+ self.assertEqual(kwargs["enable_commenter"], True)
+ self.assertEqual(kwargs["commenter_options"], {"foo": True})
+
+ def test_instrument_with_dbapi_sqlcomment_enabled(
+ self,
+ ):
+ mock_connect_module = mock.MagicMock(
+ __name__="pymysql",
+ __version__="foobar",
+ threadsafety="123",
+ apilevel="123",
+ paramstyle="test",
+ )
+ mock_connect_module.get_client_info.return_value = "foobaz"
+ mock_cursor = mock_connect_module.connect().cursor()
+ mock_connection = mock.MagicMock()
+ mock_connection.cursor.return_value = mock_cursor
+
+ with mock.patch(
+ "opentelemetry.instrumentation.pymysql.pymysql",
+ mock_connect_module,
+ ):
+ PyMySQLInstrumentor()._instrument(
+ enable_commenter=True,
+ )
+ cnx = mock_connect_module.connect(database="test")
+ cursor = cnx.cursor()
+ cursor.execute("Select 1;")
+
+ spans_list = self.memory_exporter.get_finished_spans()
+ span = spans_list[0]
+ span_id = format(span.get_span_context().span_id, "016x")
+ trace_id = format(span.get_span_context().trace_id, "032x")
+ self.assertEqual(
+ mock_cursor.execute.call_args[0][0],
+ f"Select 1 /*db_driver='pymysql%%3Afoobar',dbapi_level='123',dbapi_threadsafety='123',driver_paramstyle='test',mysql_client_version='foobaz',traceparent='00-{trace_id}-{span_id}-01'*/;",
+ )
+
+ def test_instrument_with_dbapi_sqlcomment_enabled_with_options(
+ self,
+ ):
+ mock_connect_module = mock.MagicMock(
+ __name__="pymysql",
+ __version__="foobar",
+ threadsafety="123",
+ apilevel="123",
+ paramstyle="test",
+ )
+ mock_connect_module.get_client_info.return_value = "foobaz"
+ mock_cursor = mock_connect_module.connect().cursor()
+ mock_connection = mock.MagicMock()
+ mock_connection.cursor.return_value = mock_cursor
+
+ with mock.patch(
+ "opentelemetry.instrumentation.pymysql.pymysql",
+ mock_connect_module,
+ ):
+ PyMySQLInstrumentor()._instrument(
+ enable_commenter=True,
+ commenter_options={
+ "dbapi_level": False,
+ "dbapi_threadsafety": True,
+ "driver_paramstyle": False,
+ },
+ )
+ cnx = mock_connect_module.connect(database="test")
+ cursor = cnx.cursor()
+ cursor.execute("Select 1;")
+
+ spans_list = self.memory_exporter.get_finished_spans()
+ span = spans_list[0]
+ span_id = format(span.get_span_context().span_id, "016x")
+ trace_id = format(span.get_span_context().trace_id, "032x")
+ self.assertEqual(
+ mock_cursor.execute.call_args[0][0],
+ f"Select 1 /*db_driver='pymysql%%3Afoobar',dbapi_threadsafety='123',mysql_client_version='foobaz',traceparent='00-{trace_id}-{span_id}-01'*/;",
+ )
+
+ def test_instrument_with_dbapi_sqlcomment_not_enabled_default(
+ self,
+ ):
+ mock_connect_module = mock.MagicMock(
+ __name__="pymysql",
+ __version__="foobar",
+ threadsafety="123",
+ apilevel="123",
+ paramstyle="test",
+ )
+ mock_connect_module.get_client_info.return_value = "foobaz"
+ mock_cursor = mock_connect_module.connect().cursor()
+ mock_connection = mock.MagicMock()
+ mock_connection.cursor.return_value = mock_cursor
+
+ with mock.patch(
+ "opentelemetry.instrumentation.pymysql.pymysql",
+ mock_connect_module,
+ ):
+ PyMySQLInstrumentor()._instrument()
+ cnx = mock_connect_module.connect(database="test")
+ cursor = cnx.cursor()
+ cursor.execute("Select 1;")
+ self.assertEqual(
+ mock_cursor.execute.call_args[0][0],
+ "Select 1;",
+ )
+
@mock.patch("pymysql.connect")
# pylint: disable=unused-argument
def test_uninstrument_connection(self, mock_connect):
diff --git a/instrumentation/opentelemetry-instrumentation-requests/tests/test_requests_integration.py b/instrumentation/opentelemetry-instrumentation-requests/tests/test_requests_integration.py
index a5cb8927ae..366cd0c233 100644
--- a/instrumentation/opentelemetry-instrumentation-requests/tests/test_requests_integration.py
+++ b/instrumentation/opentelemetry-instrumentation-requests/tests/test_requests_integration.py
@@ -166,7 +166,7 @@ def test_basic(self):
self.assertIs(span.status.status_code, trace.StatusCode.UNSET)
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.requests
)
diff --git a/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/engine.py b/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/engine.py
index 172c1193f3..b64af796d1 100644
--- a/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/engine.py
+++ b/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/engine.py
@@ -219,28 +219,31 @@ def _before_cur_exec(
)
with trace.use_span(span, end_on_exit=False):
if span.is_recording():
+ if self.enable_commenter:
+ commenter_data = {
+ "db_driver": conn.engine.driver,
+ # Driver/framework centric information.
+ "db_framework": f"sqlalchemy:{sqlalchemy.__version__}",
+ }
+
+ if self.commenter_options.get(
+ "opentelemetry_values", True
+ ):
+ commenter_data.update(**_get_opentelemetry_values())
+
+ # Filter down to just the requested attributes.
+ commenter_data = {
+ k: v
+ for k, v in commenter_data.items()
+ if self.commenter_options.get(k, True)
+ }
+
+ statement = _add_sql_comment(statement, **commenter_data)
+
span.set_attribute(SpanAttributes.DB_STATEMENT, statement)
span.set_attribute(SpanAttributes.DB_SYSTEM, self.vendor)
for key, value in attrs.items():
span.set_attribute(key, value)
- if self.enable_commenter:
- commenter_data = {
- "db_driver": conn.engine.driver,
- # Driver/framework centric information.
- "db_framework": f"sqlalchemy:{sqlalchemy.__version__}",
- }
-
- if self.commenter_options.get("opentelemetry_values", True):
- commenter_data.update(**_get_opentelemetry_values())
-
- # Filter down to just the requested attributes.
- commenter_data = {
- k: v
- for k, v in commenter_data.items()
- if self.commenter_options.get(k, True)
- }
-
- statement = _add_sql_comment(statement, **commenter_data)
context._otel_span = span
diff --git a/instrumentation/opentelemetry-instrumentation-sqlalchemy/tests/test_sqlcommenter.py b/instrumentation/opentelemetry-instrumentation-sqlalchemy/tests/test_sqlcommenter.py
index ec2fc51e5b..8490721e3e 100644
--- a/instrumentation/opentelemetry-instrumentation-sqlalchemy/tests/test_sqlcommenter.py
+++ b/instrumentation/opentelemetry-instrumentation-sqlalchemy/tests/test_sqlcommenter.py
@@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
+import re
import pytest
from sqlalchemy import (
@@ -21,6 +22,7 @@
from opentelemetry import context
from opentelemetry.instrumentation.sqlalchemy import SQLAlchemyInstrumentor
+from opentelemetry.semconv.trace import SpanAttributes
from opentelemetry.test.test_base import TestBase
@@ -59,6 +61,38 @@ def test_sqlcommenter_enabled(self):
r"SELECT 1 /\*db_driver='(.*)',traceparent='\d{1,2}-[a-zA-Z0-9_]{32}-[a-zA-Z0-9_]{16}-\d{1,2}'\*/;",
)
+ def test_sqlcommenter_enabled_matches_db_statement_attribute(self):
+ engine = create_engine("sqlite:///:memory:")
+ SQLAlchemyInstrumentor().instrument(
+ engine=engine,
+ tracer_provider=self.tracer_provider,
+ enable_commenter=True,
+ commenter_options={"db_framework": False},
+ )
+ cnx = engine.connect()
+ cnx.execute(text("SELECT 1;")).fetchall()
+ query_log = self.caplog.records[-2].getMessage()
+ self.assertRegex(
+ query_log,
+ r"SELECT 1 /\*db_driver='(.*)',traceparent='\d{1,2}-[a-zA-Z0-9_]{32}-[a-zA-Z0-9_]{16}-\d{1,2}'\*/;",
+ )
+ spans = self.memory_exporter.get_finished_spans()
+ self.assertEqual(len(spans), 2)
+ # first span is connection to db
+ self.assertEqual(spans[0].name, "connect")
+ # second span is query itself
+ query_span = spans[1]
+ self.assertRegex(
+ query_span.attributes[SpanAttributes.DB_STATEMENT],
+ r"SELECT 1 /\*db_driver='(.*)',traceparent='\d{1,2}-[a-zA-Z0-9_]{32}-[a-zA-Z0-9_]{16}-\d{1,2}'\*/;",
+ )
+ cnx_span_id = re.search(r"[a-zA-Z0-9_]{16}", query_log).group()
+ db_statement_span_id = re.search(
+ r"[a-zA-Z0-9_]{16}",
+ query_span.attributes[SpanAttributes.DB_STATEMENT],
+ ).group()
+ self.assertEqual(cnx_span_id, db_statement_span_id)
+
def test_sqlcommenter_enabled_otel_values_false(self):
engine = create_engine("sqlite:///:memory:")
SQLAlchemyInstrumentor().instrument(
diff --git a/instrumentation/opentelemetry-instrumentation-system-metrics/src/opentelemetry/instrumentation/system_metrics/__init__.py b/instrumentation/opentelemetry-instrumentation-system-metrics/src/opentelemetry/instrumentation/system_metrics/__init__.py
index 4e1ee2a5df..aff86ea77b 100644
--- a/instrumentation/opentelemetry-instrumentation-system-metrics/src/opentelemetry/instrumentation/system_metrics/__init__.py
+++ b/instrumentation/opentelemetry-instrumentation-system-metrics/src/opentelemetry/instrumentation/system_metrics/__init__.py
@@ -40,6 +40,7 @@
"process.runtime.thread_count": None,
"process.runtime.cpu.utilization": None,
"process.runtime.context_switches": ["involuntary", "voluntary"],
+ "process.open_file_descriptor.count": None,
}
Usage
@@ -595,7 +596,7 @@ def _get_system_network_packets(
"""Observer callback for network packets"""
for device, counters in psutil.net_io_counters(pernic=True).items():
- for metric in self._config["system.network.dropped.packets"]:
+ for metric in self._config["system.network.packets"]:
recv_sent = {"receive": "recv", "transmit": "sent"}[metric]
if hasattr(counters, f"packets_{recv_sent}"):
self._system_network_packets_labels["device"] = device
@@ -626,7 +627,7 @@ def _get_system_network_io(
"""Observer callback for network IO"""
for device, counters in psutil.net_io_counters(pernic=True).items():
- for metric in self._config["system.network.dropped.packets"]:
+ for metric in self._config["system.network.io"]:
recv_sent = {"receive": "recv", "transmit": "sent"}[metric]
if hasattr(counters, f"bytes_{recv_sent}"):
self._system_network_io_labels["device"] = device
diff --git a/instrumentation/opentelemetry-instrumentation-system-metrics/tests/test_system_metrics.py b/instrumentation/opentelemetry-instrumentation-system-metrics/tests/test_system_metrics.py
index 83abcff4c0..92c30a66f0 100644
--- a/instrumentation/opentelemetry-instrumentation-system-metrics/tests/test_system_metrics.py
+++ b/instrumentation/opentelemetry-instrumentation-system-metrics/tests/test_system_metrics.py
@@ -20,6 +20,7 @@
from unittest import mock, skipIf
from opentelemetry.instrumentation.system_metrics import (
+ _DEFAULT_CONFIG,
SystemMetricsInstrumentor,
)
from opentelemetry.sdk.metrics import MeterProvider
@@ -865,3 +866,14 @@ def test_open_file_descriptor_count(self, mock_process_num_fds):
expected,
)
mock_process_num_fds.assert_called()
+
+
+class TestConfigSystemMetrics(TestBase):
+ # pylint:disable=no-self-use
+ def test_that_correct_config_is_read(self):
+ for key, value in _DEFAULT_CONFIG.items():
+ meter_provider = MeterProvider([InMemoryMetricReader()])
+ instrumentor = SystemMetricsInstrumentor(config={key: value})
+ instrumentor.instrument(meter_provider=meter_provider)
+ meter_provider.force_flush()
+ instrumentor.uninstrument()
diff --git a/instrumentation/opentelemetry-instrumentation-urllib/tests/test_urllib_integration.py b/instrumentation/opentelemetry-instrumentation-urllib/tests/test_urllib_integration.py
index 8ac0284939..b085cc50d5 100644
--- a/instrumentation/opentelemetry-instrumentation-urllib/tests/test_urllib_integration.py
+++ b/instrumentation/opentelemetry-instrumentation-urllib/tests/test_urllib_integration.py
@@ -158,7 +158,7 @@ def test_basic(self):
self.assertIs(span.status.status_code, trace.StatusCode.UNSET)
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.urllib
)
@@ -182,7 +182,7 @@ def test_basic_new_semconv(self):
self.assertIs(span.status.status_code, trace.StatusCode.UNSET)
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.urllib
)
@@ -209,7 +209,7 @@ def test_basic_both_semconv(self):
self.assertIs(span.status.status_code, trace.StatusCode.UNSET)
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.urllib
)
@@ -344,7 +344,7 @@ def test_response_code_none(self):
self.assertIs(span.status.status_code, trace.StatusCode.UNSET)
- self.assertEqualSpanInstrumentationInfo(
+ self.assertEqualSpanInstrumentationScope(
span, opentelemetry.instrumentation.urllib
)
diff --git a/opentelemetry-instrumentation/src/opentelemetry/instrumentation/bootstrap_gen.py b/opentelemetry-instrumentation/src/opentelemetry/instrumentation/bootstrap_gen.py
index 2e7b5532f3..6b7eae6b00 100644
--- a/opentelemetry-instrumentation/src/opentelemetry/instrumentation/bootstrap_gen.py
+++ b/opentelemetry-instrumentation/src/opentelemetry/instrumentation/bootstrap_gen.py
@@ -16,6 +16,10 @@
# RUN `python scripts/generate_instrumentation_bootstrap.py` TO REGENERATE.
libraries = [
+ {
+ "library": "openai >= 1.26.0",
+ "instrumentation": "opentelemetry-instrumentation-openai-v2==2.1b0.dev",
+ },
{
"library": "aio_pika >= 7.2.0, < 10.0.0",
"instrumentation": "opentelemetry-instrumentation-aio-pika==0.50b0.dev",
diff --git a/scripts/eachdist.py b/scripts/eachdist.py
index b82d16a8ec..ca490546eb 100755
--- a/scripts/eachdist.py
+++ b/scripts/eachdist.py
@@ -237,6 +237,16 @@ def setup_instparser(instparser):
"releaseargs", nargs=argparse.REMAINDER, help=extraargs_help("pytest")
)
+ patchreleaseparser = subparsers.add_parser(
+ "update_patch_versions",
+ help="Updates version numbers during patch release, used by maintainers and CI",
+ )
+ patchreleaseparser.set_defaults(func=patch_release_args)
+ patchreleaseparser.add_argument("--stable_version", required=True)
+ patchreleaseparser.add_argument("--unstable_version", required=True)
+ patchreleaseparser.add_argument("--stable_version_prev", required=True)
+ patchreleaseparser.add_argument("--unstable_version_prev", required=True)
+
fmtparser = subparsers.add_parser(
"format",
help="Formats all source code with black and isort.",
@@ -655,6 +665,27 @@ def update_dependencies(targets, version, packages):
)
+def update_patch_dependencies(targets, version, prev_version, packages):
+ print("updating patch dependencies")
+ if "all" in packages:
+ packages.extend(targets)
+
+ # PEP 508 allowed specifier operators
+ operators = ["==", "!=", "<=", ">=", "<", ">", "===", "~=", "="]
+ operators_pattern = "|".join(re.escape(op) for op in operators)
+
+ for pkg in packages:
+ search = rf"({basename(pkg)}[^,]*?)(\s?({operators_pattern})\s?)(.*{prev_version})"
+ replace = r"\g<1>\g<2>" + version
+ print(f"{search=}\t{replace=}\t{pkg=}")
+ update_files(
+ targets,
+ "pyproject.toml",
+ search,
+ replace,
+ )
+
+
def update_files(targets, filename, search, replace):
errors = False
for target in targets:
@@ -687,10 +718,12 @@ def release_args(args):
versions = args.versions
updated_versions = []
+ # remove excluded packages
excluded = cfg["exclude_release"]["packages"].split()
targets = [
target for target in targets if basename(target) not in excluded
]
+
for group in versions.split(","):
mcfg = cfg[group]
version = mcfg["version"]
@@ -707,6 +740,40 @@ def release_args(args):
update_changelogs("-".join(updated_versions))
+def patch_release_args(args):
+ print("preparing patch release")
+
+ rootpath = find_projectroot()
+ targets = list(find_targets_unordered(rootpath))
+ cfg = ConfigParser()
+ cfg.read(str(find_projectroot() / "eachdist.ini"))
+
+ # remove excluded packages
+ excluded = cfg["exclude_release"]["packages"].split()
+ targets = [
+ target for target in targets if basename(target) not in excluded
+ ]
+
+ # stable
+ mcfg = cfg["stable"]
+ packages = mcfg["packages"].split()
+ print(f"update stable packages to {args.stable_version}")
+
+ update_patch_dependencies(
+ targets, args.stable_version, args.stable_version_prev, packages
+ )
+ update_version_files(targets, args.stable_version, packages)
+
+ # prerelease
+ mcfg = cfg["prerelease"]
+ packages = mcfg["packages"].split()
+ print(f"update prerelease packages to {args.unstable_version}")
+ update_patch_dependencies(
+ targets, args.unstable_version, args.unstable_version_prev, packages
+ )
+ update_version_files(targets, args.unstable_version, packages)
+
+
def test_args(args):
clean_remainder_args(args.pytestargs)
execute_args(
diff --git a/scripts/otel_packaging.py b/scripts/otel_packaging.py
index 2f42e44189..3b09dd87eb 100644
--- a/scripts/otel_packaging.py
+++ b/scripts/otel_packaging.py
@@ -21,14 +21,23 @@
scripts_path = os.path.dirname(os.path.abspath(__file__))
root_path = os.path.dirname(scripts_path)
instrumentations_path = os.path.join(root_path, "instrumentation")
+genai_instrumentations_path = os.path.join(root_path, "instrumentation-genai")
def get_instrumentation_packages():
- for pkg in sorted(os.listdir(instrumentations_path)):
+ pkg_paths = []
+ for pkg in os.listdir(instrumentations_path):
pkg_path = os.path.join(instrumentations_path, pkg)
if not os.path.isdir(pkg_path):
continue
+ pkg_paths.append(pkg_path)
+ for pkg in os.listdir(genai_instrumentations_path):
+ pkg_path = os.path.join(genai_instrumentations_path, pkg)
+ if not os.path.isdir(pkg_path):
+ continue
+ pkg_paths.append(pkg_path)
+ for pkg_path in sorted(pkg_paths):
try:
version = subprocess.check_output(
"hatch version",