From d9c7f5fc07186070bc5d42d17145af07658dfacc Mon Sep 17 00:00:00 2001 From: Rishita Date: Mon, 27 Jul 2026 03:30:01 +0530 Subject: [PATCH 1/8] feat: Add Groq instrumentation package Assisted-by: Antigravity --- .../.changelog/141.added | 1 + .../README.rst | 114 ++++++++ .../examples/manual/.env | 26 ++ .../examples/manual/README.rst | 58 ++++ .../examples/manual/custom_hook.py | 98 +++++++ .../examples/manual/main.py | 70 +++++ .../examples/manual/requirements.txt | 9 + .../examples/zero-code/.env | 29 ++ .../examples/zero-code/README.rst | 45 +++ .../examples/zero-code/main.py | 24 ++ .../examples/zero-code/requirements.txt | 10 + .../pyproject.toml | 85 ++++++ .../instrumentation/genai/groq/__init__.py | 146 ++++++++++ .../genai/groq/chat_buffers.py | 52 ++++ .../genai/groq/chat_wrappers.py | 217 +++++++++++++++ .../instrumentation/genai/groq/package.py | 1 + .../instrumentation/genai/groq/patch.py | 156 +++++++++++ .../instrumentation/genai/groq/utils.py | 257 ++++++++++++++++++ .../instrumentation/genai/groq/version.py | 15 + .../tests/__init__.py | 2 + .../cassettes/inference_conformance.yaml | 48 ++++ .../test_chat_completions_basic.yaml | 48 ++++ .../tests/conformance/__init__.py | 2 + .../tests/conformance/inference.py | 49 ++++ .../tests/conftest.py | 128 +++++++++ .../tests/requirements.latest.txt | 1 + .../tests/requirements.oldest.txt | 1 + .../tests/test_chat_completions.py | 38 +++ .../tests/test_conformance.py | 34 +++ pyproject.toml | 2 + tox.ini | 22 ++ uv.lock | 45 ++- 32 files changed, 1832 insertions(+), 1 deletion(-) create mode 100644 instrumentation/opentelemetry-instrumentation-genai-groq/.changelog/141.added create mode 100644 instrumentation/opentelemetry-instrumentation-genai-groq/README.rst create mode 100644 instrumentation/opentelemetry-instrumentation-genai-groq/examples/manual/.env create mode 100644 instrumentation/opentelemetry-instrumentation-genai-groq/examples/manual/README.rst create mode 100644 instrumentation/opentelemetry-instrumentation-genai-groq/examples/manual/custom_hook.py create mode 100644 instrumentation/opentelemetry-instrumentation-genai-groq/examples/manual/main.py create mode 100644 instrumentation/opentelemetry-instrumentation-genai-groq/examples/manual/requirements.txt create mode 100644 instrumentation/opentelemetry-instrumentation-genai-groq/examples/zero-code/.env create mode 100644 instrumentation/opentelemetry-instrumentation-genai-groq/examples/zero-code/README.rst create mode 100644 instrumentation/opentelemetry-instrumentation-genai-groq/examples/zero-code/main.py create mode 100644 instrumentation/opentelemetry-instrumentation-genai-groq/examples/zero-code/requirements.txt create mode 100644 instrumentation/opentelemetry-instrumentation-genai-groq/pyproject.toml create mode 100644 instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/__init__.py create mode 100644 instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/chat_buffers.py create mode 100644 instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/chat_wrappers.py create mode 100644 instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/package.py create mode 100644 instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/patch.py create mode 100644 instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/utils.py create mode 100644 instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/version.py create mode 100644 instrumentation/opentelemetry-instrumentation-genai-groq/tests/__init__.py create mode 100644 instrumentation/opentelemetry-instrumentation-genai-groq/tests/cassettes/inference_conformance.yaml create mode 100644 instrumentation/opentelemetry-instrumentation-genai-groq/tests/cassettes/test_chat_completions_basic.yaml create mode 100644 instrumentation/opentelemetry-instrumentation-genai-groq/tests/conformance/__init__.py create mode 100644 instrumentation/opentelemetry-instrumentation-genai-groq/tests/conformance/inference.py create mode 100644 instrumentation/opentelemetry-instrumentation-genai-groq/tests/conftest.py create mode 100644 instrumentation/opentelemetry-instrumentation-genai-groq/tests/requirements.latest.txt create mode 100644 instrumentation/opentelemetry-instrumentation-genai-groq/tests/requirements.oldest.txt create mode 100644 instrumentation/opentelemetry-instrumentation-genai-groq/tests/test_chat_completions.py create mode 100644 instrumentation/opentelemetry-instrumentation-genai-groq/tests/test_conformance.py diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/.changelog/141.added b/instrumentation/opentelemetry-instrumentation-genai-groq/.changelog/141.added new file mode 100644 index 000000000..8d669868e --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/.changelog/141.added @@ -0,0 +1 @@ +Add `opentelemetry-instrumentation-genai-groq` package for instrumenting the official Groq Python client. diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/README.rst b/instrumentation/opentelemetry-instrumentation-genai-groq/README.rst new file mode 100644 index 000000000..6dc75ae93 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/README.rst @@ -0,0 +1,114 @@ +OpenTelemetry Groq Instrumentation +================================== + +|pypi| + +.. |pypi| image:: https://badge.fury.io/py/opentelemetry-instrumentation-genai-groq.svg + :target: https://pypi.org/project/opentelemetry-instrumentation-genai-groq/ + +This library allows tracing LLM requests and logging of messages made by the +`Groq Python API library `_. It also captures +the duration of the operations and the number of tokens used as metrics. + +Installation +------------ + +If your application is already instrumented with OpenTelemetry, add this +package to your requirements. +:: + + pip install opentelemetry-instrumentation-genai-groq + +If you don't have a Groq application, yet, try our `examples `_ +which only need a valid Groq API key. + +Check out `zero-code example `_ for a quick start. + +Usage +----- + +This section describes how to set up Groq instrumentation if you're setting OpenTelemetry up manually. +Check out the `manual example `_ for more details. + +Instrumenting all clients +************************* + +When using the instrumentor, all clients will automatically trace Groq operations including chat completions. +You can also optionally capture prompts and completions as log events. + +Make sure to configure OpenTelemetry tracing, logging, and events to capture all telemetry emitted by the instrumentation. + +.. code-block:: python + + from opentelemetry.instrumentation.genai.groq import GroqInstrumentor + from groq import Groq + + GroqInstrumentor().instrument() + + client = Groq() + # Chat completion example + response = client.chat.completions.create( + model="llama3-8b-8192", + messages=[ + {"role": "user", "content": "Write a short poem on open telemetry."}, + ], + ) + +Enabling message content +************************* + +Message content such as the contents of the prompt, completion, function arguments and return values +are not captured by default. To capture message content, set the environment variable +``OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT`` to one of the following values: + +- ``span_only`` - capture content on *span* attributes. +- ``event_only`` - capture content on *event* attributes. +- ``span_and_event`` - capture content on both *span* and *event* attributes. +- ``no_content`` - do not capture content (the default). + +Uploading prompts and completions +********************************* + +To enable the built-in upload hook, set: + +- ``OTEL_INSTRUMENTATION_GENAI_COMPLETION_HOOK=upload`` +- ``OTEL_INSTRUMENTATION_GENAI_UPLOAD_BASE_PATH`` to an ``fsspec``-compatible URI/path + (e.g. ``/path/to/prompts`` or ``gs://my_bucket``). + +Install the ``upload`` extra to pull in ``fsspec``:: + + pip install opentelemetry-util-genai[upload] + +See the `opentelemetry-util-genai +`_ +for additional options. + +Enabling the latest experimental features +*********************************************** + +The latest experimental GenAI semantic conventions are used unconditionally; there is +no environment variable to opt in or out. + +.. note:: Generative AI semantic conventions are still evolving. The latest experimental features may introduce breaking changes in future releases. + +Uninstrument +************ + +To uninstrument clients, call the uninstrument method: + +.. code-block:: python + + from opentelemetry.instrumentation.genai.groq import GroqInstrumentor + + GroqInstrumentor().instrument() + # ... + + # Uninstrument all clients + GroqInstrumentor().uninstrument() + +References +---------- + +* `OpenTelemetry Project `_ +* `OpenTelemetry GenAI semantic conventions `_ +* `Groq SDK (Python) `_ diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/examples/manual/.env b/instrumentation/opentelemetry-instrumentation-genai-groq/examples/manual/.env new file mode 100644 index 000000000..7a0e0608d --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/examples/manual/.env @@ -0,0 +1,26 @@ +# TODO: Set your Groq API key here +GROQ_API_KEY=sk-YOUR_API_KEY + +# Uncomment to use Ollama instead of Groq +# OPENAI_BASE_URL=http://localhost:11434/v1 +# OPENAI_API_KEY=unused +# CHAT_MODEL=qwen2.5:0.5b + +# Uncomment and change to your OTLP endpoint +# OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317 +# OTEL_EXPORTER_OTLP_PROTOCOL=grpc + +OTEL_SERVICE_NAME=opentelemetry-python-openai + +# Remove to hide prompt and completion content +# Possible values (case insensitive): +# - `span_only` - record content on span attributes +# - `event_only` - record content on event attributes +# - `span_and_event` - record content on both span and event attributes +# - everything else - don't record content on any signal +OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=span_only + +# Uncomment to upload prompts and responses to an fsspec-compatible +# destination instead of or in addition to recording them inline on spans/events. +# OTEL_INSTRUMENTATION_GENAI_COMPLETION_HOOK=upload +# OTEL_INSTRUMENTATION_GENAI_UPLOAD_BASE_PATH=/path/to/prompts diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/examples/manual/README.rst b/instrumentation/opentelemetry-instrumentation-genai-groq/examples/manual/README.rst new file mode 100644 index 000000000..60eb05c3a --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/examples/manual/README.rst @@ -0,0 +1,58 @@ +OpenTelemetry Groq Instrumentation Example +============================================ + +This is an example of how to instrument Groq calls when configuring OpenTelemetry SDK and Instrumentations manually. + +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 Groq requests. + +Note: `.env <.env>`_ file configures additional environment variables: + +- ``OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=span_only`` configures Groq instrumentation to capture prompt and completion contents on *span* attributes. +- ``OTEL_INSTRUMENTATION_GENAI_COMPLETION_HOOK`` (commented out) - uncomment along with ``OTEL_INSTRUMENTATION_GENAI_UPLOAD_BASE_PATH`` to upload prompts and completions to an ``fsspec``-compatible destination instead of recording them inline. Also uncomment the ``opentelemetry-util-genai[upload]`` line in `requirements.txt `_ and reinstall. + +Setup +----- + +Minimally, update the `.env <.env>`_ file with your ``GROQ_API_KEY``. An +OTLP compatible endpoint should be listening for traces and logs on +http://localhost:4317. If not, update ``OTEL_EXPORTER_OTLP_ENDPOINT`` as well. + +Next, set up a virtual environment like this: + +:: + + python3 -m venv .venv + source .venv/bin/activate + pip install "python-dotenv[cli]" + pip install -r requirements.txt + +Run +--- + +Run the example like this: + +:: + + dotenv run -- python main.py + +You should see a poem generated by Groq while traces and logs export to your +configured observability tool. + +Custom completion hook +---------------------- + +`custom_hook.py `_ is a variant of ``main.py`` that passes a +custom ``CompletionHook`` implementation programmatically via +``GroqInstrumentor().instrument(completion_hook=...)``. The example hook +prints prompts and completions to stdout; real hooks typically forward content +to external storage and record reference URIs on the span/log_record. + +Run it the same way: + +:: + + dotenv run -- python custom_hook.py diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/examples/manual/custom_hook.py b/instrumentation/opentelemetry-instrumentation-genai-groq/examples/manual/custom_hook.py new file mode 100644 index 000000000..15d8c880f --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/examples/manual/custom_hook.py @@ -0,0 +1,98 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +# pylint: skip-file +"""Same as main.py, but instruments Groq with a custom CompletionHook +that prints prompts and completions to stdout. + +Run with: dotenv run -- python custom_hook.py +""" + +import os + +from groq import Groq + +from opentelemetry import _logs, metrics, trace +from opentelemetry.exporter.otlp.proto.grpc._log_exporter import ( + OTLPLogExporter, +) +from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import ( + OTLPMetricExporter, +) +from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import ( + OTLPSpanExporter, +) +from opentelemetry.instrumentation.genai.groq import GroqInstrumentor +from opentelemetry.sdk._logs import LoggerProvider +from opentelemetry.sdk._logs.export import BatchLogRecordProcessor +from opentelemetry.sdk.metrics import MeterProvider +from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader +from opentelemetry.sdk.trace import TracerProvider +from opentelemetry.sdk.trace.export import BatchSpanProcessor +from opentelemetry.util.genai.completion_hook import CompletionHook +from opentelemetry.util.genai.types import ( + InputMessage, + MessagePart, + OutputMessage, + ToolDefinition, +) + + +class PrintCompletionHook(CompletionHook): + """Minimal CompletionHook that prints inputs/outputs to stdout. + + Real hooks typically forward content to external storage (object store, + database, etc.) and record reference URIs on the span/log_record. + """ + + def on_completion( + self, + *, + inputs: list[InputMessage], + outputs: list[OutputMessage], + system_instruction: list[MessagePart], + tool_definitions: list[ToolDefinition] | None = None, + span=None, + log_record=None, + ) -> None: + print(f"[hook] inputs: {inputs}") + print(f"[hook] outputs: {outputs}") + + +trace.set_tracer_provider(TracerProvider()) +trace.get_tracer_provider().add_span_processor( + BatchSpanProcessor(OTLPSpanExporter()) +) + +_logs.set_logger_provider(LoggerProvider()) +_logs.get_logger_provider().add_log_record_processor( + BatchLogRecordProcessor(OTLPLogExporter()) +) + +metrics.set_meter_provider( + MeterProvider( + metric_readers=[ + PeriodicExportingMetricReader(OTLPMetricExporter()), + ] + ) +) + +GroqInstrumentor().instrument(completion_hook=PrintCompletionHook()) + + +def main(): + client = Groq() + chat_completion = client.chat.completions.create( + model=os.getenv("CHAT_MODEL", "llama3-8b-8192"), + 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/opentelemetry-instrumentation-genai-groq/examples/manual/main.py b/instrumentation/opentelemetry-instrumentation-genai-groq/examples/manual/main.py new file mode 100644 index 000000000..53d0b9334 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/examples/manual/main.py @@ -0,0 +1,70 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +# pylint: skip-file +import os + +from groq import Groq + +# NOTE: OpenTelemetry Python Logs API is in beta +from opentelemetry import _logs, metrics, trace +from opentelemetry.exporter.otlp.proto.grpc._log_exporter import ( + OTLPLogExporter, +) +from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import ( + OTLPMetricExporter, +) +from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import ( + OTLPSpanExporter, +) +from opentelemetry.instrumentation.genai.groq import GroqInstrumentor +from opentelemetry.sdk._logs import LoggerProvider +from opentelemetry.sdk._logs.export import BatchLogRecordProcessor +from opentelemetry.sdk.metrics import MeterProvider +from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader +from opentelemetry.sdk.trace import TracerProvider +from opentelemetry.sdk.trace.export import BatchSpanProcessor + +# configure tracing +trace.set_tracer_provider(TracerProvider()) +trace.get_tracer_provider().add_span_processor( + BatchSpanProcessor(OTLPSpanExporter()) +) + +# configure logging +_logs.set_logger_provider(LoggerProvider()) +_logs.get_logger_provider().add_log_record_processor( + BatchLogRecordProcessor(OTLPLogExporter()) +) + +# configure metrics +metrics.set_meter_provider( + MeterProvider( + metric_readers=[ + PeriodicExportingMetricReader( + OTLPMetricExporter(), + ), + ] + ) +) + +# instrument OpenAI +GroqInstrumentor().instrument() + + +def main(): + client = Groq() + chat_completion = client.chat.completions.create( + model=os.getenv("CHAT_MODEL", "llama3-8b-8192"), + 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/opentelemetry-instrumentation-genai-groq/examples/manual/requirements.txt b/instrumentation/opentelemetry-instrumentation-genai-groq/examples/manual/requirements.txt new file mode 100644 index 000000000..7ab0859aa --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/examples/manual/requirements.txt @@ -0,0 +1,9 @@ +groq~=0.13.0 + +opentelemetry-sdk~=1.43.0 +opentelemetry-exporter-otlp-proto-grpc~=1.43.0 +opentelemetry-instrumentation-genai-groq~=1.0b0 + +# Uncomment to enable the upload completion hook (pulls in fsspec). +# Required when OTEL_INSTRUMENTATION_GENAI_COMPLETION_HOOK=upload. +# opentelemetry-util-genai[upload] diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/examples/zero-code/.env b/instrumentation/opentelemetry-instrumentation-genai-groq/examples/zero-code/.env new file mode 100644 index 000000000..ff5e01960 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/examples/zero-code/.env @@ -0,0 +1,29 @@ +# TODO: Set your Groq API key here +GROQ_API_KEY=sk-YOUR_API_KEY + +# Uncomment to use Ollama instead of Groq +# GROQ_BASE_URL=http://localhost:11434/v1 +# GROQ_API_KEY=unused +# CHAT_MODEL=qwen2.5:0.5b + +# Uncomment and change to your OTLP endpoint +# OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317 +# OTEL_EXPORTER_OTLP_PROTOCOL=grpc + +OTEL_SERVICE_NAME=opentelemetry-python-groq + +# Uncomment if your OTLP endpoint doesn't support logs +# OTEL_LOGS_EXPORTER=console + +# Remove to hide prompt and completion content +# Possible values (case insensitive): +# - `span_only` - record content on span attributes +# - `event_only` - record content on event attributes +# - `span_and_event` - record content on both span and event attributes +# - everything else - don't record content on any signal +OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=span_only + +# Uncomment to upload prompts and responses to an fsspec-compatible +# destination instead of or in addition to recording them inline on spans/events. +# OTEL_INSTRUMENTATION_GENAI_COMPLETION_HOOK=upload +# OTEL_INSTRUMENTATION_GENAI_UPLOAD_BASE_PATH=/path/to/prompts diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/examples/zero-code/README.rst b/instrumentation/opentelemetry-instrumentation-genai-groq/examples/zero-code/README.rst new file mode 100644 index 000000000..4098baa65 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/examples/zero-code/README.rst @@ -0,0 +1,45 @@ +OpenTelemetry Groq Zero-Code Instrumentation Example +====================================================== + +This is an example of how to instrument Groq 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 Groq requests. + +Note: `.env <.env>`_ file configures additional environment variables: + +- ``OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=span_only`` configures Groq instrumentation to capture prompt and completion contents on *span* attributes. +- ``OTEL_LOGS_EXPORTER=otlp`` to specify exporter type. +- ``OTEL_INSTRUMENTATION_GENAI_COMPLETION_HOOK`` (commented out) - uncomment along with ``OTEL_INSTRUMENTATION_GENAI_UPLOAD_BASE_PATH`` to upload prompts and completions to an ``fsspec``-compatible destination instead of recording them inline. Also uncomment the ``opentelemetry-util-genai[upload]`` line in `requirements.txt `_ and reinstall. + +Setup +----- + +Minimally, update the `.env <.env>`_ file with your ``GROQ_API_KEY``. An +OTLP compatible endpoint should be listening for traces and logs on +http://localhost:4317. If not, update ``OTEL_EXPORTER_OTLP_ENDPOINT`` as well. + +Next, set up a virtual environment like this: + +:: + + python3 -m venv .venv + source .venv/bin/activate + pip install "python-dotenv[cli]" + pip install -r requirements.txt + +Run +--- + +Run the example like this: + +:: + + dotenv run -- opentelemetry-instrument python main.py + +You should see a poem generated by Groq while traces and logs export to your +configured observability tool. diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/examples/zero-code/main.py b/instrumentation/opentelemetry-instrumentation-genai-groq/examples/zero-code/main.py new file mode 100644 index 000000000..c8830e7be --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/examples/zero-code/main.py @@ -0,0 +1,24 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +import os + +from groq import Groq + + +def main(): + client = Groq() + chat_completion = client.chat.completions.create( + model=os.getenv("CHAT_MODEL", "llama-3.1-8b-instant"), + 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/opentelemetry-instrumentation-genai-groq/examples/zero-code/requirements.txt b/instrumentation/opentelemetry-instrumentation-genai-groq/examples/zero-code/requirements.txt new file mode 100644 index 000000000..6fd5824d6 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/examples/zero-code/requirements.txt @@ -0,0 +1,10 @@ +groq~=0.13.0 + +opentelemetry-sdk~=1.43.0 +opentelemetry-exporter-otlp-proto-grpc~=1.43.0 +opentelemetry-distro~=0.64b0 +opentelemetry-instrumentation-genai-groq~=1.0b0 + +# Uncomment to enable the upload completion hook (pulls in fsspec). +# Required when OTEL_INSTRUMENTATION_GENAI_COMPLETION_HOOK=upload. +# opentelemetry-util-genai[upload] diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/pyproject.toml b/instrumentation/opentelemetry-instrumentation-genai-groq/pyproject.toml new file mode 100644 index 000000000..4e05e2de6 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/pyproject.toml @@ -0,0 +1,85 @@ +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[project] +name = "opentelemetry-instrumentation-genai-groq" +dynamic = ["version"] +description = "OpenTelemetry Official Groq instrumentation" +readme = "README.rst" +license = "Apache-2.0" +requires-python = ">=3.10" +authors = [ + { name = "OpenTelemetry Authors", email = "cncf-opentelemetry-contributors@lists.cncf.io" }, +] +classifiers = [ + "Development Status :: 4 - Beta", + "Intended Audience :: Developers", + "License :: OSI Approved :: Apache Software License", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", +] +dependencies = [ + "opentelemetry-api ~= 1.43", + "opentelemetry-instrumentation >= 0.64b0, <1", + "opentelemetry-semantic-conventions >= 0.64b0, <1", + "opentelemetry-util-genai >= 1.0b0, <2", +] + +[project.optional-dependencies] +instruments = ["groq >= 0.6.0"] + +[project.entry-points.opentelemetry_instrumentor] +groq = "opentelemetry.instrumentation.genai.groq:GroqInstrumentor" + +[project.urls] +Homepage = "https://github.com/open-telemetry/opentelemetry-python-genai/tree/main/instrumentation/opentelemetry-instrumentation-genai-groq" +Repository = "https://github.com/open-telemetry/opentelemetry-python-genai" + +[tool.hatch.version] +path = "src/opentelemetry/instrumentation/genai/groq/version.py" + +[tool.hatch.build.targets.sdist] +include = ["/src", "/tests"] + +[tool.hatch.build.targets.wheel] +packages = ["src/opentelemetry"] + +[tool.towncrier] +directory = ".changelog" +filename = "CHANGELOG.md" +start_string = "\n" +template = "../../scripts/changelog_template.j2" +issue_format = "[#{issue}](https://github.com/open-telemetry/opentelemetry-python-genai/pull/{issue})" +wrap = true +issue_pattern = "^(\\d+)" + +[[tool.towncrier.type]] +directory = "added" +name = "Added" +showcontent = true + +[[tool.towncrier.type]] +directory = "changed" +name = "Changed" +showcontent = true + +[[tool.towncrier.type]] +directory = "deprecated" +name = "Deprecated" +showcontent = true + +[[tool.towncrier.type]] +directory = "removed" +name = "Removed" +showcontent = true + +[[tool.towncrier.type]] +directory = "fixed" +name = "Fixed" +showcontent = true diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/__init__.py b/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/__init__.py new file mode 100644 index 000000000..999da7183 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/__init__.py @@ -0,0 +1,146 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +""" +Groq client instrumentation supporting `groq`_, it can be enabled by +using ``GroqInstrumentor``. + +.. _groq: https://pypi.org/project/groq/ + +Usage +----- + +.. code:: python + + from groq import Groq + from opentelemetry.instrumentation.genai.groq import GroqInstrumentor + + GroqInstrumentor().instrument() + + client = Groq() + response = client.chat.completions.create( + model="llama3-8b-8192", + messages=[ + {"role": "user", "content": "Write a short poem on open telemetry."}, + ], + ) + +Configuration +------------- + +This instrumentation emits telemetry using the latest GenAI semantic +conventions and does not capture prompt or completion content by default. +Behavior is controlled via environment variables: + +- ``OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT`` - enable capture of + prompts, completions, tool arguments, and return values. Supported values + are ``span_only``, ``event_only``, and ``span_and_event``. +- ``OTEL_INSTRUMENTATION_GENAI_COMPLETION_HOOK=upload`` together with + ``OTEL_INSTRUMENTATION_GENAI_UPLOAD_BASE_PATH=`` - upload + prompts and completions to an ``fsspec``-compatible destination + (local filesystem, ``gs://``, ``s3://``, etc.) and record reference URIs as + ``gen_ai.input.messages.ref`` / ``gen_ai.output.messages.ref`` attributes. + Inline content is not captured unless + ``OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT`` is also set. + +See the `opentelemetry-util-genai README +`_ +for the full list of GenAI configuration variables. + +A custom ``CompletionHook`` implementation can also be passed programmatically:: + + GroqInstrumentor().instrument(completion_hook=my_hook) + +When provided, this takes precedence over the hook resolved from +``OTEL_INSTRUMENTATION_GENAI_COMPLETION_HOOK``. + +API +--- +""" + +from typing import Collection + +from wrapt import wrap_function_wrapper + +from opentelemetry.instrumentation.genai.groq.package import _instruments +from opentelemetry.instrumentation.instrumentor import BaseInstrumentor +from opentelemetry.instrumentation.utils import unwrap +from opentelemetry.util.genai.completion_hook import load_completion_hook +from opentelemetry.util.genai.handler import ( + TelemetryHandler, +) + +from .patch import ( + async_chat_completions_create_v_new, + chat_completions_create_v_new, +) + + +def _is_parse_supported(): + """Check if the parse() method is available on the Completions class.""" + try: + from groq.resources.chat.completions import ( # pylint: disable=import-outside-toplevel # noqa: PLC0415 + Completions, + ) + + return hasattr(Completions, "parse") + except ImportError: + return False + + +class GroqInstrumentor(BaseInstrumentor): + def __init__(self): + self._parse_supported = False + + def instrumentation_dependencies(self) -> Collection[str]: + return _instruments + + def _instrument(self, **kwargs): + """Enable Groq instrumentation.""" + + tracer_provider = kwargs.get("tracer_provider") + logger_provider = kwargs.get("logger_provider") + meter_provider = kwargs.get("meter_provider") + + handler = TelemetryHandler( + tracer_provider=tracer_provider, + meter_provider=meter_provider, + logger_provider=logger_provider, + completion_hook=kwargs.get("completion_hook") + or load_completion_hook(), + ) + + wrap_function_wrapper( + "groq.resources.chat.completions", + "Completions.create", + chat_completions_create_v_new(handler), + ) + + wrap_function_wrapper( + "groq.resources.chat.completions", + "AsyncCompletions.create", + async_chat_completions_create_v_new(handler), + ) + + self._parse_supported = _is_parse_supported() + if self._parse_supported: + wrap_function_wrapper( + "groq.resources.chat.completions", + "Completions.parse", + chat_completions_create_v_new(handler), + ) + + wrap_function_wrapper( + "groq.resources.chat.completions", + "AsyncCompletions.parse", + async_chat_completions_create_v_new(handler), + ) + + def _uninstrument(self, **kwargs): + import groq # pylint: disable=import-outside-toplevel # noqa: PLC0415 + + unwrap(groq.resources.chat.completions.Completions, "create") + unwrap(groq.resources.chat.completions.AsyncCompletions, "create") + if self._parse_supported: + unwrap(groq.resources.chat.completions.Completions, "parse") + unwrap(groq.resources.chat.completions.AsyncCompletions, "parse") diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/chat_buffers.py b/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/chat_buffers.py new file mode 100644 index 000000000..c89b4d3bb --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/chat_buffers.py @@ -0,0 +1,52 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +from __future__ import annotations + +from typing import Any + + +class ToolCallBuffer: + def __init__( + self, + index: int, + tool_call_id: str | None, + function_name: str | None, + ) -> None: + self.index: int = index + self.function_name: str | None = function_name + self.tool_call_id: str | None = tool_call_id + self.arguments: list[str] = [] + + def append_arguments(self, arguments: str | None) -> None: + if arguments is not None: + self.arguments.append(arguments) + + +class ChoiceBuffer: + def __init__(self, index: int) -> None: + self.index: int = index + self.finish_reason: str | None = None + self.text_content: list[str] = [] + self.tool_calls_buffers: list[ToolCallBuffer | None] = [] + + def append_text_content(self, content: str) -> None: + self.text_content.append(content) + + def append_tool_call(self, tool_call: Any) -> None: + idx = tool_call.index + for _ in range(len(self.tool_calls_buffers), idx + 1): + self.tool_calls_buffers.append(None) + + function = tool_call.function + buffer = self.tool_calls_buffers[idx] + if buffer is None: + buffer = ToolCallBuffer( + idx, + tool_call.id, + function.name if function else None, + ) + self.tool_calls_buffers[idx] = buffer + + if function: + buffer.append_arguments(function.arguments) diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/chat_wrappers.py b/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/chat_wrappers.py new file mode 100644 index 000000000..299fc5554 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/chat_wrappers.py @@ -0,0 +1,217 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +from __future__ import annotations + +import json +from typing import Optional, Any + +from opentelemetry.semconv._incubating.attributes import ( + openai_attributes as OpenAIAttributes, +) +from opentelemetry.util.genai.invocation import InferenceInvocation +from opentelemetry.util.genai.stream import ( + AsyncStreamWrapper, + SyncStreamWrapper, +) +from opentelemetry.util.genai.types import ( + OutputMessage, + Text, + ToolCallRequest, +) + +from .chat_buffers import ChoiceBuffer + + +class _ChatStreamMixin: + """Chat-specific hooks shared by sync and async stream wrappers.""" + + _self_invocation: InferenceInvocation + _self_capture_content: bool + _self_choice_buffers: list[ChoiceBuffer] + _self_response_id: Optional[str] + _self_response_model: Optional[str] + _self_service_tier: Optional[str] + _self_prompt_tokens: Optional[int] + _self_completion_tokens: Optional[int] + + def _set_response_model(self, chunk: Any) -> None: + if self._self_response_model: + return + + if getattr(chunk, "model", None): + self._self_response_model = chunk.model + + def _set_response_id(self, chunk: Any) -> None: + if self._self_response_id: + return + + if getattr(chunk, "id", None): + self._self_response_id = chunk.id + + def _set_response_service_tier(self, chunk: Any) -> None: + if self._self_service_tier: + return + + service_tier = getattr(chunk, "service_tier", None) + if service_tier: + self._self_service_tier = service_tier + + def _build_streaming_response(self, chunk: Any) -> None: + if getattr(chunk, "choices", None) is None: + return + + for choice in chunk.choices: + if not getattr(choice, "delta", None): + continue + + for idx in range(len(self._self_choice_buffers), choice.index + 1): + self._self_choice_buffers.append(ChoiceBuffer(idx)) + + if getattr(choice, "finish_reason", None): + self._self_choice_buffers[ + choice.index + ].finish_reason = choice.finish_reason + + if getattr(choice.delta, "content", None) is not None: + self._self_choice_buffers[choice.index].append_text_content( + choice.delta.content + ) + + if getattr(choice.delta, "tool_calls", None) is not None: + for tool_call in choice.delta.tool_calls: + self._self_choice_buffers[choice.index].append_tool_call( + tool_call + ) + + def _set_usage(self, chunk: Any) -> None: + usage = getattr(chunk, "x_groq", None) + if usage and getattr(usage, "usage", None): + self._self_completion_tokens = getattr(usage.usage, "completion_tokens", None) + self._self_prompt_tokens = getattr(usage.usage, "prompt_tokens", None) + + def _process_chunk(self, chunk: Any) -> None: + self._set_response_id(chunk) + self._set_response_model(chunk) + self._set_response_service_tier(chunk) + self._build_streaming_response(chunk) + self._set_usage(chunk) + + def _set_output_messages(self) -> None: + if not self._self_capture_content: # optimization + return + output_messages = [] + for choice in self._self_choice_buffers: + message = OutputMessage( + role="assistant", + finish_reason=choice.finish_reason or "error", + parts=[], + ) + if choice.text_content: + message.parts.append( + Text(content="".join(choice.text_content)) + ) + if choice.tool_calls_buffers: + tool_calls = [] + for tool_call in filter(None, choice.tool_calls_buffers): + arguments = None + arguments_str = "".join(tool_call.arguments) + if arguments_str: + try: + arguments = json.loads(arguments_str) + except json.JSONDecodeError: + arguments = arguments_str + tool_call_part = ToolCallRequest( + name=tool_call.function_name, + id=tool_call.tool_call_id, + arguments=arguments, + ) + tool_calls.append(tool_call_part) + message.parts.extend(tool_calls) + output_messages.append(message) + + self._self_invocation.output_messages = output_messages + + def _on_stream_end(self) -> None: + self._cleanup() + + def _on_stream_error(self, error: BaseException) -> None: + self._cleanup(error) + + def parse(self) -> _ChatStreamMixin: + """Called when using with_raw_response with stream=True.""" + return self + + def _cleanup(self, error: Optional[BaseException] = None) -> None: + self._self_invocation.response_model_name = self._self_response_model + self._self_invocation.response_id = self._self_response_id + self._self_invocation.input_tokens = self._self_prompt_tokens + self._self_invocation.output_tokens = self._self_completion_tokens + finish_reasons = [ + choice.finish_reason + for choice in self._self_choice_buffers + if choice.finish_reason + ] + if finish_reasons: + self._self_invocation.finish_reasons = finish_reasons + if self._self_service_tier: + self._self_invocation.attributes.update( + { + OpenAIAttributes.OPENAI_RESPONSE_SERVICE_TIER: self._self_service_tier + }, + ) + + self._set_output_messages() + + if error: + self._self_invocation.fail(error) + else: + self._self_invocation.stop() + + +class ChatStreamWrapper( + _ChatStreamMixin, + SyncStreamWrapper, +): + def __init__( + self, + stream: Any, + invocation: InferenceInvocation, + capture_content: bool, + ) -> None: + super().__init__(stream) + self._self_invocation = invocation + self._self_choice_buffers = [] + self._self_capture_content = capture_content + self._self_response_id = None + self._self_response_model = None + self._self_service_tier = None + self._self_prompt_tokens = None + self._self_completion_tokens = None + + +class AsyncChatStreamWrapper( + _ChatStreamMixin, + AsyncStreamWrapper, +): + def __init__( + self, + stream: Any, + invocation: InferenceInvocation, + capture_content: bool, + ) -> None: + super().__init__(stream) + self._self_invocation = invocation + self._self_choice_buffers = [] + self._self_capture_content = capture_content + self._self_response_id = None + self._self_response_model = None + self._self_service_tier = None + self._self_prompt_tokens = None + self._self_completion_tokens = None + + +__all__ = [ + "AsyncChatStreamWrapper", + "ChatStreamWrapper", +] diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/package.py b/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/package.py new file mode 100644 index 000000000..7cc4fab6e --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/package.py @@ -0,0 +1 @@ +_instruments = ("groq >= 0.6.0",) diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/patch.py b/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/patch.py new file mode 100644 index 000000000..a5c5db21d --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/patch.py @@ -0,0 +1,156 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + + +import logging + +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) +from opentelemetry.semconv._incubating.attributes import ( + openai_attributes as OpenAIAttributes, +) +from opentelemetry.util.genai.handler import TelemetryHandler +from opentelemetry.util.genai.invocation import ( + InferenceInvocation, +) +from opentelemetry.util.genai.types import ( + Error, +) + +from .chat_wrappers import AsyncChatStreamWrapper, ChatStreamWrapper +from .utils import ( + _prepare_output_messages, + create_chat_invocation, + is_streaming, +) + +_logger = logging.getLogger(__name__) + + +def chat_completions_create_v_new( + handler: TelemetryHandler, +): + """Wrap the `create` method of the `ChatCompletion` class to trace it.""" + capture_content = handler.should_capture_content() + + def traced_method(wrapped, instance, args, kwargs): + chat_invocation = create_chat_invocation( + handler, kwargs, instance, capture_content=capture_content + ) + + try: + result = wrapped(*args, **kwargs) + if hasattr(result, "parse"): + # result is of type LegacyAPIResponse, call parse to get the actual response + parsed_result = result.parse() + else: + parsed_result = result + if is_streaming(kwargs): + return ChatStreamWrapper( + parsed_result, chat_invocation, capture_content + ) + + _set_response_properties( + chat_invocation, parsed_result, capture_content + ) + chat_invocation.stop() + return result + except Exception as error: + chat_invocation.fail(Error(type=type(error), message=str(error))) + raise + + return traced_method + + +def async_chat_completions_create_v_new( + handler: TelemetryHandler, +): + """Wrap the `create` method of the `AsyncChatCompletion` class to trace it.""" + capture_content = handler.should_capture_content() + + async def traced_method(wrapped, instance, args, kwargs): + chat_invocation = create_chat_invocation( + handler, kwargs, instance, capture_content=capture_content + ) + + try: + result = await wrapped(*args, **kwargs) + if hasattr(result, "parse"): + # result is of type LegacyAPIResponse, calling parse to get the actual response + parsed_result = result.parse() + else: + parsed_result = result + if is_streaming(kwargs): + return AsyncChatStreamWrapper( + parsed_result, chat_invocation, capture_content + ) + + _set_response_properties( + chat_invocation, parsed_result, capture_content + ) + chat_invocation.stop() + return result + + except Exception as error: + chat_invocation.fail(Error(type=type(error), message=str(error))) + raise + + return traced_method + + +def _set_response_properties( + chat_invocation: InferenceInvocation, result, capture_content: bool +) -> InferenceInvocation: + if getattr(result, "model", None): + chat_invocation.response_model_name = result.model + + if getattr(result, "choices", None): + finish_reasons = [] + for choice in result.choices: + finish_reasons.append(choice.finish_reason or "error") + + chat_invocation.finish_reasons = finish_reasons + + if capture_content: # optimization + chat_invocation.output_messages = _prepare_output_messages( + result.choices + ) + + if getattr(result, "id", None): + chat_invocation.response_id = result.id + + if getattr(result, "service_tier", None): + chat_invocation.attributes.update( + { + OpenAIAttributes.OPENAI_RESPONSE_SERVICE_TIER: result.service_tier + }, + ) + chat_invocation.metric_attributes.update( + { + OpenAIAttributes.OPENAI_RESPONSE_SERVICE_TIER: result.service_tier + }, + ) + + if getattr(result, "usage", None): + chat_invocation.input_tokens = result.usage.prompt_tokens + chat_invocation.output_tokens = result.usage.completion_tokens + elif getattr(result, "x_groq", None): + usage = getattr(result.x_groq, "usage", None) + if usage: + chat_invocation.input_tokens = getattr(usage, "prompt_tokens", None) + chat_invocation.output_tokens = getattr(usage, "completion_tokens", None) + + if getattr(result, "system_fingerprint", None): + chat_invocation.attributes.update( + { + OpenAIAttributes.OPENAI_RESPONSE_SYSTEM_FINGERPRINT: result.system_fingerprint + }, + ) + chat_invocation.metric_attributes.update( + { + OpenAIAttributes.OPENAI_RESPONSE_SYSTEM_FINGERPRINT: result.system_fingerprint + }, + ) + + return chat_invocation diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/utils.py b/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/utils.py new file mode 100644 index 000000000..d503dba36 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/utils.py @@ -0,0 +1,257 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +from __future__ import annotations + +import json +from typing import Any, Iterable, List, Mapping +from urllib.parse import urlparse + +import groq +from httpx import URL +from groq import NotGiven + +from opentelemetry.semconv._incubating.attributes import ( + gen_ai_attributes as GenAIAttributes, +) +from opentelemetry.semconv._incubating.attributes import ( + openai_attributes as OpenAIAttributes, +) +from opentelemetry.util.genai.handler import TelemetryHandler +from opentelemetry.util.genai.invocation import ( + InferenceInvocation, +) +from opentelemetry.util.genai.types import ( + FunctionToolDefinition, + InputMessage, + OutputMessage, + Text, + ToolCallRequest, + ToolCallResponse, + ToolDefinition, +) + +_GroqOmit = getattr(groq, "Omit", None) + + +def get_property_value(obj, property_name): + if isinstance(obj, dict): + return obj.get(property_name, None) + + return getattr(obj, property_name, None) + + +def get_server_address_and_port( + client_instance, +) -> tuple[str | None, int | None]: + base_client = getattr(client_instance, "_client", None) + base_url = getattr(base_client, "base_url", None) + if not base_url: + return None, None + address = None + port = None + if isinstance(base_url, URL): + address = base_url.host + port = base_url.port + elif isinstance(base_url, str): + url = urlparse(base_url) + address = url.hostname + port = url.port + + if port == 443: + port = None + + return address, port + + +def is_streaming(kwargs): + return non_numerical_value_is_set(kwargs.get("stream")) + + +def non_numerical_value_is_set(value: bool | str | NotGiven | None): + return bool(value) and value_is_set(value) + + +def value_is_set(value): + if _GroqOmit is not None and isinstance(value, _GroqOmit): + return False + return value is not None and not isinstance(value, NotGiven) + + +def _openai_response_format_to_output_type(response_format_type: str) -> str: + if response_format_type in ("json_object", "json_schema"): + return GenAIAttributes.GenAiOutputTypeValues.JSON.value + return response_format_type + + +def create_chat_invocation( + handler: TelemetryHandler, + kwargs, + client_instance, + capture_content: bool, +) -> InferenceInvocation: + # pylint: disable=too-many-branches + + address, port = get_server_address_and_port(client_instance) + invocation = handler.inference( + "groq", + request_model=kwargs.get("model", ""), + server_address=address if address else None, + server_port=port if port else None, + ) + invocation.temperature = get_value(kwargs.get("temperature")) + invocation.top_p = get_value(kwargs.get("p") or kwargs.get("top_p")) + invocation.max_tokens = get_value(kwargs.get("max_tokens")) + invocation.presence_penalty = get_value(kwargs.get("presence_penalty")) + invocation.frequency_penalty = get_value(kwargs.get("frequency_penalty")) + invocation.seed = get_value(kwargs.get("seed")) + if (stop_sequences := get_value(kwargs.get("stop"))) is not None: + if isinstance(stop_sequences, str): + stop_sequences = [stop_sequences] + invocation.stop_sequences = stop_sequences + + if (choice_count := get_value(kwargs.get("n"))) is not None: + # Only add non default, meaningful values + if isinstance(choice_count, int) and choice_count != 1: + invocation.request_choice_count = choice_count + + if ( + response_format := get_value(kwargs.get("response_format")) + ) is not None: + if isinstance(response_format, type): + invocation.attributes[GenAIAttributes.GEN_AI_OUTPUT_TYPE] = ( + GenAIAttributes.GenAiOutputTypeValues.JSON.value + ) + elif isinstance(response_format, Mapping): + if ( + response_format_type := get_value(response_format.get("type")) + ) is not None: + invocation.attributes[GenAIAttributes.GEN_AI_OUTPUT_TYPE] = ( + _openai_response_format_to_output_type( + response_format_type + ) + ) + elif isinstance(response_format, str): + invocation.attributes[GenAIAttributes.GEN_AI_OUTPUT_TYPE] = ( + _openai_response_format_to_output_type(response_format) + ) + + if capture_content: # optimization + invocation.input_messages = _prepare_input_messages( + kwargs.get("messages", []) + ) + invocation.tool_definitions = _prepare_tool_definitions( + kwargs.get("tools") + ) + return invocation + + +def get_value(v: Any): + if value_is_set(v): + return v + return None + + +def _is_text_part(content: Any) -> bool: + return isinstance(content, str) or ( + isinstance(content, Iterable) + and all(isinstance(part, str) for part in content) + ) + + +def _prepare_input_messages(messages) -> List[InputMessage]: + chat_messages = [] + for message in messages: + role = get_property_value(message, "role") + chat_message = InputMessage(role=str(role), parts=[]) + chat_messages.append(chat_message) + + content = get_property_value(message, "content") + + if role == "assistant": + tool_calls = get_property_value(message, "tool_calls") + if tool_calls: + chat_message.parts += extract_tool_calls_new(tool_calls) + if _is_text_part(content): + chat_message.parts.append(Text(content=str(content))) + + elif role == "tool": + tool_call_id = get_property_value(message, "tool_call_id") + chat_message.parts.append( + ToolCallResponse(id=tool_call_id, response=content) + ) + + else: + # system, developer, user, fallback + if _is_text_part(content): + chat_message.parts.append(Text(content=str(content))) + return chat_messages + + +def extract_tool_calls_new(tool_calls) -> list[ToolCallRequest]: + parts = [] + for tool_call in tool_calls: + call_id = get_property_value(tool_call, "id") + + func_name = "" + arguments = None + func = get_property_value(tool_call, "function") + if func: + func_name = get_property_value(func, "name") or "" + arguments_str = get_property_value(func, "arguments") + if arguments_str: + try: + arguments = json.loads(arguments_str) + except json.JSONDecodeError: + arguments = arguments_str + + parts.append( + ToolCallRequest(id=call_id, name=func_name, arguments=arguments) + ) + return parts + + +def _prepare_tool_definitions(tools) -> list[ToolDefinition] | None: + if not tools: + return None + + definitions: list[ToolDefinition] = [] + for tool in tools: + tool_type = get_property_value(tool, "type") + if tool_type == "function": + func = get_property_value(tool, "function") + if func: + definitions.append( + FunctionToolDefinition( + name=get_property_value(func, "name") or "", + description=get_property_value(func, "description"), + parameters=get_property_value(func, "parameters"), + ) + ) + return definitions + + +def _prepare_output_messages(choices) -> List[OutputMessage]: + output_messages = [] + for choice in choices: + if choice.message: + parts = [] + tool_calls = get_property_value(choice.message, "tool_calls") + if tool_calls: + parts += extract_tool_calls_new(tool_calls) + content = get_property_value(choice.message, "content") + if _is_text_part(content): + parts.append(Text(content=str(content))) + + message = OutputMessage( + finish_reason=choice.finish_reason or "error", + role=( + choice.message.role + if choice.message and choice.message.role + else "" + ), + parts=parts, + ) + output_messages.append(message) + + return output_messages diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/version.py b/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/version.py new file mode 100644 index 000000000..e7bf4a48e --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/version.py @@ -0,0 +1,15 @@ +# Copyright The OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +__version__ = "0.1b0.dev" diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/tests/__init__.py b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/__init__.py new file mode 100644 index 000000000..e57cf4aba --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/__init__.py @@ -0,0 +1,2 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/tests/cassettes/inference_conformance.yaml b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/cassettes/inference_conformance.yaml new file mode 100644 index 000000000..8b49345b1 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/cassettes/inference_conformance.yaml @@ -0,0 +1,48 @@ +interactions: +- request: + body: '{"messages":[{"role":"user","content":"Say this is a test"}],"model":"llama3-8b-8192","stream":false}' + headers: + authorization: + - Bearer test_groq_api_key + content-type: + - application/json + method: POST + uri: https://api.groq.com/openai/v1/chat/completions + response: + body: + string: |- + { + "id": "chatcmpl-12345", + "object": "chat.completion", + "created": 1731368630, + "model": "llama3-8b-8192", + "choices": [ + { + "index": 0, + "message": { + "role": "assistant", + "content": "This is a test." + }, + "logprobs": null, + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 12, + "completion_tokens": 14, + "total_tokens": 26 + }, + "x_groq": { + "usage": { + "prompt_tokens": 12, + "completion_tokens": 14 + } + } + } + headers: + Content-Type: + - application/json + status: + code: 200 + message: OK +version: 1 diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/tests/cassettes/test_chat_completions_basic.yaml b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/cassettes/test_chat_completions_basic.yaml new file mode 100644 index 000000000..f03abb0ae --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/cassettes/test_chat_completions_basic.yaml @@ -0,0 +1,48 @@ +interactions: +- request: + body: '{"messages":[{"role":"user","content":"Tell me a joke"}],"model":"llama3-8b-8192"}' + headers: + authorization: + - Bearer test_groq_api_key + content-type: + - application/json + method: POST + uri: https://api.groq.com/openai/v1/chat/completions + response: + body: + string: |- + { + "id": "chatcmpl-12345", + "object": "chat.completion", + "created": 1731368630, + "model": "llama3-8b-8192", + "choices": [ + { + "index": 0, + "message": { + "role": "assistant", + "content": "Why did the chicken cross the road? To get to the other side." + }, + "logprobs": null, + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 12, + "completion_tokens": 14, + "total_tokens": 26 + }, + "x_groq": { + "usage": { + "prompt_tokens": 12, + "completion_tokens": 14 + } + } + } + headers: + Content-Type: + - application/json + status: + code: 200 + message: OK +version: 1 diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/tests/conformance/__init__.py b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/conformance/__init__.py new file mode 100644 index 000000000..e57cf4aba --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/conformance/__init__.py @@ -0,0 +1,2 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/tests/conformance/inference.py b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/conformance/inference.py new file mode 100644 index 000000000..7cf846962 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/conformance/inference.py @@ -0,0 +1,49 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +"""Conformance scenario: groq chat completion (inference).""" + +from __future__ import annotations + +from typing import Any + +from groq import Groq + +from opentelemetry.instrumentation.genai.groq import GroqInstrumentor +from opentelemetry.sdk._logs import LoggerProvider +from opentelemetry.sdk.metrics import MeterProvider +from opentelemetry.sdk.trace import TracerProvider +from opentelemetry.test_util_genai.conformance import Scenario +from opentelemetry.test_util_genai.instrumentor import instrument + + +class InferenceScenario(Scenario): + expected_spans = {"chat": 1} + expected_metrics = ( + "gen_ai.client.operation.duration", + "gen_ai.client.token.usage", + ) + + def run( + self, + *, + tracer_provider: TracerProvider, + meter_provider: MeterProvider, + logger_provider: LoggerProvider, + vcr: Any, + ) -> None: + with instrument( + GroqInstrumentor(), + tracer_provider=tracer_provider, + logger_provider=logger_provider, + meter_provider=meter_provider, + content_capture="SPAN_ONLY", + ): + with vcr.use_cassette("inference_conformance.yaml"): + Groq().chat.completions.create( + messages=[ + {"role": "user", "content": "Say this is a test"} + ], + model="llama3-8b-8192", + stream=False, + ) diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/tests/conftest.py b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/conftest.py new file mode 100644 index 000000000..1b2dcd627 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/conftest.py @@ -0,0 +1,128 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +"""Unit tests configuration module.""" + +import os + +import pytest +from groq import AsyncGroq, Groq + +from opentelemetry.instrumentation.genai.groq import GroqInstrumentor +from opentelemetry.sdk.trace import TracerProvider +from opentelemetry.sdk.trace.export import SimpleSpanProcessor +from opentelemetry.sdk.trace.sampling import ALWAYS_OFF +from opentelemetry.test_util_genai.instrumentor import instrument + +pytest_plugins = [ + "opentelemetry.test_util_genai.fixtures", + "opentelemetry.test_util_genai.vcr", +] + + +@pytest.fixture(autouse=True) +def environment(): + if not os.getenv("GROQ_API_KEY"): + os.environ["GROQ_API_KEY"] = "test_groq_api_key" + + +@pytest.fixture +def groq_client(): + return Groq() + + +@pytest.fixture +def async_groq_client(): + return AsyncGroq() + + +@pytest.fixture(scope="module") +def vcr_config(): + from opentelemetry.test_util_genai.vcr import ( # noqa: PLC0415 + scrub_response_headers_overwrite, + ) + + return { + "filter_headers": [ + ("cookie", "test_cookie"), + ("authorization", "Bearer test_groq_api_key"), + ], + "decode_compressed_response": True, + "before_record_response": scrub_response_headers_overwrite( + { + "Set-Cookie": "test_set_cookie", + } + ), + } + + +@pytest.fixture( + scope="function", + params=[(True, "span_only")], + name="content_mode", +) +def fixture_content_mode(request): + # returns tuple: (latest_experimental_enabled: bool, content_mode: str) + # we don't test (True, "event_only"), (True, "span_and_event") because it's util's + # responsibility. + return request.param + + +@pytest.fixture(scope="function") +def instrument_no_content( + tracer_provider, + logger_provider, + meter_provider, + content_mode, +): + with instrument( + GroqInstrumentor(), + tracer_provider=tracer_provider, + logger_provider=logger_provider, + meter_provider=meter_provider, + ) as instrumentor: + yield instrumentor + + +@pytest.fixture(scope="function") +def instrument_with_content( + tracer_provider, logger_provider, meter_provider, content_mode +): + _, content_mode_value = content_mode + with instrument( + GroqInstrumentor(), + tracer_provider=tracer_provider, + logger_provider=logger_provider, + meter_provider=meter_provider, + content_capture=content_mode_value, + ) as instrumentor: + yield instrumentor + + +@pytest.fixture(scope="function") +def instrument_with_content_unsampled( + span_exporter, logger_provider, meter_provider, content_mode +): + _, content_mode_value = content_mode + tracer_provider = TracerProvider(sampler=ALWAYS_OFF) + tracer_provider.add_span_processor(SimpleSpanProcessor(span_exporter)) + with instrument( + GroqInstrumentor(), + tracer_provider=tracer_provider, + logger_provider=logger_provider, + meter_provider=meter_provider, + content_capture=content_mode_value, + ) as instrumentor: + yield instrumentor + + +@pytest.fixture(scope="function") +def instrument_event_only(tracer_provider, logger_provider, meter_provider): + with instrument( + GroqInstrumentor(), + tracer_provider=tracer_provider, + logger_provider=logger_provider, + meter_provider=meter_provider, + content_capture="event_only", + ) as instrumentor: + yield instrumentor diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/tests/requirements.latest.txt b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/requirements.latest.txt new file mode 100644 index 000000000..30c82b330 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/requirements.latest.txt @@ -0,0 +1 @@ +groq diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/tests/requirements.oldest.txt b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/requirements.oldest.txt new file mode 100644 index 000000000..800a50178 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/requirements.oldest.txt @@ -0,0 +1 @@ +groq==0.6.0 diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/tests/test_chat_completions.py b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/test_chat_completions.py new file mode 100644 index 000000000..d457c848b --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/test_chat_completions.py @@ -0,0 +1,38 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +import pytest +from opentelemetry.semconv._incubating.attributes.gen_ai_attributes import ( + GEN_AI_OPERATION_NAME, + GEN_AI_REQUEST_MODEL, + GEN_AI_SYSTEM, + GenAiOperationNameValues, + GenAiSystemValues, +) +from groq import Groq + + +@pytest.mark.vcr +def test_chat_completions_basic( + instrument_no_content, + span_exporter, + vcr, + groq_client: Groq, +): + with vcr.use_cassette("test_chat_completions_basic.yaml"): + response = groq_client.chat.completions.create( + model="llama3-8b-8192", + messages=[ + {"role": "user", "content": "Tell me a joke"}, + ], + ) + + assert response is not None + spans = span_exporter.get_finished_spans() + assert len(spans) == 1 + span = spans[0] + + assert span.attributes.get(GEN_AI_SYSTEM) == "groq" or span.attributes.get("gen_ai.provider.name") == "groq" + assert span.attributes.get(GEN_AI_OPERATION_NAME) == GenAiOperationNameValues.CHAT.value + assert span.attributes[GEN_AI_REQUEST_MODEL] == "llama3-8b-8192" + assert "gen_ai.response.model" in span.attributes diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/tests/test_conformance.py b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/test_conformance.py new file mode 100644 index 000000000..c84b975b9 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/test_conformance.py @@ -0,0 +1,34 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +"""Per-scenario conformance tests for groq.""" + +from __future__ import annotations + +from typing import Any + +import pytest + +# Skip collection when weaver_live_check isn't installed (non-conformance envs). +pytest.importorskip("opentelemetry.test.weaver_live_check") + +from opentelemetry.test.weaver_live_check import WeaverLiveCheck # noqa: E402 +from opentelemetry.test_util_genai.conformance import ( # noqa: E402 + Scenario, + run_conformance, +) + +from .conformance.inference import InferenceScenario + + +@pytest.mark.parametrize( + "scenario", + [ + InferenceScenario(), + ], + ids=lambda s: type(s).__name__, +) +def test_conformance( + scenario: Scenario, vcr: Any, weaver_live_check: WeaverLiveCheck +) -> None: + run_conformance(scenario, vcr=vcr, weaver=weaver_live_check) diff --git a/pyproject.toml b/pyproject.toml index c20a511db..393cd0811 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -99,6 +99,7 @@ include = [ "instrumentation/opentelemetry-instrumentation-genai-agno", "instrumentation/opentelemetry-instrumentation-genai-anthropic", "instrumentation/opentelemetry-instrumentation-genai-claude-agent-sdk", + "instrumentation/opentelemetry-instrumentation-genai-langchain", "instrumentation/opentelemetry-instrumentation-genai-openai-agents", "instrumentation/opentelemetry-instrumentation-genai-weaviate-client", @@ -113,6 +114,7 @@ exclude = [ "instrumentation/opentelemetry-instrumentation-genai-anthropic/examples/**/*.py", "instrumentation/opentelemetry-instrumentation-genai-claude-agent-sdk/tests/**/*.py", "instrumentation/opentelemetry-instrumentation-genai-claude-agent-sdk/examples/**/*.py", + "instrumentation/opentelemetry-instrumentation-genai-langchain/tests/**/*.py", "instrumentation/opentelemetry-instrumentation-genai-langchain/examples/**/*.py", "instrumentation/opentelemetry-instrumentation-genai-openai-agents/tests/**/*.py", diff --git a/tox.ini b/tox.ini index a66f45c21..2fbfceff7 100644 --- a/tox.ini +++ b/tox.ini @@ -42,6 +42,12 @@ envlist = py314-test-instrumentation-genai-anthropic-conformance lint-instrumentation-genai-anthropic + ; instrumentation-genai-groq + py3{10,11,12,13,14}-test-instrumentation-genai-groq-latest + py310-test-instrumentation-genai-groq-oldest + py314-test-instrumentation-genai-groq-conformance + lint-instrumentation-genai-groq + ; instrumentation-genai-claude-agent-sdk py3{10,11,12,13}-test-instrumentation-genai-claude-agent-sdk-latest py310-test-instrumentation-genai-claude-agent-sdk-oldest @@ -137,6 +143,17 @@ deps = anthropic-conformance: {[testenv]pytest_deps} anthropic-conformance: -r {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-anthropic/tests/requirements.latest.txt + groq-oldest: {[testenv]pytest_deps} + groq-oldest: -e {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-groq[instruments] + groq-oldest: -r {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-groq/tests/requirements.oldest.txt + groq-latest: {[testenv]test_deps} + groq-latest: {[testenv]pytest_deps} + groq-latest: -e {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-groq[instruments] + groq-latest: -r {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-groq/tests/requirements.latest.txt + groq-conformance: {[testenv]pytest_deps} + groq-conformance: -e {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-groq[instruments] + groq-conformance: -r {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-groq/tests/requirements.latest.txt + claude-agent-sdk-oldest: {[testenv]pytest_deps} claude-agent-sdk-oldest: -e {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-claude-agent-sdk[instruments] claude-agent-sdk-oldest: -r {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-claude-agent-sdk/tests/requirements.oldest.txt @@ -205,6 +222,10 @@ commands = test-instrumentation-genai-anthropic-conformance: pytest {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-anthropic/tests/test_conformance.py --vcr-record=none {posargs} lint-instrumentation-genai-anthropic: sh -c "cd instrumentation && ruff check opentelemetry-instrumentation-genai-anthropic" + test-instrumentation-genai-groq-{oldest,latest}: pytest --ignore={toxinidir}/instrumentation/opentelemetry-instrumentation-genai-groq/tests/test_conformance.py {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-groq/tests {posargs} + test-instrumentation-genai-groq-conformance: pytest {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-groq/tests/test_conformance.py --vcr-record=none {posargs} + lint-instrumentation-genai-groq: sh -c "cd instrumentation && ruff check opentelemetry-instrumentation-genai-groq" + test-instrumentation-genai-claude-agent-sdk: pytest {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-claude-agent-sdk/tests --vcr-record=none {posargs} lint-instrumentation-genai-claude-agent-sdk: sh -c "cd instrumentation && ruff check opentelemetry-instrumentation-genai-claude-agent-sdk" @@ -300,6 +321,7 @@ deps = -e {toxinidir}/instrumentation/opentelemetry-instrumentation-google-genai[instruments] -e {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-agno[instruments] -e {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-anthropic[instruments] + -e {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-groq[instruments] -e {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-langchain[instruments] -e {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-claude-agent-sdk[instruments] -e {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-openai-agents[instruments] diff --git a/uv.lock b/uv.lock index c157a7cce..5c4b85cd2 100644 --- a/uv.lock +++ b/uv.lock @@ -15,6 +15,7 @@ members = [ "opentelemetry-instrumentation-genai-agno", "opentelemetry-instrumentation-genai-anthropic", "opentelemetry-instrumentation-genai-claude-agent-sdk", + "opentelemetry-instrumentation-genai-groq", "opentelemetry-instrumentation-genai-langchain", "opentelemetry-instrumentation-genai-openai", "opentelemetry-instrumentation-genai-openai-agents", @@ -499,7 +500,7 @@ name = "exceptiongroup" version = "1.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } wheels = [ @@ -572,6 +573,23 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e4/d3/5268aeabf2ad82658c4e2ff3a060648d0f02f3926cb53247c0e4d0dab49e/griffelib-2.1.0-py3-none-any.whl", hash = "sha256:cc7b3d2d2865ad0b909fcc38086e3f554b5ea7acbaa7bbb7ecaa3f5dfb7d9f00", size = 142560, upload-time = "2026-06-19T12:05:38.742Z" }, ] +[[package]] +name = "groq" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "distro" }, + { name = "httpx" }, + { name = "pydantic" }, + { name = "sniffio" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/67/3e/687064918e861082cb02165872bbda31269126a108a78794dae86ddadae2/groq-1.6.0.tar.gz", hash = "sha256:c4237ecf0053ba85fd926bb31cb4b178996310474b4618867994e3e40d8e3c02", size = 158424, upload-time = "2026-07-24T17:25:49.517Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/40/164338d796cf41ea5930a42023e986d8c993720bed670d5aa143e5854873/groq-1.6.0-py3-none-any.whl", hash = "sha256:fa16db582455db324adcff1b5908519474736872e28cd5c8fa2b8bef6860e12a", size = 143693, upload-time = "2026-07-24T17:25:48.2Z" }, +] + [[package]] name = "grpcio" version = "1.78.0" @@ -1323,6 +1341,31 @@ requires-dist = [ ] provides-extras = ["instruments"] +[[package]] +name = "opentelemetry-instrumentation-genai-groq" +source = { editable = "instrumentation/opentelemetry-instrumentation-genai-groq" } +dependencies = [ + { name = "opentelemetry-api" }, + { name = "opentelemetry-instrumentation" }, + { name = "opentelemetry-semantic-conventions" }, + { name = "opentelemetry-util-genai" }, +] + +[package.optional-dependencies] +instruments = [ + { name = "groq" }, +] + +[package.metadata] +requires-dist = [ + { name = "groq", marker = "extra == 'instruments'", specifier = ">=0.6.0" }, + { name = "opentelemetry-api", specifier = "~=1.43" }, + { name = "opentelemetry-instrumentation", specifier = ">=0.64b0,<1" }, + { name = "opentelemetry-semantic-conventions", specifier = ">=0.64b0,<1" }, + { name = "opentelemetry-util-genai", editable = "util/opentelemetry-util-genai" }, +] +provides-extras = ["instruments"] + [[package]] name = "opentelemetry-instrumentation-genai-langchain" source = { editable = "instrumentation/opentelemetry-instrumentation-genai-langchain" } From a2c889ac4a3da16b272f2c656706c8e81ab516f8 Mon Sep 17 00:00:00 2001 From: Rishita Date: Sun, 2 Aug 2026 01:08:36 +0530 Subject: [PATCH 2/8] chore: address review feedback and add streaming test coverage - Remove unused imports to satisfy ruff - Use GEN_AI_RESPONSE_MODEL semconv constant - Add VCR cassettes and mock iteration for streaming and error scenarios tests - Fix environment variable names in examples Assisted-by: Antigravity 2.0 --- .../examples/manual/.env | 6 +- .../examples/manual/main.py | 2 +- .../genai/groq/chat_wrappers.py | 10 +- .../instrumentation/genai/groq/patch.py | 14 +- .../instrumentation/genai/groq/utils.py | 5 +- .../instrumentation/genai/groq/version.py | 2 +- .../test_async_chat_completions_basic.yaml | 21 +++ ...test_async_chat_completions_streaming.yaml | 27 +++ ...st_chat_completions_caller_side_error.yaml | 27 +++ .../test_chat_completions_provider_error.yaml | 93 +++++++++ ...st_chat_completions_stream_side_error.yaml | 27 +++ .../test_chat_completions_streaming.yaml | 27 +++ .../tests/test_chat_completions.py | 178 +++++++++++++++++- 13 files changed, 409 insertions(+), 30 deletions(-) create mode 100644 instrumentation/opentelemetry-instrumentation-genai-groq/tests/cassettes/test_async_chat_completions_basic.yaml create mode 100644 instrumentation/opentelemetry-instrumentation-genai-groq/tests/cassettes/test_async_chat_completions_streaming.yaml create mode 100644 instrumentation/opentelemetry-instrumentation-genai-groq/tests/cassettes/test_chat_completions_caller_side_error.yaml create mode 100644 instrumentation/opentelemetry-instrumentation-genai-groq/tests/cassettes/test_chat_completions_provider_error.yaml create mode 100644 instrumentation/opentelemetry-instrumentation-genai-groq/tests/cassettes/test_chat_completions_stream_side_error.yaml create mode 100644 instrumentation/opentelemetry-instrumentation-genai-groq/tests/cassettes/test_chat_completions_streaming.yaml diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/examples/manual/.env b/instrumentation/opentelemetry-instrumentation-genai-groq/examples/manual/.env index 7a0e0608d..28cc4d645 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-groq/examples/manual/.env +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/examples/manual/.env @@ -2,15 +2,15 @@ GROQ_API_KEY=sk-YOUR_API_KEY # Uncomment to use Ollama instead of Groq -# OPENAI_BASE_URL=http://localhost:11434/v1 -# OPENAI_API_KEY=unused +# GROQ_BASE_URL=http://localhost:11434/v1 +# GROQ_API_KEY=unused # CHAT_MODEL=qwen2.5:0.5b # Uncomment and change to your OTLP endpoint # OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317 # OTEL_EXPORTER_OTLP_PROTOCOL=grpc -OTEL_SERVICE_NAME=opentelemetry-python-openai +OTEL_SERVICE_NAME=opentelemetry-python-groq # Remove to hide prompt and completion content # Possible values (case insensitive): diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/examples/manual/main.py b/instrumentation/opentelemetry-instrumentation-genai-groq/examples/manual/main.py index 53d0b9334..69f5485c0 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-groq/examples/manual/main.py +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/examples/manual/main.py @@ -48,7 +48,7 @@ ) ) -# instrument OpenAI +# instrument Groq GroqInstrumentor().instrument() diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/chat_wrappers.py b/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/chat_wrappers.py index 299fc5554..bd0e193d7 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/chat_wrappers.py +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/chat_wrappers.py @@ -4,7 +4,7 @@ from __future__ import annotations import json -from typing import Optional, Any +from typing import Any, Optional from opentelemetry.semconv._incubating.attributes import ( openai_attributes as OpenAIAttributes, @@ -87,8 +87,12 @@ def _build_streaming_response(self, chunk: Any) -> None: def _set_usage(self, chunk: Any) -> None: usage = getattr(chunk, "x_groq", None) if usage and getattr(usage, "usage", None): - self._self_completion_tokens = getattr(usage.usage, "completion_tokens", None) - self._self_prompt_tokens = getattr(usage.usage, "prompt_tokens", None) + self._self_completion_tokens = getattr( + usage.usage, "completion_tokens", None + ) + self._self_prompt_tokens = getattr( + usage.usage, "prompt_tokens", None + ) def _process_chunk(self, chunk: Any) -> None: self._set_response_id(chunk) diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/patch.py b/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/patch.py index a5c5db21d..2f478cbe9 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/patch.py +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/patch.py @@ -4,12 +4,6 @@ import logging -from opentelemetry.semconv._incubating.attributes import ( - gen_ai_attributes as GenAIAttributes, -) -from opentelemetry.semconv._incubating.attributes import ( - openai_attributes as OpenAIAttributes, -) from opentelemetry.util.genai.handler import TelemetryHandler from opentelemetry.util.genai.invocation import ( InferenceInvocation, @@ -138,8 +132,12 @@ def _set_response_properties( elif getattr(result, "x_groq", None): usage = getattr(result.x_groq, "usage", None) if usage: - chat_invocation.input_tokens = getattr(usage, "prompt_tokens", None) - chat_invocation.output_tokens = getattr(usage, "completion_tokens", None) + chat_invocation.input_tokens = getattr( + usage, "prompt_tokens", None + ) + chat_invocation.output_tokens = getattr( + usage, "completion_tokens", None + ) if getattr(result, "system_fingerprint", None): chat_invocation.attributes.update( diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/utils.py b/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/utils.py index d503dba36..fea7281aa 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/utils.py +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/utils.py @@ -8,15 +8,12 @@ from urllib.parse import urlparse import groq -from httpx import URL from groq import NotGiven +from httpx import URL from opentelemetry.semconv._incubating.attributes import ( gen_ai_attributes as GenAIAttributes, ) -from opentelemetry.semconv._incubating.attributes import ( - openai_attributes as OpenAIAttributes, -) from opentelemetry.util.genai.handler import TelemetryHandler from opentelemetry.util.genai.invocation import ( InferenceInvocation, diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/version.py b/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/version.py index e7bf4a48e..0062fad57 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/version.py +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/version.py @@ -12,4 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -__version__ = "0.1b0.dev" +__version__ = "1.0b0.dev" diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/tests/cassettes/test_async_chat_completions_basic.yaml b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/cassettes/test_async_chat_completions_basic.yaml new file mode 100644 index 000000000..d2ce4302b --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/cassettes/test_async_chat_completions_basic.yaml @@ -0,0 +1,21 @@ +# TODO: this is generated by AI, re-record +interactions: +- request: + body: '{"messages":[{"role":"user","content":"Tell me a joke"}],"model":"llama3-8b-8192"}' + headers: + accept: + - application/json + content-type: + - application/json + method: POST + uri: https://api.groq.com/openai/v1/chat/completions + response: + body: + string: '{"id":"chatcmpl-test","choices":[{"finish_reason":"stop","index":0,"message":{"content":"A joke!","role":"assistant"}}],"created":123,"model":"llama3-8b-8192","object":"chat.completion"}' + headers: + content-type: + - application/json + status: + code: 200 + message: OK +version: 1 diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/tests/cassettes/test_async_chat_completions_streaming.yaml b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/cassettes/test_async_chat_completions_streaming.yaml new file mode 100644 index 000000000..fef748b35 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/cassettes/test_async_chat_completions_streaming.yaml @@ -0,0 +1,27 @@ +# TODO: this is generated by AI, re-record +interactions: +- request: + body: '{"messages":[{"role":"user","content":"Tell me a joke"}],"model":"llama3-8b-8192","stream":true}' + headers: + accept: + - application/json + content-type: + - application/json + method: POST + uri: https://api.groq.com/openai/v1/chat/completions + response: + body: + string: 'data: {"id":"chatcmpl-test","choices":[{"delta":{"content":"A"},"index":0}],"created":123,"model":"llama3-8b-8192","object":"chat.completion.chunk"} + +data: {"id":"chatcmpl-test","choices":[{"delta":{},"finish_reason":"stop","index":0}],"created":123,"model":"llama3-8b-8192","object":"chat.completion.chunk"} + +data: [DONE] + +' + headers: + content-type: + - text/event-stream + status: + code: 200 + message: OK +version: 1 diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/tests/cassettes/test_chat_completions_caller_side_error.yaml b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/cassettes/test_chat_completions_caller_side_error.yaml new file mode 100644 index 000000000..1f9bba514 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/cassettes/test_chat_completions_caller_side_error.yaml @@ -0,0 +1,27 @@ +# TODO: this is generated by AI, re-record +interactions: +- request: + body: '{"messages":[{"role":"user","content":"Tell me a long joke"}],"model":"llama3-8b-8192","stream":true}' + headers: + accept: + - application/json + content-type: + - application/json + method: POST + uri: https://api.groq.com/openai/v1/chat/completions + response: + body: + string: 'data: {"id":"chatcmpl-test","choices":[{"delta":{"content":"A"},"index":0}],"created":123,"model":"llama3-8b-8192","object":"chat.completion.chunk"} + +data: {"id":"chatcmpl-test","choices":[{"delta":{"content":" long"},"index":0}],"created":123,"model":"llama3-8b-8192","object":"chat.completion.chunk"} + +data: [DONE] + +' + headers: + content-type: + - text/event-stream + status: + code: 200 + message: OK +version: 1 diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/tests/cassettes/test_chat_completions_provider_error.yaml b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/cassettes/test_chat_completions_provider_error.yaml new file mode 100644 index 000000000..b0b582c1c --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/cassettes/test_chat_completions_provider_error.yaml @@ -0,0 +1,93 @@ +interactions: +- request: + body: |- + { + "messages": [ + { + "role": "user", + "content": "Tell me a joke" + } + ], + "model": "non-existent-model" + } + headers: + accept: + - application/json + accept-encoding: + - gzip, deflate + authorization: + - Bearer test_groq_api_key + connection: + - keep-alive + content-length: + - '86' + content-type: + - application/json + host: + - api.groq.com + user-agent: + - Groq/Python 1.6.0 + x-stainless-arch: + - other:amd64 + x-stainless-async: + - 'false' + x-stainless-lang: + - python + x-stainless-os: + - Windows + x-stainless-package-version: + - 1.6.0 + x-stainless-read-timeout: + - '60' + x-stainless-retry-count: + - '0' + x-stainless-runtime: + - CPython + x-stainless-runtime-version: + - 3.12.13 + method: POST + uri: https://api.groq.com/openai/v1/chat/completions + response: + body: + string: |- + { + "error": { + "message": "Invalid API Key", + "type": "invalid_request_error", + "code": "invalid_api_key" + } + } + headers: + alt-svc: + - h3=":443"; ma=86400 + cache-control: + - private, max-age=0, no-store, no-cache, must-revalidate + cf-cache-status: + - DYNAMIC + cf-ray: + - a2471c7b281cb1c5-BOM + connection: + - keep-alive + content-length: + - '96' + content-type: + - application/json + date: + - Sat, 01 Aug 2026 19:04:54 GMT + server: + - cloudflare + set-cookie: test_set_cookie + strict-transport-security: + - max-age=15552000 + vary: + - Origin + via: + - 1.1 google + x-groq-region: + - bom + x-request-id: + - req_01kyzbe28dfpt959zxf99vxag3 + status: + code: 401 + message: Unauthorized +version: 1 diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/tests/cassettes/test_chat_completions_stream_side_error.yaml b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/cassettes/test_chat_completions_stream_side_error.yaml new file mode 100644 index 000000000..1f9bba514 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/cassettes/test_chat_completions_stream_side_error.yaml @@ -0,0 +1,27 @@ +# TODO: this is generated by AI, re-record +interactions: +- request: + body: '{"messages":[{"role":"user","content":"Tell me a long joke"}],"model":"llama3-8b-8192","stream":true}' + headers: + accept: + - application/json + content-type: + - application/json + method: POST + uri: https://api.groq.com/openai/v1/chat/completions + response: + body: + string: 'data: {"id":"chatcmpl-test","choices":[{"delta":{"content":"A"},"index":0}],"created":123,"model":"llama3-8b-8192","object":"chat.completion.chunk"} + +data: {"id":"chatcmpl-test","choices":[{"delta":{"content":" long"},"index":0}],"created":123,"model":"llama3-8b-8192","object":"chat.completion.chunk"} + +data: [DONE] + +' + headers: + content-type: + - text/event-stream + status: + code: 200 + message: OK +version: 1 diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/tests/cassettes/test_chat_completions_streaming.yaml b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/cassettes/test_chat_completions_streaming.yaml new file mode 100644 index 000000000..fef748b35 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/cassettes/test_chat_completions_streaming.yaml @@ -0,0 +1,27 @@ +# TODO: this is generated by AI, re-record +interactions: +- request: + body: '{"messages":[{"role":"user","content":"Tell me a joke"}],"model":"llama3-8b-8192","stream":true}' + headers: + accept: + - application/json + content-type: + - application/json + method: POST + uri: https://api.groq.com/openai/v1/chat/completions + response: + body: + string: 'data: {"id":"chatcmpl-test","choices":[{"delta":{"content":"A"},"index":0}],"created":123,"model":"llama3-8b-8192","object":"chat.completion.chunk"} + +data: {"id":"chatcmpl-test","choices":[{"delta":{},"finish_reason":"stop","index":0}],"created":123,"model":"llama3-8b-8192","object":"chat.completion.chunk"} + +data: [DONE] + +' + headers: + content-type: + - text/event-stream + status: + code: 200 + message: OK +version: 1 diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/tests/test_chat_completions.py b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/test_chat_completions.py index d457c848b..5ac948795 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-groq/tests/test_chat_completions.py +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/test_chat_completions.py @@ -2,14 +2,16 @@ # SPDX-License-Identifier: Apache-2.0 import pytest +from groq import AsyncGroq, Groq + from opentelemetry.semconv._incubating.attributes.gen_ai_attributes import ( GEN_AI_OPERATION_NAME, GEN_AI_REQUEST_MODEL, + GEN_AI_RESPONSE_MODEL, GEN_AI_SYSTEM, GenAiOperationNameValues, - GenAiSystemValues, ) -from groq import Groq +from opentelemetry.trace import StatusCode @pytest.mark.vcr @@ -21,18 +23,174 @@ def test_chat_completions_basic( ): with vcr.use_cassette("test_chat_completions_basic.yaml"): response = groq_client.chat.completions.create( - model="llama3-8b-8192", - messages=[ - {"role": "user", "content": "Tell me a joke"}, - ], - ) + model="llama3-8b-8192", + messages=[ + {"role": "user", "content": "Tell me a joke"}, + ], + ) assert response is not None spans = span_exporter.get_finished_spans() assert len(spans) == 1 span = spans[0] - assert span.attributes.get(GEN_AI_SYSTEM) == "groq" or span.attributes.get("gen_ai.provider.name") == "groq" - assert span.attributes.get(GEN_AI_OPERATION_NAME) == GenAiOperationNameValues.CHAT.value + assert ( + span.attributes.get(GEN_AI_SYSTEM) == "groq" + or span.attributes.get("gen_ai.provider.name") == "groq" + ) + assert ( + span.attributes.get(GEN_AI_OPERATION_NAME) + == GenAiOperationNameValues.CHAT.value + ) + assert span.attributes[GEN_AI_REQUEST_MODEL] == "llama3-8b-8192" + assert GEN_AI_RESPONSE_MODEL in span.attributes + + +@pytest.mark.vcr +@pytest.mark.asyncio +async def test_async_chat_completions_basic( + instrument_no_content, + span_exporter, + vcr, + async_groq_client: AsyncGroq, +): + with vcr.use_cassette("test_async_chat_completions_basic.yaml"): + response = await async_groq_client.chat.completions.create( + model="llama3-8b-8192", + messages=[{"role": "user", "content": "Tell me a joke"}], + ) + + assert response is not None + spans = span_exporter.get_finished_spans() + assert len(spans) == 1 + span = spans[0] + assert ( + span.attributes.get(GEN_AI_SYSTEM) == "groq" + or span.attributes.get("gen_ai.provider.name") == "groq" + ) + assert ( + span.attributes.get(GEN_AI_OPERATION_NAME) + == GenAiOperationNameValues.CHAT.value + ) assert span.attributes[GEN_AI_REQUEST_MODEL] == "llama3-8b-8192" - assert "gen_ai.response.model" in span.attributes + + +@pytest.mark.vcr +def test_chat_completions_streaming( + instrument_no_content, + span_exporter, + vcr, + groq_client: Groq, +): + with vcr.use_cassette("test_chat_completions_streaming.yaml"): + response = groq_client.chat.completions.create( + model="llama3-8b-8192", + messages=[{"role": "user", "content": "Tell me a joke"}], + stream=True, + ) + for _ in response: + pass + + spans = span_exporter.get_finished_spans() + assert len(spans) == 1 + span = spans[0] + assert ( + span.attributes.get(GEN_AI_SYSTEM) == "groq" + or span.attributes.get("gen_ai.provider.name") == "groq" + ) + + +@pytest.mark.vcr +@pytest.mark.asyncio +async def test_async_chat_completions_streaming( + instrument_no_content, + span_exporter, + vcr, + async_groq_client: AsyncGroq, +): + with vcr.use_cassette("test_async_chat_completions_streaming.yaml"): + response = await async_groq_client.chat.completions.create( + model="llama3-8b-8192", + messages=[{"role": "user", "content": "Tell me a joke"}], + stream=True, + ) + async for _ in response: + pass + + spans = span_exporter.get_finished_spans() + assert len(spans) == 1 + + +@pytest.mark.vcr +def test_chat_completions_provider_error( + instrument_no_content, + span_exporter, + vcr, + groq_client: Groq, +): + with vcr.use_cassette("test_chat_completions_provider_error.yaml"): + with pytest.raises(Exception): + groq_client.chat.completions.create( + model="non-existent-model", + messages=[{"role": "user", "content": "Tell me a joke"}], + ) + + spans = span_exporter.get_finished_spans() + assert len(spans) == 1 + span = spans[0] + assert span.status.status_code == StatusCode.ERROR + assert "error.type" in span.attributes + + +@pytest.mark.vcr +def test_chat_completions_caller_side_error_inside_stream( + instrument_no_content, + span_exporter, + vcr, + groq_client: Groq, +): + with vcr.use_cassette("test_chat_completions_caller_side_error.yaml"): + with pytest.raises(ValueError, match="Caller error"): + response = groq_client.chat.completions.create( + model="llama3-8b-8192", + messages=[{"role": "user", "content": "Tell me a long joke"}], + stream=True, + ) + with response: + raise ValueError("Caller error") + + spans = span_exporter.get_finished_spans() + assert len(spans) == 1 + span = spans[0] + assert span.status.status_code == StatusCode.ERROR + assert span.attributes.get("error.type") == "ValueError" + + +@pytest.mark.vcr +def test_chat_completions_stream_side_error_mid_iteration( + instrument_no_content, + span_exporter, + vcr, + groq_client: Groq, +): + with vcr.use_cassette("test_chat_completions_stream_side_error.yaml"): + response = groq_client.chat.completions.create( + model="llama3-8b-8192", + messages=[{"role": "user", "content": "Tell me a long joke"}], + stream=True, + ) + from unittest import mock + + iterator_mock = mock.MagicMock() + iterator_mock.__next__.side_effect = ConnectionError("Stream dropped") + response._self_iterator = iterator_mock + + with pytest.raises(ConnectionError, match="Stream dropped"): + for _ in response: + pass + + spans = span_exporter.get_finished_spans() + assert len(spans) == 1 + span = spans[0] + assert span.status.status_code == StatusCode.ERROR + assert span.attributes.get("error.type") == "ConnectionError" From 1a1afc4a6d82c6e3589d6eb3c610a43f16faecd1 Mon Sep 17 00:00:00 2001 From: Rishita Date: Sun, 2 Aug 2026 13:43:54 +0530 Subject: [PATCH 3/8] Fix copilot lint warnings, dependency pins, and add changelog --- .../.changelog/1234.added | 1 + .../instrumentation/genai/groq/patch.py | 24 ------------------ .../tests/requirements.latest.txt | 14 ++++++++++ .../tests/requirements.oldest.txt | 23 ++++++++++++++++- .../tests/test_chat_completions.py | 7 ++--- screenshots/photo_2026-07-27_03-17-43.jpg | Bin 0 -> 66992 bytes screenshots/photo_2026-07-27_03-17-48.jpg | Bin 0 -> 75248 bytes screenshots/photo_2026-07-27_03-17-55.jpg | Bin 0 -> 86379 bytes 8 files changed, 41 insertions(+), 28 deletions(-) create mode 100644 instrumentation/opentelemetry-instrumentation-genai-groq/.changelog/1234.added create mode 100644 screenshots/photo_2026-07-27_03-17-43.jpg create mode 100644 screenshots/photo_2026-07-27_03-17-48.jpg create mode 100644 screenshots/photo_2026-07-27_03-17-55.jpg diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/.changelog/1234.added b/instrumentation/opentelemetry-instrumentation-genai-groq/.changelog/1234.added new file mode 100644 index 000000000..09b94586d --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/.changelog/1234.added @@ -0,0 +1 @@ +Add Groq instrumentation diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/patch.py b/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/patch.py index 2f478cbe9..980586119 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/patch.py +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/patch.py @@ -114,18 +114,6 @@ def _set_response_properties( if getattr(result, "id", None): chat_invocation.response_id = result.id - if getattr(result, "service_tier", None): - chat_invocation.attributes.update( - { - OpenAIAttributes.OPENAI_RESPONSE_SERVICE_TIER: result.service_tier - }, - ) - chat_invocation.metric_attributes.update( - { - OpenAIAttributes.OPENAI_RESPONSE_SERVICE_TIER: result.service_tier - }, - ) - if getattr(result, "usage", None): chat_invocation.input_tokens = result.usage.prompt_tokens chat_invocation.output_tokens = result.usage.completion_tokens @@ -139,16 +127,4 @@ def _set_response_properties( usage, "completion_tokens", None ) - if getattr(result, "system_fingerprint", None): - chat_invocation.attributes.update( - { - OpenAIAttributes.OPENAI_RESPONSE_SYSTEM_FINGERPRINT: result.system_fingerprint - }, - ) - chat_invocation.metric_attributes.update( - { - OpenAIAttributes.OPENAI_RESPONSE_SYSTEM_FINGERPRINT: result.system_fingerprint - }, - ) - return chat_invocation diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/tests/requirements.latest.txt b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/requirements.latest.txt index 30c82b330..6151caf32 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-groq/tests/requirements.latest.txt +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/requirements.latest.txt @@ -1 +1,15 @@ +# Copyright The OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + groq diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/tests/requirements.oldest.txt b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/requirements.oldest.txt index 800a50178..3af852be6 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-groq/tests/requirements.oldest.txt +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/requirements.oldest.txt @@ -1 +1,22 @@ -groq==0.6.0 +# 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. + +# Oldest test-only dependency pins. +# +# The package's own declared deps (groq via the instruments extra, opentelemetry-api, +# opentelemetry-instrumentation, opentelemetry-semantic-conventions, opentelemetry-util-genai) +# are resolved to their pyproject.toml floors by UV_RESOLUTION=lowest-direct on the oldest tox +# factor, so they are NOT pinned here — pyproject.toml is the single source of truth. The +# OpenTelemetry SDK and test utilities come transitively from opentelemetry-test-util-genai, which +# every oldest env installs. Pin here only test-only deps that nothing else already provides. diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/tests/test_chat_completions.py b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/test_chat_completions.py index 5ac948795..4afbdc890 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-groq/tests/test_chat_completions.py +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/test_chat_completions.py @@ -1,6 +1,8 @@ # Copyright The OpenTelemetry Authors # SPDX-License-Identifier: Apache-2.0 +from unittest import mock + import pytest from groq import AsyncGroq, Groq @@ -179,12 +181,11 @@ def test_chat_completions_stream_side_error_mid_iteration( messages=[{"role": "user", "content": "Tell me a long joke"}], stream=True, ) - from unittest import mock - + iterator_mock = mock.MagicMock() iterator_mock.__next__.side_effect = ConnectionError("Stream dropped") response._self_iterator = iterator_mock - + with pytest.raises(ConnectionError, match="Stream dropped"): for _ in response: pass diff --git a/screenshots/photo_2026-07-27_03-17-43.jpg b/screenshots/photo_2026-07-27_03-17-43.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d0548e5eeb8986f197b122cd0464ea4a7abfeb76 GIT binary patch literal 66992 zcmeFZ1z1+w)+oH_5RsOa?vQR!y1P^9mKG2MrMtURTImprc~R5l zB8XF1{SG(%9d2&nY6kMygFGg`>h>T90Qipp03q%d%`_PR8bbhpaQ+vKCJz8^1OY(9 z*e}|l%2j>g2-@5%Ji)R6fHM1C!0EoreHacPfdAkvEdk)*830_@0|4A%06;hRUXCjc zBv-JZudx5Q*X0}#2q0bo5(p?L$S5f2XsD=Y=r_=>fxjCBm{^$LLx4w!i-SvuM@>pd zNJ`B}MM1^L!NS5JDkQ3=<^cEKRdCq`V57pTApr<**Z@2>90E4nWe30qwig@{Y#jas zL^yZ^BxDp+G>{4ha{n$3OhJStUCsg+2yg&A76KM1cAAnv0Z^s(#)tZYF?cV+HZXvT zC4378e;??{=p{Bq7f&Bdw?2P0d?vB`1{GV;sxUj;vvd==i43lYPDa4k7S8#|$C|n0 zMlSSeWnSRsAot;IxFbnJpKap~IZA@`_5uIDoulQ-P^IsB%=#_L&CS+bXa3FBOQ87c zvt>X1gU9PSD={tSG*TSdPu)=xGnVg&ri)3=8w=*~eIsnXWQk(I# z9z<8h&cB^6Q0b8)HL@x!I&XYE>}^~$L@3gG8C&t*-&gQQPQ(uYGJJdPam&~vegHsp zBy)YtXZ?ePLG_Qk|2l^F7C>}G{T+{H(~IB5exO7p|40M7y}Jp33+)D&=;2doz=FaDdAq5GvH*^k(A_!PQ)F$Jm7w^X!*r_nEduK65p9Nh`-LF+g9Hg}OJXU=~xZoyGpY@u>+x6AOjp#R7uh&OR<<@w% zoGWh=jN=wl#12xFZdPwHA4+8>5TPQXZ<%HBA?N3jR!c0&Mr&_&+@)DbTjwE{Ilc*(j|jr3WqaZ}7m&a&+K{I2oW^>jR#S!&z!suPCrJ;ROO=5)O~%#S|ZR9lZ6FSre1!IA8aKQIQnB*Twj=pzni- zxuwSu1x*_+J1wnEjg+qY{U6?UmG>dkcC~-a68m1Gf?5-#+S=%jrgX0;_mN?un{6zm znkvH=z(uoa&bD^;kN&=*edk9{A%G!p zqGf+A58s9d_agUuI--j(z{czK>HTmUw5uu>KwYDDw8dOhA2U?otar|)Up!+~h`3UaZO?2(gmDi5XtlX0gE{=cg_KFy3_zejzKs#gMHvZN ze+ZZ+K8B$$mlqlXlkwhht$&vmNke_l*sb`*0;v;>*hG*j`vD$mm3;{)#mLhx4{zti z7*PP&{q%+|^m&es6@zv?5O@sN_=A~TkR4+_ZNXcZ?AG(iu80B8ZPT{jon`%n3QHNJllKZ$SBvXI-o~0`nmI+vW2RGg=Z>S?8|(?H4NpE3-jZ zt0R_!wO*wIYah#4Y*u5)wAXsOIpXWnYRVkqXy1^amULBX;)`s{6BQnE`y3BZ-+Ib`kpyhwGFdLP$Y}gK=`p zxw+|kCC|@>B#gYLk4L*7gcfIF_fvpX`T=n2%ep}83;4&rq^OA3#^XF|wHcc5IY^?E zjIB#UOA{;g;ESn6jPHjh*oUxrx0!}bL_%c3Q=S@$hd<4Q*D|~PmH-cEYRVH2>RjU- zhACwb2c`-96{%C-!eWH55^%3IOGU1?8r?sdS)&j5F(YBAATWVFe>^hNw)Wne_i)1? z`+Da~j*U;wi}UNv?_5ru*wv+$bFUcx=?fjppHBTpN}CE_aqBv0-w~m?BKMYKgh4Y$ zRRiGswm=%gNrtg1gxza>(fVF**ygS2P**`#KgE00o269y;8gr8KtjFqGYNiq7>*x+ zBW+Wzn(R|hHZ{a%dHOvOV}ie(kXZ|#jb`HBwX$h=%SWgF6vl<+T{ShuwqZC--Nelv zUy?ZEpjvE@`hCtu;@IW3Viy|oa>Wm$mRAk;GZPR2>-95=)R_zK1hZpV#&fM31s29S zQTL-t^S`Gf+ny*vmDtnQ^-D^f?*Ry~DImPXM>|tGkfKH{qEed#X(WyxEo@olKd!Dd zV7;Cczb&HLg}a3)U&*VnEtT=xg8ef)Jj$Oaa1CtC58gyQ>7Z4L-)2Bkyz@N`fdUB? zTYdR0fGj}>`dvS$zvO;lf7S+lCFIiH{)F@o_K1xI0L;P3%$4*@@Xr{W&6OShPBzpB z=t<1#c<2dG*Kmw1fzr_L^wu1#GJnJ=h2M(yXC;3TZ>j^70YK()|`|2Kt2Qa{n(NPh@n1qJ}> zRJn^)lVluIkDxU zSBqMhz+=v%ia0B2M(K=4^iVYXTfpkqMVSDT8EEIT)N_@}<;9Fg!*~9WQ8(#{#eo77UmGs!q_lB92)Z=e3@GB7c!~LwtV2et%cQdy3A({dH{zfBhy& z0yE+rz6k+p!s~{$Wx`%>p1nJ^+ReGOa|s~rM2S5L>3W@#cffx5dG=2})b~7ozTup$ zflN8k2H_X`xBs-zfkhZC*1!(zwzr)Q*M&(Sb=|cRe%<$lFKGO07Kg;Z1>eMBPV_N_ z|4()Q41skfN^W{WA~^jMT=t`xwOjr}(goH*#e{tLL82B3$E zcFZ^KbqPGX1h_UHd->{Q?57MoeEUNX&R%+H8a4<2Hh>cw!A#Hkni+=7?d-WD5%$r_ zp`lk+>$fsL`TtM?A1th)e7BJL&aWff!b7BPmd;1zS^`cw=F1fn%4uk5y zsxFaAZWP*ZI)c2LRU{clA9=2n@NQqx$w6Duhtm6nv{^*YsEJ(%-U5IeJ7w|=rqRc& zs%ObiiCOC5(6y!)v0g~N2;}5mudL|Ol=4Db37?emeAw*iP<0937!5G9i2sJ@b%wVS z6;~x-Hl!2>RGRsNz61q{{uG3oBM?AO$P#`NAl_zs&*1Kr3k>c!5zw3)xU%2jaT3=Aj=}Kn9-^ zk6(LP(U^1XT36ozWLRjk*jCp*t1CI3KP;J_nL*b}mP#4)tovS{+k^^WD}02yIp|dL zKngc86+gvfvW$Z@(eEV7+rc?BN3hk;JZt3(j$I^|FmwXIF=ek}lJbnd?qdv42@Yid zsZ-&GcM4^`5U#$ib-!E#Z*Zj-;$bg8Tw0Uy7!s?b_|bTe&8MJsAh&u44E8q`(Md_z=-5p(&vW(LX11VBQwde3$-&c zM7o3+yV5o7L~DY>4xFtL%Q?Vpjz41#9)e$Zi|u zz%h~<0lZjam$v|b;^U3Yy>@-Sjw2JhL9q6TU_3{&s5>=)v8GPM|5W+A_aPd^T{spm zf;bjC$o~PRP6YKNVJI383Mv2qggOz1c&BG+FdP7Wmow-{Fqw0JcH}lJfyq#oU8G|N z(|R$pXNrU?QLt9kr|rl129psyefgCsNdokJ!cAf9{~Rz17nB^W!HqQT8-9fGhgm1F z(C~qy%JsV}y3;xw8N*u+I0CU_eRa=?p~El@ut6cuBt?_jUxX28CV=rvE1W9aonNs( zV?TNiyPswhySB13{<^T^wiZ4+B}vO$IaXxXpaGb`e`gr~mLYlyN!jdgk-rhb#fFp? zg7f^3M;s_KUmubE4e8%l;9u(`yyf2j+Y#$G5*YqR?i>K1y@mCIr}f~vI*~et0~2Lc z^mFxg16B+x*7Pf_KaNX&m&3nC!6hpCz7Rr;P?j>(YqXD?b`o_=p`o^5d|V-Njy`mM z=Suuf4#mG#3C@wL4eal@{tNQ{9lw)@FY^Cg?BAkS8=*VD*x-vg{eQ*&J@#Fmev%>l zC+~l$T}4<9C1wP;Ms+KFEQBRuobLTl2ObgsRQz|4tF2=agDl;oI1wuk&ebdf<-n7b zw|__cHy+$8m+`mQe?dM*R%Cpiy6;bCeMtVlRQ`L6o;=)2pdj^c9LE2(F7R3a+$v3E z=51vR>W}vITWq|{K%8QuzMGNw)P*SbO7LpPX_ox8lAkGX)>r8Fsg)-HEgRph=N^Gr zeol{z49?a&F?1DZ-O0V;`L6Ukent4p7i=2}17+lmF}#1QES$RkRWjHK8Wt8GU^qH< zsEa=*$u+jC1XYM#QPMz+<2UNItyfh=-&Z_FcE)9obD6^!Z$3q6YWIZXk-h!V>0u7dcK@Z!)?-cElhW~ zk!`0SoKkVCGkVbmLsl^aRk<_i?Tpm|2#>9m>jzno!6O^5^oA16-n?6LLvkp7) zi2tnCL8@H*+Ti<53A}TINXLFa&OdFY8Il4@8&t@BUc~qi3UJA~XZP+!&CDa*$)a`K ze!E$VYA$v(%M(8O%&CVY@F7E5v0=JYuo}#So0z0D#_-o_J{U}7>o`pOI3z4I=HqOY zHkqlnV^VNxoOD8Nm@VS16R>b7=2tN4Ch+AFV1FTCq7YDe*nG55#c1gL{^-o@Ta`eo z;A=e}{o#k6ZVRtP`6jl#Qo6if)1Gy;2qsiVJ2oYlS(R9R!E43$(ypya{^8_b8CIIO z=;ChVGW|rPyOAG{1xlKx6r7!>Y@M553h|7706Q9XQgC$_1L7bI+S{_&D>=c?rXkCG zwOEK^DIF>-3V`QrDZbn8ufxAttvx&Oe0xRY`DUz=B}Vtf0VQb~fTPGUw=o|_jlSB| zg6Gz-=}w=Q?de^7xRH_G-KPshi=3HCGd-D2Q;r@a5!~hxE+_8x7Coe)AIua^1vSDh z#eNMnhR zxtS#iMuvk&L_$D>2LS<0`+f(EgNK5ROMpc|#leYBd7JBw>OJneH+fKbX~e13oWSd0 zRPfdq4iz{Q`V#U%($ZY=9Bo83gyymAgomqI74v?fllXv;Yy+5)Rw=7XGd@#%vnI#bzeSh zImt#{lhda-6RM$`g5~&u87=>5a(7e*_L^HI-KyJu?!CA*#hQB~?OTkWY9?&?9~n70 z;nrwpMQ=@XJd$1rRkf)t)zXU8?r!R_T6kL#K;IKOt*TNH7qj9e zvV6eY>_L~nU6QDsMjKWC<&%+LSaLK`Y5LCc`|7StOJplo-I07M*E5dwwk&u8SGJaF zXKF8wzR=_83j=&Fq}E3m4{*buXrvm9sm-c)mJL*HQBOhcS8SOxm(9s<&UAi^5-c+} zSR4JwlwD!>^{L{hdA=EQM1!7u2FKgl+q;6e0}&eT*ii|&>;L}=ycW+= z_Km0}C<&L-sbB1eGxp0t!FylCe9> z$k@aiNS2mM`rN`3z_)`Q*&B~0;J#@;zjcFM-qvgmCZ>E}!7!O#-g zl(B_dDsH|aBS)WQexVW-r9~T};UQ9Y<+yXG{XY1wZ?X3-Zc)EI4_OKwQZm+(643hS zEP+woe}Bx9r@?a)E^KtxQ|yp3rmrl(9bT!mr6p;xJwPK{v9oBgqB_&$T47xKhR&{O z>UCrp&M+L4C64Z{y&1R7C9?U_B$i3Owq`pI=d8!9JNH0p#wq+4H?d>KB^V6tmJdX2@Rh zyoSf1A^JGD0lA?V7yR2k2ovg`obEiT!tTUxRAk2T&TfG<^sV@s$CU#dAQ+e zr1Q=yguifYKl&y|yc(4{ozp@3OOg=B&o~jwx;uvPTsWoab+=(%+G&2;^q3iQlpLi)me&QXHT71wJ$+#q zqx*V}cB2nCZi9K!RK=GT258ja1jom>R0)cG=youV`wNf?p)} zY4S}QGaJ;eGCGk^5EJ%3sWHK-77o^a06)1NHhq*XG|NDJ^Aeb`X{B5n&|yjoJ-D6_ zyII}I{;lx5Rj8@MhQ;1|WhV#Imi6lsUfe=`l@w9gkdCusSLU0@kgeYC$&hvtwpw3% zV=)vwM*QtM=RMw_4F5M)*oCYc_djX$g8ZKjUh{)q0rkqGA}f^M(WW_Mk)})nWrt$O~EGC|>78E>ddn4>kh9M|-`?S^ptt9V3H_7Lvf$fs>T#;TV86Dfyf$t zlWqr^c0(OWaNwf$M@AO*Ch@F_F@B0exj@ByoPW;DNq?_h6OGqPNc$MofA7ID_6O4h zws%DD^34*a>pPrI=tLxM3|<2LZ&>k)?=5KeK6=f;u}GNuDN@nu#`>w8@VlBS_M(os1Yc7MeIkIIgZ6kXVaL{6yKw zGfFvPK7ZhAHYHR~V-odc$?~}V7f;nb+-?=(ZmOA5A8GOD2MV0sO|Ly7SvMXUT1q7< z1~UU)m^J)(81s2kwLAC)?pn|Ka%K}KY>P9fp6h#t;PbaIhMXtQaa#47@h?mIWLKWX z?PK(jbdfw^f$sa>lD(gDBh>kI>$g0keTVY!W>jt0jB)eh>H-;d)aG3hbVSCkG)vv6 zBsO&?NtU(h(&>QOTg#nz$-SiU%RcBEV#;L$P00{7EjDJPWkr)jj-wV#% zh8Uc$6h%3{>gi!ewY;{-(6jX*U%T`9p5L0uTbM6mlKP5Kj-Y@z(w3tH^1ml&&n}*{ zT7H~U{cnqagW8;XUiSI=fr8S(I1d_WR1ncw&RHzgn)#g#HuUi=#lE;S^l*6u2>Hu~ z`u0p2aV-%KYG2z_`7jcc)@100ttb*Jk26aV0j>kD#S@8uz!k38gN{?qZ8|Y@s}(9P zPAZRhGX}STQ%*_^2?G8Fy71ExMrYSpF6b@fo?v*$niMMqM6}s`LoP|P?fI7%w;wwdL9xbHiIo6s==I!re$QB zgr`B1Tn2i0iwTKlwK}xz)h{6~l5Ry70`Bg|KFd}-^&t-v^>ii9;}$k#Ek<~SkzTUh zr+N?9OkD&Id4;YK;=sRB50@xeQxZAOpv-2^S)qXlYi5dM?ZUXI7RZ8`V|AnJw~v#& z+a&Hm;$HOKC(%&_1=bttO6c4uFbBd&S2InrG2fSFz+ z`Gg<~$3n9y)V-haHnF0-rd*10!yFxz+Pma0bz34lV=ervPtYN>Vse(rTlq>JWz!?Z zU!TP&Ikb4sb}{F%D&`C8izho~*t%OT7$R2D+SGicB2U7~e_LL;QE8rBAX%P7i&kmt zQzbn(TQ1Uy20sINK&_BD zLksIWpEp!&U)N#lcoHLJu~x+DUaHA#;OWqIZvscNcut&R zMI9<*do3YPx3XcIn#)S0+7&NvM%KKvfU>*RZC^&ICJ8B>`l5_U)E9;#oSVQI!)Z!- z4i6_POP@)@JnvNR7JJZ8xm#eK>fXQQ6Bao+NK-{Qrtm}$vrOun;hY@1l(!rIj8f7! zJc9gwBT)%-xA1NFp|R@%QIMfM&co{W4r^A%6PbJ_Pk)X|>KVl_qSGD47fJW*GgB^s zyN|DPZ|~+6TPzcqqfqm3PLaRK-}E(jcL}8V0We=5@gn1~)Fp7d&q05Dt%v?RMCOYu zBc~kkHT|==z?LnXLYgeMScmu=Uuzl$oq4uqL|J+x8e%kd!N5(q*Jlk%spI+7vXW`n zpUGp>DcFn#3T}JX(N3u*(TY6$;wy$s^NPqu~uM=sw>V(^s-5B^@DC zOcKwl@XoLZ>bXnV+(`}0i|BJ0xO#7DWcCaxr5+VYC!R~O+DFNc71BxJIJ>^wx_Z7Iqr6&r(sB|bIxT(KCyf%ps`xKY7*6( z=haI6lKcwS4Itwb^bB(U$ zg{3Z`?H1z$A^S*b*XdPQ3WzrMWwy|pJR^4t`f~aJOm`_peBIG_9zOzB` zmjvV);ZO)n%vm928n$@e6)RqRy5PPba_7xOehPJttV+$;*?GQl8I()Z(#20TkQogN zo0a98xXhUH%QlrW%$TE`P3CX(V&2dFAfOl9N_`RgB+ytFQXb!7DC$jA4xSOyWLQjUUwDkQ<|62LA3%jvTC( zR)fD6hx?N?oZlOeausJmKjIq=zDQX6dmP4!`G{tDj_rrk`Qo@bA`duwsOnzF9vxRJ zSWyYc+LYPx6*wAPAD(S(yCo@q&1RsXfe=zv$URrdA!kEb;9gB!+-qQDi4hsu4due_ zt|d4Y!Lbrg;Mf@FP0*!>b`{jeCowjSYuC&wRNl>tGwIX@!%v6 z+7PG38KJWVW$J8^1PFBKv=*jo+K54Qz9>IFHogR+z{%?=^Nljf@`xu9n@T>+B1TY8 zezDUPUB1C4PbqfUD0w?9d|xK9uS?L)z07Z|-Y` z#p24;Vd(3$^oyKF)X8b$mzJY48`YR=FG8Y_LWg9VB!fR3KAx>{c1dtxZ9Y+7<&y^g zr-0?aak>8Zb7;y{%`ZIX8J01c`nw%>pRSW+Iytn0Tk!z4JciM#T8WC`ZEm!+&~8Y> z-}}82o}!|hw02J?^9XIda#jSBrAMzC<0AgesO#sl&xcNJWi8vng<%$nZErvBSeeYO z21V%awY=7n0S^y2FMwCw0tbhs<_?tPE>jT;$H>pUY9HBoq|>enM6EeyedJWaCnm&tr+~4!v5d=c)K+FW5W&bAuj5qkq$1C zO7-25Zs}xnA#w%mu&qbmU{PFMpr3=z8z|`KU|#~VY9H`VCK5Gt34G*EmHi$K4RjxM5TLhTZ#hmR9#3 z?5w7>>75zGW81L~M!beprFGWlD*zA0JqTI6g34 zMyr&0<|q+iCF87U&3uape{5MMiuSC2Y+HMj4p%utdQ&Ql&UGV(n1xY8X*A|TJDaRm zgMQZwrtp%FnWd>FW3yX*j=|Nd#0FZloT1%^_Bgn=vuex5o?Zea<%)11$o60xn~w3$>EP6?YQ3oD@kmeFLwIGS>!Xn8 z*?xHL$u5HRtuZyDENiN)+qkjXTKj7aaBzdIbEn|) zyw0k86gn;45JP=^Se;K~cXuE8vK=eLQKaiUCOqcs7C!p2G>fFAo`>h^Aw4?w`OR-q z#uwffOjZ-_71~m7201J8h14pqte=wL*HD{6Cn$%Dm|>A*0@`sk{bvi0l=mq5fRkB3$w zggmA=C?noIQK~g8VvvKzLMDaljUunJ56-=ju*%t${3AIxw-!*2;&r@?*1r0+@IsjJ6H*jmO-f5*ZgF5&}p`TN|gG)cFhIT!XZH=*6(n{}5! zAk!QPpHc}MFH}LDl!|M;S5qK1IZ%E-AnLuIwqjk_iacIDj%vfa^%?s+S$*{+=3ZI7 z!g1*&Z0wwLvC{{qX+*cExf$Z+#RM*a5DM(H>$b$>JSD`D-@qfcAB+73T3|!ttU^Wv z(t3P#P-Db$mj3iR{xuiiMei>r5+4XZB%T?JYuRQpDH8+O#5T1H)Ts zh7&X=m+KiYh3Q-DJ9*G&O4T>0<=|Z3SrKaW8>^xFsz;qBcvTY*zyv(UlRE z5A)mJj`$kgkezL2OKqjsuOl#{i?es#?9%nEc^<5&vpToR5SO>Mh)%ZMTbL_c9T(B) zz%3WRp=2}cQVClfT&rG09cb7Ij{R6wyn>5x>k?>)rWPX5UvBf@x=j}8k{sU6&Yoct zL$pTZ(~GB*PT!O2l;KGAzSisk!>BR7O3i>~ysvvDL1)Mq`fG{)JSI9_%ca8L*!lEE zJg{T^_7?XlQ;y}m?YR2pJ=~EwEQFXYfe%w=ZmSL<&}U5V%W#_9qx%f4H!C|h`oqdX z3$-YQTvHLJ6{KBUwM&>p zU|`qh@{q2U$CZ6|2UD%D{B=v=);C^c6E-}%dghJ_I((P%a42>28%6W!x0e9LImM!p z_HBFdF9VIa9g4vR*9Kk@MK;n$9;M7gC75H)Su`DTDtyH(-X)i^BY31f-|h0UBJQ&m zugJGR+qx+}dX}DI!S+%7v?HfxAxP1m%`as_NuiQ#Vz-h!k8|0os}3>U435He>Mp{Z&o*N zW<2##>4A1QHxuxB@E#RwU1R#piEr;Dz*+_u#D5IizE{ zwfp3Vl?-hq=X;7Ddwe*L%dikC|qxO}cSw`$@8isb&wKl!fu&vn_+gtIZ zWzr90gxt2(S2Qgta#q2&!y2&PUWU24=sX{|C^%ofL}O9RqLaWj7b6K)VGU+lny;1P zq6$$9)zjB`4Pof?eY){LKR`#0+=E%VDRtu7PJ1g}(&_f#a?&Ux!~RYl;kUq0El-Ee zV!=XFyRsx|;wH-~aSLaH>hTqYE{m1jPSc)Dx38rPbr8mqhw3*dp2%qtc*hAAM{S;o zz_XS+uUoC+RW#oqu{7M;M-L!*VQBZPw-M9V?u8k#ku9B?;q9-5Uv~wKO<}I|=|)vi zN|?ermTRa$2kA1VGYWq|=G{SxzeA97%Z}X+yTIhCNMNg5{|h9 z%$A<)$j&)Ef!CAYIt!COG#vFs2qBNpm+BeI2)^PO)p}^(j8j;ulf3Odl|(}EGWdwE zps(lCx+wI(bkR^;6JI)ka?^z@_7X^iZLClux5H=&29|0)?cbB|1^-`-d{8yH{mm!z zqr1-9Zx<5c>>JcyYag$$`fV$~Zu*`oq=yCvUPmRy;-;{^GyEhEK^*ySM%`(o4I^N; zfj5t^zlzYw(LU~vw_Wc$ku>ZNC34|npQ)^;WKg^4&QQi~^ObPBb^^G51m}4KR z1SuJK7!(N}yOG;6)a*Bp=%?=sAiFX;D2rg4yHnn9Six?&Tb8yJhnIl?diGyy0=s;5@10~cfG<#K7qC;Gv7n;1-+RRDViEZeyR9{8TTmB!aVc<{fC0Tyn7${)a)+~L|B<15 z=WTndy+=&XpQmv=*lVY-joNk-dq-L$AnKTddXQXMaZk2~4>RUoyyDg=!(IW*5+=SY~$8po~N~u<}+85JfK}lz8f*Y zHmJ-TKC{OAMzJ!btsdKM(5tU7yM}+ z0tx*Z!uXk;k0n>@yO6AS9E=Q<5|?;SGgN7MI-MRFHb*dGeLNLO*0@`ncsPHnm#TU) zb{)wUI%lEv#D}tXuHFTGq)oBnIDL%s`|7z{hI7rndrV^j6-cA}Y^ zBWsV(eBt5R5KHheE#g`z6C=}2jhk%m%~rlu+V);6^?)>Ar)4sga!b=v$A@2QP4%}9 zGBeyk?g78Z5V?2)F8C`{7f*$63zzXyTL>CP3W)|qsU^9NHf0%~D-fVn3FwF(=ikbO zB1zI)y}57H(P~)kyk>6>}%} zpzFz@4xflITF||Q$ze7)JfqXrx?Jy2c8E{KNAe*tEV5j%XDoRIQ@3%|Ze|GGtE95= zd1mc$k$eT00NW7M2p(D{Y(P$@GZ0`!!~iXFOR>-Jqi)nX{uq>Y!R<3jdiK1XY&n`8 zsY2SQQVicYSU=Z$^ivoQ?HbK?r*-K!%asI@gX;Ye#w@0_YH@w0&@jS5xfoxh9mg@k zxAe^d;gL`@NQJl7?WXEzt!m__ESMZ>Y63Bk(q(c-h^|(J6zU(W=O^&*T-<>zcG!M* zZ`F=_%Zb&}61lE^r4p5v#sE)GK?_+_YW`Gg24`GW{o3zMFX|cLR)xE^U^$sqbXk{{ zSy}aj?temPOSJtA+a3m*49k2re-vAP2~@HR{oLqaFNzb%tGG=s@bW1|jhX%5jW}u; zc4l$0!5E)}z6Qx)Lc+0XRRUV>$gvM5I{ zT6I*YW46)L7bnZLsq~3VMRl0A&)s*9w+tF8_8$>t%PXeu(%ksN2sL1Sn3p@ATKq=b5=RBn!*cD(F@T=<$6{dO@SF+x~mkYa_)`z)2Fk{7-| znwDljs_(!2WofRQ4kxBhfC>Cw7k_|7l)6%}<+IQREn1%V=gY+sh@Z5N{jlvRNY}!@ z9Q4sNB-vTWb!>lOnpU03NYER~50G6oJf6_)$bK)?p?4-+H<0D)bwA#qzoGh^r|v|D zWFX2CA;s{c@-;*5=E#T@gRZ4$XWBDG-Y!g6Io<|*xrgw5)9x58LzssGIGN$^C4yH{ zYn_c6yY>~%^IUK>P=eDsBTGkgBij4h3{iHljh?RHIIO;l%_d$Y(DZzHS}`I62d-|Sqav5U-Wx@`G8b$2Yw!dNq%rJ4xIoSbFgenA8~ z)pAs{1Wp^(n^lFxSz|rEL}$7F@chZ&G`#TZ(%T*dnCwoPl4Fz-}W+oKS7qqiVr3NIC$)n$-%-Pr4Gg=}m; zGdpLjst;0i$=!P?P!}Bb;?`1?19>mL?I-8$NLw3;`g0$VrQX9+J@jc|?87eWia514 z>xVPs8sJUFWM72C&`_XRltr_V5=jle5#9A@BTPeba{PcMO}fKK!)lD6FO!$Ry~QTb zZ!iX3T8ncy*rHE-dNT-uX^5+C9v7zda! z1N}>y-;5O_nOP#_BN{iHBLnEYCT$Atry2HmU`FuOHYat$N)XZ!XFXjjOC0FZD6ZP4Ws>VsNEcY0@;b zXw}m?Ro|hQ;piZ}K1o0EZm>30PlVc@=Rqfvzz9cuwOQhQJ$n~R-&;7&#bq|AYqA2a zG_qney4xwVp##(JylZ??RnU@>v510?@{nuVhTLnm`$qikkO&uKPZ^*idI!|MwrnE;X%1$F9JL=oalld|=#4FmDZei^>+c8^LnOy=g zc)g~>rf252yRi3JqAFbMCNfnbBB5H&%&vV*2ANfm(Tu~r-2-Hv^wGJYuG0kN3zA27 zAFvDOLJlH>4GpK*%lbLay{x_>f9v@4<>2tmAv-EaIvi&8F&4~?DM9Kya`(Q}q$_&cf9;g2=-jWT zdNOld&w8i3qU_qi4^!h%?z#rk-4&o{_$)yLgsojV zrbEPmH&K*uW0!dQ&4flC0q^xrP07cniTTu2v<%HITp&<$iduZ5{JG}5t*|PFFAv3U z9et*C_fCJ6-R#qLM=Kq+H%M0QeuBqpjn@Wu-iMKM2dn}a3s|nUm?B3*lpZ<^p9%Uf8wM;3>D+ z0~d1G0^#TP+Zmb3;(O}<#w8T^0V}NNS07&Yef?ki&crzgevgE18gk#SUp)%vGauGtDpT^g7~tDt;+UQ7FI%TtX~_miCpz1gEBbH3vN!G3DcG>iQb z`Tl>uK35S^7S7N03lU#1Br$U_o@SI@j8^--gL0}}|Ia`E2EP`+m*@j-MlX)r!M{M8 zz169+YjH}%YCfrvz)YKfCj0B|5mxFTWZukp(zOqf`eA9Fff;m;PWtUN_3jC8-!ItS zb#T=pTxn5!7IOSdFt{Z?Cq(O$UYkJFQX<#pe!DFjp~L*_vY|BGMP>}5SyVVeWPh1M@uWKR%CqRx1l+75%C#Ox`2wxB6QJW z7teSuDXJH;YUWbitUF)fsLjVr@{7P1|GZ`~`sv-4p}6AY!@xjn8MB?g=Drd~2JaPZ zj?z=HmU>U#NN^{()400^3+^r5bMC!w z&dl8R-o0mL&Ahd4_wK#E{=TZ}-Bq=BRekcS*ZPQrif|jNAs=QYH{lqS7idwvT$27(z0D2Rq2Ecn!Xmtq^zNN*#^blOwll zC7f$8>3HL|sm7i*cXPnF4vr(|FT#EPre}0%hH9C#nV3*(y!2AgDCc@_^Rlcl$_wwL z`Jzm#-8AgI^wnCWMfS3Gj9XS%j9Ri9|IEWB>m+vx&95uRm_=DPmgCiE3_OO%Q7L;aROkzr_?@Ys9B&-v!Qq zqx$}Y97of^;zMTW$8D)^~-rFNw-szD@W<3_4$9_LECT!Kcc2)Tx`v$enyI zogNhS3>-<{v{ON`@gG#8PdkrBxZjgS?{c{1p!@SVw8-Jr7|}*qB%*?=GQ8bb%=6SR zOT6@bXo~|Vn+0OAr=(p(IPJ4*6qcRW0vV!?>79AN)&7Ua`-{_TPTUWnuX4|%!c)rb zGqFN7s;p)ii7Wc6R*!t`M$UI-6@T++`d3H3zW~KobzW=&JK?HzQd?4rTev2REzQws z{6Cb_=chBFRmlYDdC)FFjE#CDReedxzA0{JAYJ+i*1BGbT2W%ZRu@;rC}XuqYEu8% zj^_RqRRL)bJ`-6}g&tlljco7;n!suHQHJ`@ri(Z}wI$k}SDM`@CpCg`a;>sP7Wmcq zgSNB7Wg>5a#~B2#NRCM=Y&W09AcfWa*nyVm ziXLK;vrssGSqj9|Q2H+b@+sT-M02>wc_M+WzdAOp-sCgTPlFI) zlYW|IgOSX6mQN=L*EVacM(}Iijz&}0mBY8_OpoUJ9PDO)1reE)02h~GV{;vDhn@ZR ztt$&xmL?el?_9*bB5GV|5#;eZ#O4h%Po#Hh-&vsrpDjL^p}Ym7wuZccMwuvAzG5GI zh1Jr`{DAE&Y!IHBg*laU8r4KrDR8^0%TdBxTtJY1@Fiu>d4)EqxhDIWg?WW~bzfkl z>&KXppfcPpEXQV)U+hBbzV(Ocru&4h%JfHmq3WJ!zIzhTdmqwKmKzWB&sX;=3}5+2 zlCDq5Em^7sFT1-$%e1@KNTFB5kMCry1YQL`)+#zCkY`2j+{-T+|HirTo6AcxFhU01 z4F}Q>nzUr-;h3Ho(FS`B#X9j3j)s!bJ()L~qCHZb6}*LbP8tje_7Mow#wvEO5!fZJ zF0STz%y2%>-ex=VX6O~Qay}>Asw;~*Xd>^)Gd>||?2~Q68WOI>qdCAfyOnEtR5`Jf z3??%p5VWO*>3mNgnxUdEX3fBFEhZP_$IXl(bVd>5wR7g`2r5~@U-Tww(T~M0k=Haa z3_|&vpTV0`uIzL4MXrx#vk@u8xe>TwG-R%^N0L>*^I|KtT&zg0Ate<%GNv-<7$+0R zMw;XHl8rmAOlI_5EZv)T zoLnJHF_IK5uXbBuK45B_3{?62cgN4ajdX0id(4Z8Rc|JmAgv^^3hF>riKpCO2z+LLHEDN@h=6zwWPhKx3NCf4Dzn3FDoS& zc+1F+_Y46kc9Ih=$H#oFEPJ`Rwn&IC(Bpg}LBjv8fYKzH#9fewUfG~tZrkp`K)3w0 z;+@cQLycDcTQ55mb{kkvz}#^4-V5s>r|8`FAoj8b2^)N0n@w2u^lm9>%cH2hw6CAY z?jo=~vypQU`kU+<=HFyPf0G^kjVbbv8S?*?`S+CnP|6Xj!CbA$5*61!7X6l8(qh(q zKd`oFZIa@@(y7q5rTo*_ztrbH*3y5k6Pk%0PBg(*6}W z1w|b2ymbMX;B(-We{~Sz4tvD=-Toerqm5j7FOvX0S-csleJvgxcP%(r9S2b>gwbeq zrx^mm)?!tL{qYa^UP@O571qwiK}!Yn3Jk={&!PyBH62yXOX7Sq01PDP&ytX>n(sXL z(kSpb)XD4X_f)#MG{Gm*!X@{f!>9z7cP*DDJh70?2w8F1p8w$Wyr6f_pRt@m*Fs;3_-zC*43X0NQD>tr z-^K>oou8va-bc=Sm#*B{e|!v^&*JBJhhYpQs?5n;*RO7uxP6YWUr{PGDZBK^Ccqn_ zPX%eBR#AsCUua*kJV${i(zp1zSbeqFzGVdWd_mKDz_rhCH=$D>2Ad(yd*Ja13Jy?w zaD@xS#IXNq=UB&4N3avCmd@pZHx}-zq-xzWe-KHyT-2ITbdJL0HYpL0q3F%Jno|(!@VDpkkIAqtA2FGC@9nJG z{bJYq8QMeA+AqsLI*o5#b3J^XQK+=no$7a5}Kl%P-p?Vloz$mMIAT67aXIlX$Noa>t7=4pR z#V|2JN>R)IwYIiPukf(exRrpPJYV6SY?$oe;DB7Z>qPusjRP?B$O5PJQ`xsV)F&8C zDR?SxZZd8o@h%214lOJI?SUH?HiV4}{jA~(9$5AvJ~phMwuK_h7GxR5 zhOYZ8LzhCo5p!U!!e5t10(Y4YKb&t?Qq4>-bY&|&+0>d^OYSx z#St!uv=^UIOtZhbk{P&Htn!hg5k$qg`YJRQkR(m6l8i}0`>DK7*A39Zd)qtLj7Onv ztd>;JifK*PJ#RF4VD&poGE2$VC4wWtdUBsg{R47psT#RBY!tET`PLqvKoEwMHJAw| zeRs1Xbk$={;TX2Kok2xYRQ_C7yf4-pFyz;#LtG->nxT%>nvVC5C85`809r?+*qXlP zQ}Cc6xGP+x)!72Uw<(f@ZJiMlTw6Lbyt4e5Il^eVO=j)_+U0q0CS|%{t%GcWKo3fl z`y#2Nopy{Z?cGKZf|IQom?tx8VG+A)QNJTnGnC`&hN$D5DG*EAZJk7{9Fx&dAQ!MQ zDHUa^EJ_QtGtqA3T%dJwd1PlMYt~1k6%{;*l?(rA?F?=~M!N~1wSqt$|KKRfFNJ!9 zY9TjDPKhIH8o4fs*Csk_cMQ8&wt?NxcgBSbI&1rJUX2ud!KwfqVjUe~)RH;CbIZgU zAF$(>!sYYV*FrO)s^zv47cNGwXi^DL6WYFc@j=nR(x7nvXZg4J?cIIyE6&Lo@CCTC zCih#ep*8U`@q-=J4rSYNwpo|_ObfLobfUu0>wkKfD>FrKmg5g*YN7sbOg{Wceu>(A znZ~pTK0}3TeTO+$C@l5A85u!S${U$9Pb$5QFJ=)nt^Nr9ka=m8b;16@N+T3e?Slan zpc~J)7MqITW%MIkzNp2t+{omM<5y^hWQ~LFyoG{ey|Yt^HtZ*0t@|0=)L7Ii6*y!M za!ueRDnkSSFF1+I3fHK#{=q-5<6pSd>MoK`E{q2k_D{URZA$(7h)@3>3e^9VM}<{8 zN6eSt_4f7@5>H8jDL4H1-;Y}B=wcDd_6FNOKW#t5o$B+U`H^%t5=y89Mt}X3eem~sB8wH39%UakW$pWvLdo>Qf@&9aVSYs|lrPF%B#xa6nM)nNvZIc&PW&MR;B7&EW0XUVWe0LbKTYINFq7u$ve z_y@+}BKL7iE05x^w(tz|Gb#rvxA-6?Ytu96KFmGS?jI!y?h|E&>Z2oqJ45X8AeeY0JDwDiX9TOYsTX#xbbH=~6 zHn@z|(U<vD$~Xn6IcdPsyD=Ri)Y!^UY_-a!0x za~X7H@!Zl&>J?wwkpZDbRK?dP(-I}yNGfjayhY>8QrhwIa1*4y<2Fy53J9HV{xKFH zWK@F)FHb zAOrj9liX^d@%hz;;|`i0kT~Nst8;0!CLbT;59Fhm@&hYV1se1(jfywb{3==JLkgUwD%NI*}(wF__wd~p_l&SL~<*1tkPBiqgQ%~r7@h04y99s-AnP7^x$XI9-?bB_G zU^loG5pnk8jV1)?60+OBJCi9i8OU(O;HgL1nk=;bSZAz*#5L6tEi0xB;7$o(ePzyx zhU2R-ejRVkUnBErk1+JxIv3;qXcBBvb*NitBfH4D(?P=@L){xZTOX)mShqtc6z;7~ z$63VP+lUh4Gz>trKYu;AH)`xMa$UyDic}oq<{D6Y`Wo*ZJi>EM_4;n=AX!7bQLJ=RZdE)5XQHnniFo#;S;2bQh5yWZ!+^ z^mImI)(hM2S!BH^Tw-T0PbWdw=yflyuGeUmr!D@PA1H3v*VmN{E12wDHw{GCz+J6$ z$x)vx{TiwN9eaeYuW)+$=%ATS`4*N%?^&|i$N&mD-?0f@+k|y|SDifisS4453dXR! z$?SorB#{72R^wL!pF%#TEWx6V|M3(dDXz9y^Hx!Y)e zk($6?Xe|mf^(pm5Lw>+G0I(8?3LsJNRY6zqqUo=!mWv~o2P%-29YmT`Pph&Cf&AEf zP<=(4R;8A_6F7)_K9*Nd0~?Jm1m%DU($lGt0SDY-IX&x}-t)nAv}u#Zj*lx5Zu%l^ z$;Y%wu`4+=CW&6wk}XB4leh0jCmT&i2kY+Nl%Kn_)STm|!H=STfmzmEN-33>uicG3 zMJTel_fGE6*daFayr_efKYUln`Qz9J$=kU|eFzCXw=DB`sf>gxYJO9GvU)gA}# z7PnT!Uw{Iy0LFo$p(sS? zG&R)?UZFQoBsDM|I`CnaFA3M@G0MyMSVPGfiTuk8YGaeIlpx#O;c8`Fol4zYn|F6- z0=(b&cmlsWTy`kDHxIJYem-w!?)tvMKwRFp4oYxd`h!|4k%nYkObKZC>viF;e5jL@ z3aX0w0O5!}_9QU6?>rqH)0LS;FY8wV39VA*nvx#_iAEQV*Ae(7|A&Mwi8JZiyKQ%w70ii+=o+Q34(2XwGp7#=B6w@-j;tBFS7#dZO+eJc zfq?1}{w(Jd<5KnE@eKudGmsKkPySl(F>&Ws&RJ9#CeYNje|J)>7s ze7ztmrPyfm*<;#>Xm3+6vh=am2U(1^MF!VcA{>gj-0(^oix{*i$CQ$d!IUJN(r}7N zOj$CmEJGrFc3@U<8ls{+Hl$+kEg(u0N|>S7E}XT3v)-wZG8c^frX#+pQ8=VM~X;^s7YlwZ&zuRVh4@I28pIhvnj^U(+7Cq;03Q zwYDKGqPebU<{F_~c&5&Cpp`&h7yo4`tK(xQ_{=6#ieCs9gT6-&e+r{N)c03_oxT;_ zWO%B}w{!m)&LefEz3V-$ZlNeS(21_rGPCVH35_clTwM;3LV&9T_*X5JWrKWxaI9kt z(Gy}AX!46}b@b`-hQ|!-rr(}$X?(*IZq8I5+MVbVB}<_ZDRvIXUw}MXW+_Vha*gpvm?A+6xg(u#gDDli6m3P zy-#&F=3-4eKCpRI6$Oxx9EvPz2Ii7+;^~*)LyhU&&+B{I;U1m-P84ra%(1MVU!9f` zPm-YQuRTAk;N@x+Z(LKM#pGPfENpGwc(4N!PJ&R?%pRXq;iN6H^bHJKVe~RN_rkpm zE&{X_5IZ9h2#9?Q4vuc6`iqn4_e+EI4+bOxu^9a>n_Wk&aS@6s$8|zzL4<+JpPA9^ zC|{5;iJJm{oG^-E+4_1eCfs{UQTqw4h>tWgi@7|Bk+8obU`rZ4R;4s z0&XIB!ygdZvn=1Cz}?j8Ft#NN>{!O_?8lab56VK_beoKT`Oy}$BQGuL#@rL0DNzw= z@@qYA2XG30wS4qXD&yv=JUgQVc8A`*JAMnUTS`H0 zxc!OK66HG5Yx_NO;4Tx((e|Fv$e-PZ9bnWB@C#%KUe z*xtKIDghJTT2LlSqY>UtTq`4`r1X^`L0B&{RZ(;#{mP5F`no#n4loOU4BLjh zewD?ziTC*^g8oF?>$lHSD7{wV0O`KS(hNOyN&GpwCi+Gkrw#4!EgvT+V{x5xX_r!Z z>XvC{wwDyw02XQJ$%PBLknxStpS(mhBkRzU(YRt9vMRG(wul%yu#gX#emaUp0y4Yi zwvaM;>n~ldee}47FvY8AUI)hZ^!IDKQm3aB(y-h;%`i0-ioX_*ebTuVuVqp=d%Oa- zX(LQJj|eKh?JnQ*-`~3kS0(knr#;9w>HAI$&{#~na8CCt&f49U?O?P(p5uA@%Rk*R z;GaggZ}6w4wK%wxd;h;AHMaw@%SF30@1d6KRf*33K<46|uriI==XzH~amnDND0k8o z2xxKG{vQWB4ALxBXzAX00Pqp3`|C=^<)4&4A3i_n#?zN)KMnQ6PI2|gLUs;5;d<9> zqqa6Re+j5b*$grN|DP_6=!e}D6D|d5=uq7?+PAk? zRufz9AEI;hh=d}G$kZZk%=Ld#2E(qb=1|bE4hQq~LdLJ71czE{hxdj~6Zgd~M&V|V zGXI~|=s(>Q|4hb0A;6e;CnBflf36SQHmLDD1m8$P3k6Z(k_x$z2gZKh%lg}YA2|}> zf*>Nkcizl(98*2rBRHz!aOH!sZCZD{9sBC`Q;Tn_z|E5WR8s(_dkkfrw(~w|snN}k z{95v$a-)3=Yh?-Sz}+-SgG*K!?mh{UacgoE){Z%_@1tkSo+6#)l%TeHd=wawXk3>L zps%%t`tGsOk|T%EAq7nqg5e|g*Tz?HOJNw`riI6kE3;Xm$xEX*?T4=XkBhivdP-xA zNw5RPdKNSwM=)l6x-cZA7B$Nfk#YJR-M2`1ObwQbI}WAjmDh@ z1~Tkcp(mx5q>Y+Cj^OWLgOJ}L_vCGc7IW0aROqd_b*XB<%3T0mADn(BGWwYE$j>w> z@gusH%-fN)Ggc|Ozd7y8=Bm#UZNFV^UHFFA?K?Yfg z+O&D-yKaiSi4yxFBXb3OqHCoUSlPy*N-OMKJf>J5N_6igY)|BK!dpE*nzQxJGP-`r zv~ILcC0lgC&~){Jn~vvfs}9FGFQG4N(P2^ii}9NyZeX!NjQ+}>VL09EUImDiwnZiq zSxZ6#DiK5u87wr#)lX0^pPkCt`VGcvJRUFFNN|A6erEpqV?;@~`RYhN1|@&WA)Kya zBV935wqQw47>gHOF+V-oMi7A#mjD1gMN#1n%O~u|Ux10{t^OLH{I%uPUl87L_D@U3 z4QdL!wKV9I6mQla#DhoDyTq@jiSQb3aTXgt&3+HGQiyRBSc-08=+xT$sbo+6-7`x9 zZzMjYxxtWvnc`*9;X-M}Z9;Lz6i4-5RI1^ilQ7%425xG=3WNS2FT#Oh+CyIla1h7e;m5M zz3oueUf>yBGNL50Y3s=V1*l#_<5ym3Tu(LoYh857B+^f<7FmK?do4!$&Xc3NIUi}X z+W8uDn9iFRW2>{Hs?^SfVSSQgH?dRq%jX&Zl|gauQG*c6Z2Qf>5r=@gr=toXrdhB@ zQ7A?L%b#kpUv3p6k?}CGMS%>p7Q;`rX=T@)p{gWiLluut&E z)^XpYdT5`7)dXz3_U~NvP%&N26-@mJIEGs?eR07e;=@4dxHVj&uHIVwBgI z?i9PwhHbT|LL*~G%u%FQ`0QdKo<(%(?d6;oE)2sL>F32O zNf(MaZY36YSz=MTHit&pax$a4#iFYS?AL2MS4NUCJzePN<{|N&&43%Zx4$;G=_zZ` zAq3~Sa}OPK$aYj`86`sMTvcv@p{Q@smBJ}JxQ}>@}} zWg83C+V>;>Ngg#nJ3oO8Pbb)(!RoRv5j9`lR3JkHQNZKOBiDGxYWA6QMA_=^!p&~){V{F7 z^YRrd9eQ1g8}uj3A?Kkd-I_z-)Fn zeXW4c;C9_MaH5xHd45L%+B1~BOC%BzCkfg9nP}rna{2tX$@G_kmx8X-#I94uKPBe@ zpf72!OT0O5@jVG#%I=6T--`1>JM@tN3ysptT}M^Mg;34mM1)rM?Iu02XHE&~lJ^fhglDxW3VPKif zth3@!QfcLN$I16xcUWdguXkMx0%0<*3Hm%c?omV<4vLgQ@Tk$B5crp^tQY~eoC7D9 zcyWgWK&1N+>V?K2TXIrIOs))HItuUW-5S{YnN`H%ttd0XZ^aH&5pzNX1@RRa zYYRF@yH)o_9ESrX`&QT-fQBlZv3SD0VdcH3y)ql%Vg9PPkOFdeVa?vbhL%ae#EOj$LYFJO0- z7PmnwTwo^P%?r`Cayq(UBpEQfAMFBsbpyBX&u0+AYGS>R3$Q7PGL`u;Cj*yk?t@?Pv}?s25;(sDleZl`_iFfPPXE|TuRbkCwcJ%<*_@~bh#PvW zJ}u;bTh6`z+mmQ=n?`&RLr z)a=|6L~D=ez$Ra05+x}^S(ICwI(IThCV5*F!T!V6Hh~3K+xK{{-;Lzr`sccUbU_3)~3nuyeDXU+xX?sbLy9#DpSSQKKu9|c;R zcA(LfDLOf2L7@!cY#5tA+T$*cw}vYj7f}cffobBIyxh|gaLX#Zjz#zUqnmAC{^E&hNWS5t5^Iau6NUa;p zBHhZ|+ElLKNHGviTZCQ&4mHv9z>?aJAG@w`tP!R?SaP3QF65#RgN89vSsSErZ;fw& z)H=1#i&w37$kBVM`n7a_r(3TR47NDyiP^H`63lpoB_3=Q{rL-!8t}JP_mdrIRkj?& z6-cnsT6kS$(dKNgG_f#+>s#7Gfx{Iw(}wu=idYIWQo_wL75&th>RxvzAchp!THldarO@;*fLM#Q@Q3u^Srv zQyxTre)22LeGLkFYfX*mYqlPl%E<_6%5tnjfYAL40V8-llmHlOH+Y888$YzgY?Rj7 zj)}rd5ajFbDvhTh?*d_>j#P~gWs+wU%e~tz?cP(q>RKmFMHKx(!iuG8#~v}$O3SAo ztsR(ex0$5(6O3DWDLJT~Jgn2S=+n5-N`I9%H3TGkGaKaiRPaKaTEanlC3KP2!hVZB zA^|e`_Y9kH)vA~ZUz9k>(*TRMt(q|8!jQU4gGog+%~k8K$aO-sz{W$zBYQQC`QiufXIDpuQ~c+^JJOeDDBt75qQlKa<;vktjfQW1|5e4Q z=ucmhyX$6pa3dCl^7^aLD{8S_WdqZnS^fgNWZI7@H#J{Hbo$n^0o!mD!5RklUTNrV zJNI%S?(VYGrTC#qny8ZUObGvXGMww-ZA4c_9x#&C|b|2{q^_MB4QVPLfW|n z-=6kXDY0yq7Eks(6xl=125FI~D=g}NDOmPqFQ{rH{!~KcNqPyc$pS`BY(N8L#t7%f zzducx)xX2;>4rHLC`SAR$5?4y#@d2#{q0M13G**)wJn(WhFpQM1CY*iWmGhhVxQ|C zRT_zw=M>2<%sf?9TpL=Ll~lsgCq8oUlGF`I~^% zy!6MQ1W%kZI@bxoh{jht1Frn!PMk!^7c7ffXJt0b)yO5`)u>ee6A{s~79Z1}pie}E zAHF6q%C9+!U!*ppTh_H_r?1i`Tltpw!A>v_yB^5t$<+ux=U?>X=hv!#w(JhOp;)BK zJTI98$=WmkP_d?c{()QgGUkQ!OSn>;Yg6(u0s7Ai$Ej^f51%~#UeCGgu|yaqG2_=+ z9q#T-G{KS{Y!m854-+gGbm{PkItD}dEM6ivQYb9qp%No>BbmOlf}0oh za%`GFoQosQMGzdtkV<;}t@wlPAWH8;agltGKfNQa59bRMKNdGe6~(df-zeeC&t9lf zgc?kMlys_s;zIe*sS#>ipZ9td-_=VMAtb1wMjki`xr;3L=2J;1f|if3a0q09yzM_* z>-KQygpn@fiFGe3q^3`&i7E*nunJY(50aJr}^s0=uK9;BZA+b>FG+0S8Wl_E%aR>Z0Lp_*l7p2m8>i9@%i#CVgP0 zJ*f~{TQW=R=y0l>D!(|o9pR%`Qv-x1_*|&FcP~4IRsZboIg9$$2$prJtnbRwXV?vl z*PxumLhuzMcoO=)b~&)R8durUeWbBMbyX}-F;aq4!krA2Wj1^dH7}4XbtX0|yP89R zl2n=+!Wylgyr zoU4#3?8@57O3ui3Zgi_b>7el_z4ESVSeRk-*Oo;`!t1rqIKioQl(Zzo5M(PcDl1uu4&@TCMKf9iRgVEOI_?E=QaYk=+Rrs2w2&Ei#79c?pM)^qE9 z(gi0#CUdr5geVbxWhJ`0X_$e{#oiq{UFMekU!i$j&WEne7}F#569JKvUY5tv^X-$xSzjrd*hcmAs^}K3>oq zek|fDO^Tv~I5?34lo!hM(n-&tS}h84Y`-a#NiJlpqrf~Izj?4BFf;2Ss;5nfa=|>3 zfTF<&XDp7^TOA8Dnog4#0MDD|$LuQ0vonrJ^tdaaq%7Q=c$aYI~Qc zm^e==MaV>_b|muvVTFRll9zN1b=q2ed}x<;_4jNN!+*dR#(7YNUtLB@#r$)qFw`st6 z2Qq}g8&TLV7G{C>I_^ZD=hJ!*h3k6 zJD;VVxJ9n@SS7W7nmAhY)@0|W~jYOXkO%KmfzI{N7@Vbu)!p#(GuzT_fKE1@hT)~v3a+(E?KVaXu) zm{MGMnot4d`VyGZcZhp(@Y?P!5`cWJ9#_h_nyes&>R%t`?en$Hari)UYj_!KhZBjW zLJTU(2XG>=gFIHi(rZtelq>W9 zAfh=7WWsVdmJj%#_|FTCZI(U$2%aXwBFV>`7NW}9o0UBnK=o?@vdN;O6Q;W zTD@{TQQ_eh1A~J8 z=>G+12^+xB1RxBXtSeJ^)S<#P=TXD>>u#9Pp9`U`N}2A2O#PJlySJd)Ol zktqDK4jtSDkph))?Z%|m{{dwj7R-VqLhN=2}UF3e>L}XD^RgvL~KZI zP<;X=L*`~*5E$KX4kso=Z3ylYPWch#qHT~mv|8s_ECfjeK1S8nt1>Tt8;LAU9~C1q z{cRE#es{&qliilin5d?t>(iwK8O6-yQs?j7oM-uajibR)oOa(P<^0%Zp@t!-QR__K z-2-(kTICw2PObMm!nlHn*-=XM*$^{qJlk6~ghm_OPoucs^xR|)fm0&)#}4Ez3eMrm zIa$EevB)I6h|OSGTVp|7vQ-Ycs}LL(`*SMrvsw+^b&ZxA>`|3(qqO^r7-O8P>MDs2 zI9c~Sc3W$=ajvxMhfhA|AtgXKGU;2=#?IyxxkbzN>Ecu4twR%1Z>XCtR)rCT?%lpzYFCm`KNYN07hthw05a-hTaxb6X0Yd4X=sUUPJ&dr zSGb()=34%Q=F0}`9+yd{;lP#;W9xZIL!bK{*(Lg=Ta}A@gc<4G)*bNDA1)5*9;@(G zTUt@b%FG?+UM_51431aGv4!tzoNOc$`$nktT}W>Bmp>%|yHl()D3t6;>;2p?qO7k9 zj6RO0>#Ibom>6#1LK7wyIw+)CWf#5H)mjLN^wb4CErn;*MFzPm7(@sgTH3*0 z9L+32^tt8M*y3@lAMvK(fqqNn6ovsNR5J2s?DScCYNSyftGY$8T6D&~OjTH=H`xG4s#~RfBlnw%sH1 zv&11mCebpCq;Kw8(p?&ov>PzR*2Y;2r{o(oA97A8QkThfqMcV|rX9Aiz&!MnC_;9u z=UNoObp)A_{E;fck;5Lu>`k;SP_^AFdI~g^tcmJj5#@tt>2{_ZWtRZ> z^Y5SYA}4Hl@7YjiUUk}tRC7Ecv~G8pu0Fx0NWEW}$93`9dYU3(pN)?mX4^ zPoiG7g&?3t4}GF4w|~%Kf3X-~So7KD56{UP+)NGCy$eEK<(G~HFF)2@Fo8C%WN_vO z1&#T4SZjJX#;mj2EK}s}7VljQZmqiobZMdHZ+6LE;m7cGL#IU|LPJj?x6Rg(bdYOS zToo})hq#nY+LM*2Ws;OP3i%`)1rS!9cb5uWasK(Ts|e@*Bg3@OK}@o ztSP%dC?hkKi|)42@y8s^B^n362CJ+X?1|8mj(H;rt3MM#_jLlfVMS%=3jsxpGYHyaY%GclDjm9P0NpNmu_EWFkt;`CSq>7kp3_- z(zcOB?E%Ea%Ql3VHC&fr#)6e6J-LaS6HGEraX=L2Uso?oGtuxzfobf=rL3OXu^ud*pWT6&`2M zZwE)k0_sYvUB_&6E#xg-qBd{i(spxmZ@XRR0K4VSrmNO8>VzgkP?qhDG#wi+XEL>d zo&!KZU|fts7dk%4MI9+sbag`D;rf(N+X(mBT10=E8wKU|d;^iip!e#rWM{%{M0is) zG_b(S;eE0(GVaf4dco~c&bRTV)gQtBJrCL{p;Fy7k6WI|@~69G!-G@J339g{6jcKY zVhNAagz9Vsc8aOq+Tk89!3~Am#VtW^_`&6;o&A7VRUy}XF8&Mony&hKV!+3&=>(}b znDoo8k8$QOw{WUDQ5r}{<+(Kp#hA!ddGEc>1ZEWXVh?X0f95GeE#VokvazZwQox9B zo}j32o*eLSop+?(KB88+1!#HUp?ae5;Jh2`VH>w=x$b&8r>WNcyF?w;N2bQyyM~(n z{ZdP0Q8+QGJImLZ?Y?{-+v(+J;{-f$CHy<<`h%`aK+%E4m@SkljevWiLm0FK15gLt z0uW5pFmjNC+YA)qh*M#1Nb011T_cw(DC17=7>_OGm6AU{L4|YNT-=>ynm4~pZzwyF znS`F9=`Czz4xkLXuY0T{cAcmJ=u(1_4C+wTC^8iPlvV$p&32)Lk}zzeDY={YYQ|6L z`VcN7EF1CV2=2%iHKLrXsfvh=U!t6`*TUE&Z1BWu2o3ukZ%-U?EVb8Jwt)={AY0su zGNrfFtP0fH4P-%3gkunMP=9fJphMw?@pK2Q)JN?MM-0wbb_uQQ*3i?woJs``gjPLl zBL({IU;K$+{KI9!)*r0wDrW~JbY$TkwChCZaCo6#K&|@D3kL0AqnuHWQQf@Bd>nWL z9E-Z|t#9#M=c2MO0_g$LZ%{mX{>u>#@0L7Qe|2SM;5vg+oCh(9$Q)GLTQJwa-_Xe= z$#-XIm|Ji%Ae8W;!1+;|oo+=1 zL3CyW2%DN#n+i4LQ;zjIPv>8NNEAbpmTzwNk=GM8nLU>lF#ZzX^uI~+6%V;kCVym| zGlhMzxU?+SR3%n2WNSq;FC!ag$NoyJL@ed5FuKrF-S^F)c`YzMO2YspC14f^5{`D^ zJU=#UZEKenx z^zO)%s+e8%7wYAK6?cqHvfzQrdCqfvS}W$mIi4e`kn>lQyfOn-QL@E)`|W!SW6FV= zupfM`0f_ZjW=jL7q@AK+dPt4`yvU0OR~*7+GF^+w^DC6==08;UV#HM1ttIg#fsrkP z#q7ke{%TUSyxu%cwEeU6y*tX?Chr87!a2KcAV|UAgl(UPyy*!R_Ak8C2P)Uv*wp*zd5qCNa# zb#S)|P>+a+Veip<$->H!>xjwu18&8zY*@FJ*mbEJ5F~)5Yfq9~UytjsYAT^KZGc)? z=!y9@^GP$E=Lc_w9LJLh>YS1Grt`I>l?Ss}Mgg}8KlqKjrLv6v8ywju0 zW6gvKYlc&$^?10AH(~vL8mUiiq#&Y!5XqZe_w5SP3*YUucw*<07wz)gYxCWw)_<5_-sIDnt(zp?igz;QHBp6G}ri60sNX-X+n%)bm|m7MInR;g~jlBdN5_pNr{fx~!LelY9zd z!Pf;G;_d|kb0nu|9teUkxll7fC;vYnT#)>=o}zY+O1!>}y-8iaLH^t7pZ)-vm{t`T zWavwAiau+^sQ;_Gk)hka=+uF3Z|HMezvzmeMav0EZhw($B%%NM13-T(g4l{Ib?d)+ zwA~sG4tvvoD0VR^{dJ*s8`Q|vs7GSqB#0K+3j@@t#qiP=5!U`T=4ZcRsV_Fj9ER}M zJN|q}Z~fQYsaAV&F%R-F+b#U!p~u0*gLY2?ax^aHp{$xWiKR_lkr%D3{FvtJK)G|u zMYUZn^^bM6q%WDI+Kx<;eICI`>Ob@M0(OWURYz;DSXp=U=%k~QF+1orN{(ALquS5g zba?NKw?ovg1=%N}Ly&6aWVG;EK){F_$CzDD>EC4jesCi3>9HS(Nmn&*RzSgT@(pO` zX@jbJ+vB#?zAluU)A%`+b29diZYK8WSdxxY6BY0J<{M`vMt`1PD0e918uILTDtp2`2Q5xO8472Le=}waUfik$(VdYNA_S#)6wqX|A zj8w9&9_agDSGaBlQw{IEEM}oRQTFfJw%ir87&sx;pi4H_% z*oY7p-#|6COIM&d)JY}=<YwVxOC{zxnFng z%8zK;^2fwLJ5VR6b1bzjl{&ThrK(qN`^@TC+j6DwEgXSF&R19-%>+ns_|E?mS*x$7 zvsv$qT&zOFt)L*|52Y9Zt7HNT|J-CHpqooffhm*LqQSuNZ-MXWrIN;2jx$kUH!q_m&I-WDP@AM_1W^8(XA;aybFN}k$zM6r8WOu2{Bi=L?xN@_FM7P^H zFoC_sBbryniqsRNnpty@6GUb;Dqd?YU^1u}bH1UIX|A{Z2k=vXK)ccb54O?pcnRgX z`PQ3Xci%i~g1@jCKmOB?V4MB#$78?;qKrwA>nyrXGm127TGxyyGMjIY2Y&#wK_jeA z3YfRV_8utrNvQS)f`d5GP#t`MoqXtj0M9T`ixid29uF0ws3Y9r?Mv~8@n3l*0#LSD486|oVLa%oF*c;2bh2|+q6ro2z-qr?6642MBkDpJ}x z0jq^!l64ywO3;}2xaj#xOCMZVRUU`C8`XGHQiV9|_lIDE)YiVz@^37St#;Jhz( zU2~cSnJtFWU0p+AAqh}Wf`ZD%cAE!#uC*2&@cU%!6W5XmV_ES;*0NqUj?qLElR}N> z>Y8>>>e~{)Gk>^#e{~#Df1zDRWDPxKxapd7^>fVGY*7>w|4fegw(^)`NJM4CxnX74 zUM(&K^;66_=<#<`Ei!9)hdbc6HkS@i5P3MA zK}b|mt(w3j@qu7nj+Rdx7VMI1SS1RP$QL}Wwv(=&$YmpGa+Dvuj?rAn;NDwmx>CkB zgWJ7j84oPm+u4;qPH>v<-jmr(RCk;I0kk@vOibM+2jw*5ogNv4VY1{NPSd+d;o9+4 zsv*ep@YH-_0+wkqO%O95wKEn%-7#L%AIRiSd58G4Cwo<)L?Va{y!PBP-9IikV zrz|sqcGq!NJTQj1eG~#5T1^!{S=Z3PpIq64OppAij6Qw;y$oM&2fI=HP5dztA0rY# zP_hp*r6t%>=6}XYwl;}#V^od8sMu7WELWP=LI?~X*XrtwS${`tN7e0iq{n{o{wEKp z(rC2oyx9aVXP{=BnFS*rj~zOETL-&wfoC#TQj+jvOHMLoz>Ei(haF;!`@Oik2rEW^-cy*_n(^7%#OAd~Xjz^tf(k1bu@qhvVnqRnnPx_us!oVd4ET-{643l!F zKTIJh=R>h4md&S!WX44vWM$U733?OHRI(rOm_XG?IKhCdNbMY%ve*EgqfEY<-II@n zTBs02jI!CL*UQz*RLMy&ZGZRdZ=SMm;%pv=ZFtpRl?=U&tkO+U)*m3h4f}B?*9L^A zALy~NZB@1Lwz6`f+8CPXH2*xLu^z%l@1j+$-o=5KO#jPjMZv4QrUK@>KN&1*+p7Be z3Bj@WK@2AOG~3q63!$*^HB*}A@0KaQmn|wG3GOhUSwGnIG%lY!DCUTTHW)+|a1ZZ2JZ zY*S7B5e6vjB^hao9z2R}gjpkQ`fl+%$@cHUM4jP5T7(zyPcg=Y??ZeBTY{xeaq{88 zQP-F%MY%TwpM zDOe{9|28)`(iu*ISnWWdbdWxGa0D@XxU*^4ers?@XIbyvqIQl_%TiAqryxlR1HRwS{vQ46Og&kRY(f$g-*^Mu@z%-pOH1z}jgPj? z_Rplta$n$ZDhFsk zFGnG{loyH1H_XOiNbs1#{(O+Zw|-G@Fz@`Z``0R*ic5zmub>Orx|Tb9>bRFR?VRl0*3Ho%+fkA zxs(hnxD;(_MJu)8iJ3@}G6O2WMh$&NfdmK5dImJMCGUm`wBofZUcR{|ewubt5P{sb%qQO(N$!-o-tnO_;sI69A+RfJNO87pa8Dt}O;UmQ_WWiIuBb^lvffLP? zlhgp&4#1_al(ob@EVXX4usA8b&mq`h2dtY2mK_AedRAO^8uQDnSokc){H*mNbwZxB zbEvzb2=VuY<0q;@zL63wk^ngf+hxwssZMtRPeTT+90KHZxdmygp$G7Iso4 zF}ThriKwW;MdswZjeAh&EM;!pft%;TqNU#eYj<*z?1+qQzVspSVyrp-TW z*3!=CSfMhv-8r0*B{b@^-S*(S=?C*nsbyYM{U{3cN25m9SgzqHJh<7*^4agm9#)~* zlRo6Sq%Mc9$0KG!7I31G>5SO0<3$N7a|r5N+zr+N`!wp8w*}Yj`Byp?(Q%fTMt~98 zis5UuX8p@@W#RVOQXO#fy@4XQj!x!|BA&2OMng_y^XcA%X4^d#q}I92SB6R*ebU%N zPHl38K3n}Nx5VJp=TF}+5*_~rRd*RVNozxKlWBVVJ~ zDz_|79}pK1N8E3#y7MH&!=AF%smTBrjN~odFz_})=NK2fR$`>gd|l_TjCpsY7-fkC zw%kM2XOgy!*Hqz31U>Mo9nuz}3CUyv7QXZ>o~P~4UODcx+EN4qxdz=ST#1iHMv3kH ztI=^+*qm9mxi3KDv=Qef^nfYVcj_A7>=|bRC>Nb-YER&ml7~%p_Pn@BO?!bgY#yL) z{tiyZ&H6ea&j`2 z(h#diA6VTuqqcAK)2Iuk`vDoN`51A}R91?XvGzUuBCs(5mc1qi4Ui;nWF>~a{oD1b z9%A``7*!)B7fX}2d`3zuKgc$Z;)bBJAi9Q;-ME1inmd){u6TxP$oK#`GFI;pFd6&2 z(zid@H~>4kIzmoHoaU`#M#c}Yl*q=R-i3NAEstbcfy6c-YE{I5 zT73&Drg`Q&Lj|`p;+hH)VM0kS9@`cCv@f<4SoZEph{^i#Q_~phlxGqIqy)8W^7#t$ zcuL61kLN)^Wqs8A@i z*LB~xIcWqjZ0Hs52qzy#ZEh5-c3DiiAQ1A)%E;#iTfrWbXwF(U{my9bNp-ja_U7%| zq|RN*P`Fd*^s?0E<)v{l)n+E!VL@Q=;W-aLiSqR=pSb*sdmDSAHn?4*oYr71U8a-( z{Z0FI&dz~P4I2a}4gSqY zSW3qWoD@pEGv`F(RQG{-Bn9V-jO_-0_wDE0lZ5Rw1(d);_nss460P9tx)Rny)G84P zxdNy;ggwK|j~XjVl{ez+C?c%Cfi}2h+(pL=N@J>6JgBfLRKCJx1W@tR8%B078XpFU zE_0pK4>9Xj09TgwzNlA?X|_?F#+XWU$^sVJc0d zoQKP?^%|(XYNK(TqF32^K`TcYe|Pz+!5)p#z`oxM5x#;tx!hi;Owke z3OoFL$?S?k9p-nreZZfu39FHk?4HyHD=uxH21k-)0bBiC*vkf%KMdBtP21KB4I=k| zvG`57_6{GatXq6d2zImv1!b@2eqIm>pd1BIN)(0&j&28}Y)+*}?@W$(GaNHr)@3_Z zl1egNWG5}iTc=TXzaz=RYP>+!Nt?R6V5lN}O(2D-n|(}rDBLs{F1L5CVC?x})YBxN z!;2*xrvR&yjl)DdHgCYy6BQy&FT3we*0oU3(Hua9$}68{XKJlvN2K)$Xo=yrP1Uk# z=;O545b0nwi^~1$61gL*xmCYaw#kNo#)6kdpEvYk-2jLes@WZLeeEQ?*sX-;*HLn1 zl2^4*>&ax8fx@+EWC>kzLVp$^3yI&kJo@a#`{KW0H-|*yjLj+fgWY`Hn{K1RBJt5H z8#m0K>!{@Y6k+q3P_;zsaxF{U#`T;Mb3+Sf2UM3iwOfuyD5Q7fkw01brama#fRp)| z0x$@+ZJy5|-x4&Oq0R11w5X z42G9cP)}kEw=j8TB?fB4p9H;GQ_jgR_;1+C~*&)ebI#ukngGycx~Y+OzzA>!DN^5B?r)D z?%tIkY`Z>2O=2>Z;(8IwR{Lq(x>U-RwmfMxr+Nj(q=z^sMmxnW4jqI!ISKN9V`9tR z{D?)^9W~ROtFdX5UE3G4C6-d@t@NaH?f6JlahGMc3;%lNlqp1FmMiUvXaNTM&f98D z63vaRt2Md^E42E!{N3Kxe@uhloay3+ptzzaC6zp&yv!EpBzg+B)wX#eC186xI<5`+ zS1nlP33RYwN)lSm@M2#1S4;K~g(V>kcfRM3-4r-CXvo_+#vqd4Mr16n{6c+Ei*?R~ zhBZBE1?A(sv|MalmUT{GgmdTBu1PMhdCF6+>UGO{#&1yw^%&icTeKrG9Ky9DH$c%} zx$oQ?idT=hbdjDC2mQDQz1? zy_me{!NR3)oY%^(EIg8$pa0H#REHI2z{CJty}1S8K4!nSb>5H4*pKD`F-SWuG*|6` zM-4Dl$x^M*>Q>vF-OFQdZpUJ3aP?A%Lplxed|4s>2OmtjdzA1_kL8yM!cI}V7L-Zv zS08l)ZGr3a)Oz&syf1f976!xDY0REivM=~CTNA77CQ8G^F0$h?_Oc@*WWA+sI5neP%e)|lVmpe|Vz2n2D8(GonqF8R zmOT3Fy#vE$6eQ|#8$;n87N;ldOTxWD@|=?`uIHD>Vhg(Uio*nDLB!b6Pocv2uDaCiUup@;Ii&RU7c!IEAkdm>v zQhdURoWqCKB<($l)V%O!^Bvfn>jWeP|_-oZ_u7wtD&uwNU;9dDzW64oG0FR zi^?P*p&>wL*IH_SH{JYs++3AQ*7)7Xq(s6DJrCFZD&LA)n_vl{xBFu72dgjEED_O; zEM@g@Ly54zXrvP;6!!XV=fg`NMhm5_fGp3D-IL+61bIx;1m1II;&}u3;!lUMUB;RLS^YTyg|Gp!_7|-o7hOHa+C14Vi zP-wzl5Szxq#P;qI))=aXxhC>tO8*a+)RCoHyjk_s!}j4y(-iDNMFXn%ol`! zBS*_dY^Ol%TvYUX%1z0Inoew&TE2Qpr;#?kO0`14ZFPidek*bWOYVKcJCIzPV142S zlt?jL-0gvRvMjsG$_4eJj=SO3*<+)T;CKM`EUUg$O%eqyh5KPv14zoOaMP$jj#z(7 z7G7Na)F~@x^q|Xl_^Se)9+urfDi}MeKTHEoZx&=%VVja3qmSn~L78eIfL)lx=|MjF zqgT|9cS^Z8Z(Sy+$TG6YoZ{4xU%wM%PWyyJx*SDqSZMgd=% zl!dwCrR+W{U^U3bnGuPZ7VsNs=_szwBVHdXdFtB$Lerf;$j}sbZTOUQ@9N-V>;h;J zW=G%|ndlOTZQ2ao9dgi++pe-1VQ(WBT{mTqR<-?4Y5Q4x@vxruxTTqhq3__q2sc0+K4 zXGt7|b8H#=+p#a>>nYIF2kw4u(4%c1nMUJW-`hE<&8xnuPUm=pU_qxVr?zRRPO#L5 zQY&;`ry|i7JT9cb2(%;V1AV6>Mz1TtQm6=gEF}>fkDzyfKo`tdxVnOvo4J!^&4*Of zOLWK_EJ$gp)`7nJTr$jV#RKzfMj_%}S7a&j*|f?xlh`$lioN=Bk`mQvnWe#2y+Oel zI&$<0BKC^AOHnJ2bA}2m!&8;e3>|U&a5=#%E{r?;$~l#|gQ}d;;FesbG;?@VL#kMF z{@ZBv(rCS1Aqrp^UBz;fgZzrVIaXmF{kO`)DAI}YXEyH#$kenj-qgnQ08fuDt3<*M zlCDEI{vwknv>)ImptyIwm4od$if}iL+%hV{8|LDa+i_oMsF}&v)x2q#`>{XLmlAOG zEhnb$Hk2nmzO}lvqD^*JsW+tPf&SjQ{cW-F;BA7^4I#d6bo}1oN4Sv!)?~r7neaa6 z2$IPs&Xg;*)|e%OYvNj7L%TZ5wr?mJ-SEWbpVCy~cs@wDlU7Zr#;(WmtCvzF1p!ob z6{vzc+Cmk14RRY{kuVS4CdWchjl_Y0*oKC&7rdQPDC}V_)D%HKNiDUmNA6BkeYh|a z-8P5RUj)06eEy77Tz7k4aq~iIUnaH18vQ3Ef>{{j>Tb$XD|JK{KD^k`2+aJ z6Y+fhpA_8mkEp2Yw=aKBZvQ23(W8=DE1VDkx_64y?HZ6s`T~!TgFtvm_9mAZV!Qj@ zKLEnNn+FYb5fyTLk&AnN8yvvfX}$_Qytx|u8*MxYa;(~l zrbD|CCLW5VU3)Ps2yLsWby6P5t?K#ms)`e1VV^0xyAoY`Vvq*{Ewr6?Ckyb~Yp$81 z8!WNUu$^QWRqKfyHeG!#f5)eKvxZjVG3N?xB;SYxzlul@+(B0SOYU#MkipFF=BeUw zx}pdrqJQG(cGht{t5vxon$~xW${Ypo=_QtrBP_-&f42l{FYBMUNsh5Y;uPRXJ$(gz zs`1)4snL+JlQq|YFV)&T?FkwN(lIvTLl4PN7sbheQBQ#%{z94RemSQv$r_Ycs%Lqw zXsVip1s3DFNPI1>GBF+lcSL+>dc=@v9Z|pvc|cMB_TiLCCUn*EUh`3oF874Aep5P;aJr_r$sf7NDHQWNv%sC$- zPxmb5z55@H1pE(&5dMF0V*U-}wE8lQ?J*&5-iL>{>(n0!S7ZDQmA5?Bi(V zg&Q^?2>+!653)VhN>)fyWtDdm`J|3pHvNinHZU4ILh=#ez?JWS_z5!DP_m_tV&EJf zO4gZC;s8MXgfj5P5?l9b8z=6QG+M8~R9!yhab~zRWU5w5S7=jU+!k;f>$f7%@++Of z8yB2BXfLxfGNO#T9NWl1Sk`fi^6>90GXVzmL<5V&kpKW$ruUs`{A|~(wLaK2mdI&4 z^9r3RvT}O0f_4`EPd)9ocG9w(=NKd2@DoWzwbNaS)X*%OZI|M`fnQ(0)ZKR%Lo#SM zsG^+2Gp0$8n&`cQz)wn?QY8Kj6ZRz$Hf0G8in$M*PwDHKl|a5A^?O(j{d9C&eei|j zNz3IeE?}8NteD*M-$_)H9^48RyBfw)^X-4AU%Y=%eAvpcCaUAPrgE z;g+m_3h~xSv3fz;Hc(DKrSr7o{ZNp*{GUfwyS4ibAQ}0VQ8A%JZ1(y0jS_YcgLIRh z`!U)}42fTd!nPt+%A8zApqMr^0SQK6sG+_i^w^!@%ymRS^|7>OovL;~d8BwUd=_78 z_V_|6-j7S^Bug;s%A<;S{rdc{rwz(?xSV8#L0>KT;iEAWlCf z#;WjOMtKK6C|uZ#K<+CMu~gX;FRxv)9M6LrweLVcUrs){0X_1y^$ln7mMC(2R#ZWA z=Mz2b>Y9JN%9ugv;5qg*eQIF}jTIF-Euh~@%5uLX^*;Lt72|t}v<;sI6MX7=KnU>y z!#quAimmq#EvRIW7E$Zaj~@7CQy(YoIU8Z#3#p4*#(kW&1OZxW(s#+Z73*XnAek<3 z8vPLk+fQ2Jlor8osn`t4G<`f(I%imq(C>6bHKiR9N_IB+5uLZ6P~wT1{KhtQbiKPT z9j~ou$?#_Q$4Kc){1VG*j_j^1k`)d{hPEvv2FS7I4d3;HKTEqw5X%Pe z6d4yAB~!r(?^pLEy7td7z0WCK;+%zXJoVWf2S;|gF7BSm-WmBVtr|3v^pKySUwaD@x z5}dHCt$k)=vBY@AGjHyo3`k*9s?nu@v~E6^xMN3t_5r1tKcV;X30o92OAik z(uuYwcf{h(B*!??O$9M9E;-sh0{w*?EJ>&ov zPd0BK$@h&E8!JVmTrWiTfHyx=IQF~^5IS0emZ=2+kPVEWeNwj3n2ffU*mh9 zo#c$31xGLghF@kW)y75Y@=Lc&S}?~4I5S+Joxk>v*T3a#z0L5Jos4{O$iwU3R+Uz(09=9HNtfn^dcq}7+K>G_>4gQ^M=DvKm!DdgrTACj2kivZ1)1mrR%gUvp0VG ziak+}EVKW0-!@7r<0W(n8v2+-16Q64dWAzrRkzuZzwZab~K_oN`*MkgvLwhOFJHgC)OE89}iV8nf=8 z(tNP8pkUtKFO4A!uAuP}gd#f>WObVMp8iG=O$jsYSp%IpZ&^U7}?UT zVznlDQV~g5U1`y3ETkObL)T=OVeQXD*%*P6z;(#a16!=j=XQ)l?B80mt|LoVlga~o z{MCWk;l6@YF4Kll-Y0M77q(`|-39x%Nocz>d&v<6Dt#Di>ihj#8`UkJyd-_V-lj@a zbHoF7^VgLrI8Uxdl3#!KE98gZ&wl_jh&PI5C#sRWXHh|Q*@Mu z(qo$A-Q~W0*_g#Dk$9D)^cHEF#Cc<3j`OB{CQN$OT9mV>k|DT_Qj>@HxH`$L$#3;F zYM5+^%tU(I(OirU9HA3Td5d9=P&5RmA)Yhh z4bS!8b>vA&pW9gvA(%~bj31@^t7ywfR*CGlF3s8J9oSCTeww7|JCx^nvowROz9L?O z!Qd-;?wO(A`JD|q5%Z2_oYO8%@f8Gn?DR8jkAB+mxfc$^KMUe!1h8X|7d8fxmqCCqTFOcz>t5A&%0=I(=mPRe(IGPL>^zqgKsTB z<~#<3XCsc#c5A`YP+*<$m|8)~f(t%Cixw2t>d_jPNHI>Al1>o?%} z3swzrl$Az2HtIJ21*!s-0dnpkfJiymD@3lv?)tk$Z*PcUyX|n_m|4Ip20So1fXCw& z(W%bL*Q`lPJVmYnUe@BvTg`%ey{DrM*|Uf?pFP4<}w95(m#OT zJWo$pLFm6gO#jH8dgC>dD|O z%IF;bC0>xUA*4HRPg~WCp4+V9K-hj=a4CEWag*iHg+3-_QjM9~s?X*Q$|NcO4V4pq z<5^w(2QVsMt<%kCK(ocM0qnu=aBqp4zi}DG{R3F|(y{}z+RqN$m>t~rblU8%rfUQR zU~QAlDEKTG=1zGDnOd$I%3u8f0HA)!H3?%V>=&6}X4|a+slB#dZg;;lwX`aMo%@a^ ztR=e}*imJM^3A(kRB93XjeI|r->>excMA_@ejZi64+D;#YBu639u2>VdT^7sF$ZM@nb|HOv2h_pb>vqQfB_a zFF)_Mo?Y;6iTicDX0CU;wP*7vTz3X&3Xgm?Ed7gR(!n%!ewua|9E=$;;$l$b zB|k$Nl3e{WfAA@gjB5q)A#_g0>fmSn$?g(sVR+9e#G-|M4E0MJm@i(0a>)_A*g*E> z=S>hVg?b{wdkqx6?j;#t^}KS@5B(?>r4}L%0dIwJ%tI+s9`AW4@)njRsmMUr)Xxm5 zIB3CV&Mr8-BgGC1m-XKWHQqHmR2KKK>0Nwq_dy%$EnW$vJS%J!->5!^c}}$SVTBto z7GG&RBa1$CP0f;8s>au&o|p|8b~YEh!$v18a_J#UC#G*{M{5&n4v$|jQ1m#I3Xk97 zn8_H!}NAcZyZQHATva$v)GgEKseCWa}1l1DrDz_Q9!QGHGwfp z?;<7_s|C3Ebq;~Cx3hcsWZ{Y*=|Ek|9|QGu&1aW06Z&9B#?ZydqA8w^#VuW}3qnIu3RdJ)Nc6KPP{L zSwWC{e7%-&_!pb}^E2P$?-Zb4$v=;GGBrhy<`ZYdcG(7Y&{J3QR0_pq43M)fk*p2e;$|KtPYcDBR1Y8vkxKw5?$rR#hV0KP!4K33kNmsYv zq{2on_YmrWqWRlD8vsNoXecN#sJn=x;m>4pup2y8T`=8SxOGjrUeRM2cV@LiyF0Yl zwvF-2F^Zbl&f zrZnIdJ&!d4;lRMfl(43kO?ZcK6rfNX{lvndSHFo;E0lzQ z&(S}#q;InP0c<({oHw|-zs`IQ70PTA!ICBDeD&pq>|n0nlk%60_-=uV8b3V=4%#~e zIGB*&uYVDw5d}W7{~`%MdZziOOU%6`@_1gmcYpV2LyButbYiB)TbuUywi&o9GFtd) zNGz&4z4LQv8Irs7+Ye+-9gA9_!)1pj(O9Fa&SJgTwE6fN*3TDZipk6W+N`5c44cQH3Vb&i& z*6Pafm*dul&ibGKCaT!U3&CHvR{j2XqgY~{8f3$st9<3^V2y*FL(jn;PS=%PgHcB)lay?;390)R1cTV6 zP;OvPGPKw&oQP6FP0Kc(f?lnl0FlADSZ7=9InS1(9!&RZh{#8C7fLZ9U z-BOu&h_BOr*t~$RaBs}J=xGnleti7wi=1ZCzaWypm;gbKvrvKa2nv-zc`>?ad&AoijVU|Jc$Z|q=hWGZ!HYT;R}M`WkE#(jsz%0~2~#g- zNatTX(8@o{`&f`4=QN*8v zu%^0tqs#o@OG11Mjx8kygpGK0XP}EKNTUcjv-o6N(7Ebn1c}D*Ui+Q7{nPgEbnVtd z&HM0WM_-)Zl%9qrGGg+^I;&vS1^oX+hSuNT;X1En4{hg7`a5Oq+?m-WL^$r$o{C)S zYK{9s?1ISkmA_m@F2=!qrXQQtt}CH+d%n+`c6;8%cNi5^Sppz`B(4KZ( zwt5icQ`MTS5?$Q_#n4WAvk~`|O4f~2@;Efhh!K%kv!1@Cxp&*+WB|LKzI7UIfMgv_ zrK4bMSk0zUuotg`yGOy;I*66%>-Oeu#TI9G9${l+UP5M(P^#>9#HN-nSE} zEV6~ghPqOv8nTN9)7MdZTT}pQu+c(*S8GuJ@Qx^yr{a_=ix)?nSZ~jF$(@c*?Z`Iz zu_(6~wUr{DcgO*qhe!LBa~-8YyLK#Qma0#(+rO1GsBr>;=X|*GbjU6(5hntlSwJLK z)0rS?d>6*l-T*7QFONpwu`}Mc*DFl9fQ+FA=%PPw8Y~455M65BXy97I@-WDT4kN< zI_~reU*(x>VePClF7%vsyF#vmcs3gU8ybD+Iu;NuJ|}dK{>>H$(L03x(mSAF;o%YC zp<(_~JN}_}U|~~gz(Vv67cd4Dr&(|z91fSbnx?5M1+}DGP!juma{t%A6%Lrc6plUg zB8H~=5)ZE)B^%u}#RU;2$p~J-Y_x~+mBKPV&Q4~$tp3}#QFt_Hbyr$PA)BnS3*}#A zk?w|PEF>NMDaUvzr(Ub)2Ipuqx7&{fPVuTz_s0Gz7er?9e*jXUw9z@FA<$!qgZ{cg zokdUGE&D!-Ct3*b@~_pNeIK&g4Uc~QD?0_}&9M{#e*jV1D4M?4jGI4j9e*bB{PihH zwlnv-ajS0%yb?hvBYmISEiA~bYISfesM~t8Yy80y@?PMQ}wxTD)?-e{41j$THj{cUhO) ze*KYQJLUTcMwW3p(DN!)|F>&N%^5P|^9PHAUI+VMNXO#aElM^a&m#9(Y_ZDq>u z`~-;K_>4=P%FOG@Gk$1sN8;-T2Jdd$apx0vk=Q+yQGna53~a^9oemwgb7bqe$Jrd5 zcaM}Yrkax<3^voNR*XRC;9>*J~;;F+<2x4aS!C zAU(E5>0e#)KdXF@wd>NBoEn=u{ia!eZX*TH1{{PrK>e+S{tspJpQ_^5YOzF{-#p{H z_w;W7EFxg}8JkEBbWdf@58YI*?yR25+^yxK_t(euj5gjpzM4Xv)f1W9(-^sT94KMDNWLBz^*l=Mr$HXxP(EbmoOe8wJKWD>fGY;H6Wk>};P5l*P6y%dw49>e$^F$J)ad4CVCek_;tFeGHTyZY*u?PS^PiLy|{eOFF+ zj%dFstQUr(by`lSEOw(xn_!{2v}q<`C%vHYCLfsjid{ped#RGL7DiWC#QAStxJ1Wb zEiElA4oWDIUN#`1sBbaP9Pj0SmHZ#p_A^ojMUBs;|Hh)P>VIqds+8|Y!$by|VIKKO zUs!ovvKi&lc2*^uNbj#-$j3ENq+iV4=^k85n7oB2S*7YLE5RCc>vEa*qERKJs)v@P zB~DGrv60pv@sOz-q78(eJNgO%>g9sW*GHP|%y8|3OIl`dZ}JDK+eIf8TGo<{kn@*y zNtqt#ug+`g7jl@+bI7DO*rZR)x=wTMSLqtEWuB^^osT3j@=F=q_)n?^x-G7}c!-UO zifgc&iw>UZPzb2lO}~c1qY(VBDufyyvG?F zK|n+ZAw)o6!Vv@nWP$-iiC{QH0l5uABABQlA~(n(I*172J|c$%1j7}Da3cE* zLkNLE2arRBh~b{-K4*5uamStgWA~r!{(Y~j-q(Nh*Ilowy83mkX+^Ao`}jGye**`a zSwyMgNuZY`PTt5sNZNQx&1n;={&UvejQr`#d~e_ukZ1Kcq2%acw9(?`y?7wEK=EKs3RLv@}JLAs(4T@VL7zC@y zHi21(Cvu@bB~kF%7Z&3aQ|n_lL~{m;M3lI`i`PgskT^w3n0EKGwJ?A4-4QLzG4?Mq z9Fb<1JOc3cY`+YHq3w>DZc*%ZxI}G@VdR*RK1W6yNkvybO206QI)FML?NAphB`>PQ zo~CBRD4%lo=x`w7`m^6kfp~JUcDGp7rEzcOU(Md21TIYCQhxJxCB}Ihjd7>iX5Pqf zba5p3&h{IFDjo3tgEQIhbNqUP`}AkNPRgWtt4*p~7EE3kizT%#xLP%_f_qpeCV z-^VR{ZoPIq*Iz~Kt5Wr+@qQA%un)0+8FLkwef&Nlkh%X}DW#I5uC7iX1jbXlySrJo zww0BYjTFXh#N5_N0HeqJV9;}>^U1SuaS3^anR3y~OY)!er&blaRMi3t5TyYHs+VV& zm4HqSu}y!z=1L6dPb*k4FsufYEYM*Nc>8Q^B}=Q^;Uc+;DuS$+u5diKgsiPs^E7A^ zH+h(q3rhklsx_(Zq_G$kAe>(d8i)4L05cj8sZz>$(1(Tz8ii~cmPb7@2Gd}IR^>T2 zy7~n^VeaH-P4J~&_}_BBPR4Ij^2d{H*IWn);`gokr8)V^sZh z%h=;j`+f0K@)C#3I6W@AHfW;@yX|X~yYsf&i5uFK6!C?zKa7d@(g%O#UF(yIraYVVS-=V_!{aglJy<{-* zCX(-^7fbeLEW1#x*rqmAvTT!kfoYcCNM2#&t?;OEaW8JQW!TO` zdvdoX#NN$5l@yhVs##sLn#=z%G2$5jl};}O)7DGMP9cNN;3li9u)Ce{ z{e_w2)A0o_sS{&1(hdX7BkJ~-B3_1PV!kN2iZ56UF3;xn0i`o-@;+MSjBTF}? zMZ4wGzFuau84YZq&9v-=+}`!$z{G8x1G9OL7b-**yQ_`d-TVZQlw9{~hJKw>Z; z6!H!@dvWvjN#1ul@9Gap6&&X02#6T>I&|!9Z9??9tlpcIgqz0_wXskMx@GZ#{2dXi z?G$@76P`qnE2*JXl{5TqT~uqoUcK?CNNL}DtUEr%(j)}2{WaXu6=D30no}!Di}7W1 zDHN>~&{Vie@>-7B&%yFBpULPYr3Jk!G?hI*MT(3nMnV(#mdx?Ho8oB&oUBi>8wTZB z?K{sNKDf}fdAVcsiW^QjjI!kP_;VBUpo(+TDS{Jd*wb;De*!f)$zS_}s@g(1ndOVB z8w{NWUad0cHXkpmsTpIOteH$+xNV9eEzlSxXwl#Vf|a zBh}YEENZ}g-zOD_SUD+FU9EnP$*Ui|CtXycVRg>5PW6G;6TF5~{)48z!Wt~OycDJ5 z&-ayTvLQs#sn)7%x!fe^mGYQTL{+u1v2a)(7=5k_&eRsKBpmH_AV{-Mtc{gs%`A zzX1;R?UoX03O~|;eo1?(fkA{%*u45BQFki1S+QqbkX1x)ajSRL4SpHWI`35`YUeW_ z-#M;3yv??1waXv5AZl~4V(dkz%)ClcSAN?Cq*&jC1VRt?mOOSYJxAE-Wp31W#dDqY z5bk-i2D2G0P-v)T*DIdT>bLkx@1<~oR1Ty|oKtuzR#MapPduNkkBO1fjyUVK-W1n* zdS%5Jl0Cd~?wj`msiHlb&(j*GdB=`F(6r_vcsrJIlaFi2v{E1v^%RJkjg5^XRI-~) zCfnQFy8suii310ta)aVB6YI^6Mn3ILP8BMV!^6Q9^-?>xMVrFjZItI+Mq_UmVT%!ZQTsONvPX} z9w_@Q&GUZJ^O;^f&HXy7*hG!Dr7kU+LQ|lNm3pKG;7bK6Jv`!e;p?R{>c|}TL_cNc zUJRd@(Z4|a17B{4^CdX&^NJz2y5rJL-cO7orxDRcjeU_E+0CXIL`uW%AM-Fd!SOZ6 z-^;B*qJqylUulav2S&{JR#q&okl)p&D!@P>1PvysEtY{c27$oKH^*96w8(w@)YePa z9L2JPgpI#PwLBWwEL&CIc<20ai+*S}B^t}7ygKW6Xj?qf6&wtC@=^x!y^$M2zeL}yy)Vv1zB)@%@hOqM zbGQ#1A)+GXXKGB^re@~TiBzm6!|QK{&6}lz1!m^xo8v)F8mSLE;KjZR20GV}p7Wj8 zoorsU*DIguNg6No)bkIjA_}7v9FOXvzNHR4g%fpPQ^~M0H>sh=AmL(f`kA34Bu(-T zy9?JL`3r*qS?SnaRd*4%9X@ZLIFww=VVQY_ck-6fXKg8gnj(EQpl(bdK5{dy?PNsO z{KU0JE0N?Do;>&Cmc|<@@Hm#JaW1P*#ZbzidILBqfUPPm{8px{#hTImRj)2MhoJ literal 0 HcmV?d00001 diff --git a/screenshots/photo_2026-07-27_03-17-48.jpg b/screenshots/photo_2026-07-27_03-17-48.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3db4636cc2851ef5cc6e6801573a12f1a7ca1901 GIT binary patch literal 75248 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 QNUZwjB}s3DZ`sfP22oqGHUIzs literal 0 HcmV?d00001 diff --git a/screenshots/photo_2026-07-27_03-17-55.jpg b/screenshots/photo_2026-07-27_03-17-55.jpg new file mode 100644 index 0000000000000000000000000000000000000000..75cf3227043399b99cb19980bfe5c437e3b91ef8 GIT binary patch literal 86379 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 Jbns{Xe*j43FvS1> literal 0 HcmV?d00001 From 711fe5e9fee5f07c04899f56dc61135098fbbda5 Mon Sep 17 00:00:00 2001 From: Rishita Date: Sun, 2 Aug 2026 14:14:43 +0530 Subject: [PATCH 4/8] Pin httpx==0.27.2 in oldest test requirements to fix compatibility issue between groq 0.6.0 and httpx 0.23.0 --- .../tests/requirements.oldest.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/tests/requirements.oldest.txt b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/requirements.oldest.txt index 3af852be6..2c12cb100 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-groq/tests/requirements.oldest.txt +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/tests/requirements.oldest.txt @@ -20,3 +20,5 @@ # factor, so they are NOT pinned here — pyproject.toml is the single source of truth. The # OpenTelemetry SDK and test utilities come transitively from opentelemetry-test-util-genai, which # every oldest env installs. Pin here only test-only deps that nothing else already provides. + +httpx==0.27.2 \ No newline at end of file From 176566f04f21fe457fa31e9368ad5fae1287e0b4 Mon Sep 17 00:00:00 2001 From: Rishita Date: Sun, 2 Aug 2026 14:18:35 +0530 Subject: [PATCH 5/8] Update util README link in groq package --- .../opentelemetry-instrumentation-genai-groq/README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/README.rst b/instrumentation/opentelemetry-instrumentation-genai-groq/README.rst index 6dc75ae93..58b3d91e7 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-groq/README.rst +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/README.rst @@ -80,7 +80,7 @@ Install the ``upload`` extra to pull in ``fsspec``:: pip install opentelemetry-util-genai[upload] See the `opentelemetry-util-genai -`_ +`_ for additional options. Enabling the latest experimental features From 54f98123fdbd3a16b28bd1e29633efadb6a3c435 Mon Sep 17 00:00:00 2001 From: Rishita Date: Sun, 2 Aug 2026 15:55:54 +0530 Subject: [PATCH 6/8] Add asyncio_default_fixture_loop_scope to pytest.ini to silence pytest-asyncio warning --- pytest.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/pytest.ini b/pytest.ini index 886af1c76..bf1a6c984 100644 --- a/pytest.ini +++ b/pytest.ini @@ -3,3 +3,4 @@ addopts = -rfE -v log_cli = true log_cli_level = warning +asyncio_default_fixture_loop_scope = function From 240383a7cdf5ec30d1ed1778ce424e1c4c96a80e Mon Sep 17 00:00:00 2001 From: Rishita Date: Tue, 4 Aug 2026 14:22:37 +0530 Subject: [PATCH 7/8] Fix test matrix failures and linter issues - Added missing SPDX license headers to groq/package.py and groq/version.py - Ignored test_env directory in .codespellrc and scripts/check_license_header.py - Fixed shellcheck find command to exclude virtual environments - Stripped CRLF line endings from bash scripts - Added groq to instrumentation README --- .codespellrc | 2 +- instrumentation/README.md | 1 + .../instrumentation/genai/groq/package.py | 3 +++ .../instrumentation/genai/groq/version.py | 14 +------------- scripts/check_license_header.py | 1 + tox.ini | 6 +++--- 6 files changed, 10 insertions(+), 17 deletions(-) diff --git a/.codespellrc b/.codespellrc index e20054be5..f85d0dafd 100644 --- a/.codespellrc +++ b/.codespellrc @@ -3,5 +3,5 @@ [codespell] check-hidden = true # skipping auto generated folders -skip = ./.git,./.tox,./.venv,./.mypy_cache,./docs/_build,./target,*/LICENSE,./venv,*/cassettes +skip = ./.git,./.tox,./.venv,./test_env,./.mypy_cache,./docs/_build,./target,*/LICENSE,./venv,*/cassettes ignore-words-list = ot diff --git a/instrumentation/README.md b/instrumentation/README.md index 228b4672a..dc6e53668 100644 --- a/instrumentation/README.md +++ b/instrumentation/README.md @@ -4,6 +4,7 @@ | [opentelemetry-instrumentation-genai-agno](./opentelemetry-instrumentation-genai-agno) | agno >= 2.0.0 | No | development | [opentelemetry-instrumentation-genai-anthropic](./opentelemetry-instrumentation-genai-anthropic) | anthropic >= 0.16.0 | No | development | [opentelemetry-instrumentation-genai-claude-agent-sdk](./opentelemetry-instrumentation-genai-claude-agent-sdk) | claude-agent-sdk >= 0.1.14 | No | development +| [opentelemetry-instrumentation-genai-groq](./opentelemetry-instrumentation-genai-groq) | groq >= 0.6.0 | No | development | [opentelemetry-instrumentation-genai-langchain](./opentelemetry-instrumentation-genai-langchain) | langchain >= 0.3.21 | No | development | [opentelemetry-instrumentation-genai-llama-index](./opentelemetry-instrumentation-genai-llama-index) | llama-index-core >= 0.14.19 | No | development | [opentelemetry-instrumentation-genai-openai](./opentelemetry-instrumentation-genai-openai) | openai >= 1.26.0 | Yes | development diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/package.py b/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/package.py index 7cc4fab6e..150e9e2a9 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/package.py +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/package.py @@ -1 +1,4 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + _instruments = ("groq >= 0.6.0",) diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/version.py b/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/version.py index 0062fad57..d302c33ff 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/version.py +++ b/instrumentation/opentelemetry-instrumentation-genai-groq/src/opentelemetry/instrumentation/genai/groq/version.py @@ -1,15 +1,3 @@ # 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. - +# SPDX-License-Identifier: Apache-2.0 __version__ = "1.0b0.dev" diff --git a/scripts/check_license_header.py b/scripts/check_license_header.py index 500476344..286802c68 100644 --- a/scripts/check_license_header.py +++ b/scripts/check_license_header.py @@ -16,6 +16,7 @@ "target", ".tox", ".venv", + "test_env", "__pycache__", "node_modules", ) diff --git a/tox.ini b/tox.ini index 1d148030f..86f8c17ed 100644 --- a/tox.ini +++ b/tox.ini @@ -317,11 +317,11 @@ commands = [testenv:shellcheck] -commands_pre = - sh -c "sudo apt update -y && sudo apt install --assume-yes shellcheck" +# commands_pre = +# sh -c "sudo apt update -y && sudo apt install --assume-yes shellcheck" commands = - sh -c "find {toxinidir} -name \*.sh | xargs shellcheck --severity=warning" + sh -c "find {toxinidir} -type f -name \*.sh -not -path '*/.tox/*' -not -path '*/.venv/*' -not -path '*/test_env/*' | xargs --no-run-if-empty shellcheck --severity=warning" [testenv:{precommit,ruff}] basepython: python3 From 9478ba679cc8a73d12d4e9c701b8b0bcc1726672 Mon Sep 17 00:00:00 2001 From: Rishita Date: Wed, 5 Aug 2026 14:03:23 +0530 Subject: [PATCH 8/8] Fix changelog fragment naming to match PR number --- .../.changelog/1234.added | 1 - .../.changelog/{141.added => 313.added} | 0 2 files changed, 1 deletion(-) delete mode 100644 instrumentation/opentelemetry-instrumentation-genai-groq/.changelog/1234.added rename instrumentation/opentelemetry-instrumentation-genai-groq/.changelog/{141.added => 313.added} (100%) diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/.changelog/1234.added b/instrumentation/opentelemetry-instrumentation-genai-groq/.changelog/1234.added deleted file mode 100644 index 09b94586d..000000000 --- a/instrumentation/opentelemetry-instrumentation-genai-groq/.changelog/1234.added +++ /dev/null @@ -1 +0,0 @@ -Add Groq instrumentation diff --git a/instrumentation/opentelemetry-instrumentation-genai-groq/.changelog/141.added b/instrumentation/opentelemetry-instrumentation-genai-groq/.changelog/313.added similarity index 100% rename from instrumentation/opentelemetry-instrumentation-genai-groq/.changelog/141.added rename to instrumentation/opentelemetry-instrumentation-genai-groq/.changelog/313.added