ddtrace 3.11.0rc1__cp312-cp312-musllinux_1_2_aarch64.whl → 3.11.0rc3__cp312-cp312-musllinux_1_2_aarch64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ddtrace might be problematic. Click here for more details.
- ddtrace/_logger.py +5 -6
- ddtrace/_trace/product.py +1 -1
- ddtrace/_trace/sampling_rule.py +25 -33
- ddtrace/_trace/trace_handlers.py +12 -50
- ddtrace/_trace/utils_botocore/span_tags.py +48 -0
- ddtrace/_version.py +2 -2
- ddtrace/appsec/_asm_request_context.py +3 -1
- ddtrace/appsec/_constants.py +7 -0
- ddtrace/appsec/_handlers.py +11 -0
- ddtrace/appsec/_iast/_listener.py +12 -2
- ddtrace/appsec/_processor.py +1 -1
- ddtrace/contrib/integration_registry/registry.yaml +10 -0
- ddtrace/contrib/internal/aiobotocore/patch.py +8 -0
- ddtrace/contrib/internal/avro/__init__.py +17 -0
- ddtrace/contrib/internal/azure_functions/patch.py +23 -12
- ddtrace/contrib/internal/azure_functions/utils.py +14 -0
- ddtrace/contrib/internal/boto/patch.py +14 -0
- ddtrace/contrib/internal/botocore/__init__.py +153 -0
- ddtrace/contrib/internal/botocore/services/bedrock.py +3 -27
- ddtrace/contrib/internal/django/patch.py +31 -8
- ddtrace/contrib/{_freezegun.py → internal/freezegun/__init__.py} +1 -1
- ddtrace/contrib/internal/google_genai/_utils.py +2 -2
- ddtrace/contrib/internal/google_genai/patch.py +7 -7
- ddtrace/contrib/internal/google_generativeai/patch.py +7 -5
- ddtrace/contrib/internal/langchain/patch.py +11 -443
- ddtrace/contrib/internal/langchain/utils.py +0 -26
- ddtrace/contrib/internal/logbook/patch.py +1 -2
- ddtrace/contrib/internal/logging/patch.py +4 -7
- ddtrace/contrib/internal/loguru/patch.py +1 -3
- ddtrace/contrib/internal/openai_agents/patch.py +44 -1
- ddtrace/contrib/internal/protobuf/__init__.py +17 -0
- ddtrace/contrib/internal/pytest/__init__.py +62 -0
- ddtrace/contrib/internal/pytest/_plugin_v2.py +13 -4
- ddtrace/contrib/internal/pytest_bdd/__init__.py +23 -0
- ddtrace/contrib/internal/pytest_benchmark/__init__.py +3 -0
- ddtrace/contrib/internal/structlog/patch.py +2 -4
- ddtrace/contrib/internal/unittest/__init__.py +36 -0
- ddtrace/contrib/internal/vertexai/patch.py +7 -5
- ddtrace/ext/ci.py +20 -0
- ddtrace/ext/git.py +66 -11
- ddtrace/internal/_encoding.cpython-312-aarch64-linux-musl.so +0 -0
- ddtrace/internal/_encoding.pyi +1 -1
- ddtrace/internal/ci_visibility/encoder.py +126 -49
- ddtrace/internal/ci_visibility/utils.py +4 -4
- ddtrace/internal/core/__init__.py +5 -2
- ddtrace/internal/endpoints.py +76 -0
- ddtrace/internal/schema/processor.py +6 -2
- ddtrace/internal/telemetry/writer.py +18 -0
- ddtrace/internal/test_visibility/coverage_lines.py +4 -4
- ddtrace/internal/writer/writer.py +24 -11
- ddtrace/llmobs/_constants.py +3 -0
- ddtrace/llmobs/_experiment.py +75 -10
- ddtrace/llmobs/_integrations/bedrock.py +4 -0
- ddtrace/llmobs/_integrations/bedrock_agents.py +5 -1
- ddtrace/llmobs/_integrations/crewai.py +52 -3
- ddtrace/llmobs/_integrations/gemini.py +7 -7
- ddtrace/llmobs/_integrations/google_genai.py +10 -10
- ddtrace/llmobs/_integrations/{google_genai_utils.py → google_utils.py} +103 -7
- ddtrace/llmobs/_integrations/langchain.py +29 -20
- ddtrace/llmobs/_integrations/openai_agents.py +145 -0
- ddtrace/llmobs/_integrations/pydantic_ai.py +67 -26
- ddtrace/llmobs/_integrations/utils.py +68 -158
- ddtrace/llmobs/_integrations/vertexai.py +8 -8
- ddtrace/llmobs/_llmobs.py +83 -14
- ddtrace/llmobs/_telemetry.py +20 -5
- ddtrace/llmobs/_utils.py +27 -0
- ddtrace/settings/_config.py +1 -2
- ddtrace/settings/asm.py +9 -2
- ddtrace/settings/profiling.py +0 -9
- {ddtrace-3.11.0rc1.dist-info → ddtrace-3.11.0rc3.dist-info}/METADATA +1 -1
- {ddtrace-3.11.0rc1.dist-info → ddtrace-3.11.0rc3.dist-info}/RECORD +154 -160
- ddtrace/contrib/_avro.py +0 -17
- ddtrace/contrib/_botocore.py +0 -153
- ddtrace/contrib/_protobuf.py +0 -17
- ddtrace/contrib/_pytest.py +0 -62
- ddtrace/contrib/_pytest_bdd.py +0 -23
- ddtrace/contrib/_pytest_benchmark.py +0 -3
- ddtrace/contrib/_unittest.py +0 -36
- /ddtrace/contrib/{_aiobotocore.py → internal/aiobotocore/__init__.py} +0 -0
- /ddtrace/contrib/{_aiohttp_jinja2.py → internal/aiohttp_jinja2/__init__.py} +0 -0
- /ddtrace/contrib/{_aiomysql.py → internal/aiomysql/__init__.py} +0 -0
- /ddtrace/contrib/{_aiopg.py → internal/aiopg/__init__.py} +0 -0
- /ddtrace/contrib/{_aioredis.py → internal/aioredis/__init__.py} +0 -0
- /ddtrace/contrib/{_algoliasearch.py → internal/algoliasearch/__init__.py} +0 -0
- /ddtrace/contrib/{_anthropic.py → internal/anthropic/__init__.py} +0 -0
- /ddtrace/contrib/{_aredis.py → internal/aredis/__init__.py} +0 -0
- /ddtrace/contrib/{_asyncio.py → internal/asyncio/__init__.py} +0 -0
- /ddtrace/contrib/{_asyncpg.py → internal/asyncpg/__init__.py} +0 -0
- /ddtrace/contrib/{_aws_lambda.py → internal/aws_lambda/__init__.py} +0 -0
- /ddtrace/contrib/{_azure_functions.py → internal/azure_functions/__init__.py} +0 -0
- /ddtrace/contrib/{_azure_servicebus.py → internal/azure_servicebus/__init__.py} +0 -0
- /ddtrace/contrib/{_boto.py → internal/boto/__init__.py} +0 -0
- /ddtrace/contrib/{_cassandra.py → internal/cassandra/__init__.py} +0 -0
- /ddtrace/contrib/{_consul.py → internal/consul/__init__.py} +0 -0
- /ddtrace/contrib/{_coverage.py → internal/coverage/__init__.py} +0 -0
- /ddtrace/contrib/{_crewai.py → internal/crewai/__init__.py} +0 -0
- /ddtrace/contrib/{_django.py → internal/django/__init__.py} +0 -0
- /ddtrace/contrib/{_dogpile_cache.py → internal/dogpile_cache/__init__.py} +0 -0
- /ddtrace/contrib/{_dramatiq.py → internal/dramatiq/__init__.py} +0 -0
- /ddtrace/contrib/{_elasticsearch.py → internal/elasticsearch/__init__.py} +0 -0
- /ddtrace/contrib/{_fastapi.py → internal/fastapi/__init__.py} +0 -0
- /ddtrace/contrib/{_flask.py → internal/flask/__init__.py} +0 -0
- /ddtrace/contrib/{_futures.py → internal/futures/__init__.py} +0 -0
- /ddtrace/contrib/{_gevent.py → internal/gevent/__init__.py} +0 -0
- /ddtrace/contrib/{_google_genai.py → internal/google_genai/__init__.py} +0 -0
- /ddtrace/contrib/{_google_generativeai.py → internal/google_generativeai/__init__.py} +0 -0
- /ddtrace/contrib/{_graphql.py → internal/graphql/__init__.py} +0 -0
- /ddtrace/contrib/{_grpc.py → internal/grpc/__init__.py} +0 -0
- /ddtrace/contrib/{_gunicorn.py → internal/gunicorn/__init__.py} +0 -0
- /ddtrace/contrib/{_httplib.py → internal/httplib/__init__.py} +0 -0
- /ddtrace/contrib/{_httpx.py → internal/httpx/__init__.py} +0 -0
- /ddtrace/contrib/{_jinja2.py → internal/jinja2/__init__.py} +0 -0
- /ddtrace/contrib/{_kafka.py → internal/kafka/__init__.py} +0 -0
- /ddtrace/contrib/{_kombu.py → internal/kombu/__init__.py} +0 -0
- /ddtrace/contrib/{_langchain.py → internal/langchain/__init__.py} +0 -0
- /ddtrace/contrib/{_langgraph.py → internal/langgraph/__init__.py} +0 -0
- /ddtrace/contrib/{_litellm.py → internal/litellm/__init__.py} +0 -0
- /ddtrace/contrib/{_logbook.py → internal/logbook/__init__.py} +0 -0
- /ddtrace/contrib/{_logging.py → internal/logging/__init__.py} +0 -0
- /ddtrace/contrib/{_loguru.py → internal/loguru/__init__.py} +0 -0
- /ddtrace/contrib/{_mako.py → internal/mako/__init__.py} +0 -0
- /ddtrace/contrib/{_mariadb.py → internal/mariadb/__init__.py} +0 -0
- /ddtrace/contrib/{_mcp.py → internal/mcp/__init__.py} +0 -0
- /ddtrace/contrib/{_molten.py → internal/molten/__init__.py} +0 -0
- /ddtrace/contrib/{_mongoengine.py → internal/mongoengine/__init__.py} +0 -0
- /ddtrace/contrib/{_mysql.py → internal/mysql/__init__.py} +0 -0
- /ddtrace/contrib/{_mysqldb.py → internal/mysqldb/__init__.py} +0 -0
- /ddtrace/contrib/{_openai.py → internal/openai/__init__.py} +0 -0
- /ddtrace/contrib/{_openai_agents.py → internal/openai_agents/__init__.py} +0 -0
- /ddtrace/contrib/{_psycopg.py → internal/psycopg/__init__.py} +0 -0
- /ddtrace/contrib/{_pydantic_ai.py → internal/pydantic_ai/__init__.py} +0 -0
- /ddtrace/contrib/{_pymemcache.py → internal/pymemcache/__init__.py} +0 -0
- /ddtrace/contrib/{_pymongo.py → internal/pymongo/__init__.py} +0 -0
- /ddtrace/contrib/{_pymysql.py → internal/pymysql/__init__.py} +0 -0
- /ddtrace/contrib/{_pynamodb.py → internal/pynamodb/__init__.py} +0 -0
- /ddtrace/contrib/{_pyodbc.py → internal/pyodbc/__init__.py} +0 -0
- /ddtrace/contrib/{_redis.py → internal/redis/__init__.py} +0 -0
- /ddtrace/contrib/{_rediscluster.py → internal/rediscluster/__init__.py} +0 -0
- /ddtrace/contrib/{_rq.py → internal/rq/__init__.py} +0 -0
- /ddtrace/contrib/{_sanic.py → internal/sanic/__init__.py} +0 -0
- /ddtrace/contrib/{_selenium.py → internal/selenium/__init__.py} +0 -0
- /ddtrace/contrib/{_snowflake.py → internal/snowflake/__init__.py} +0 -0
- /ddtrace/contrib/{_sqlite3.py → internal/sqlite3/__init__.py} +0 -0
- /ddtrace/contrib/{_starlette.py → internal/starlette/__init__.py} +0 -0
- /ddtrace/contrib/{_structlog.py → internal/structlog/__init__.py} +0 -0
- /ddtrace/contrib/{_subprocess.py → internal/subprocess/__init__.py} +0 -0
- /ddtrace/contrib/{_urllib.py → internal/urllib/__init__.py} +0 -0
- /ddtrace/contrib/{_urllib3.py → internal/urllib3/__init__.py} +0 -0
- /ddtrace/contrib/{_vertexai.py → internal/vertexai/__init__.py} +0 -0
- /ddtrace/contrib/{_vertica.py → internal/vertica/__init__.py} +0 -0
- /ddtrace/contrib/{_webbrowser.py → internal/webbrowser/__init__.py} +0 -0
- /ddtrace/contrib/{_yaaredis.py → internal/yaaredis/__init__.py} +0 -0
- {ddtrace-3.11.0rc1.dist-info → ddtrace-3.11.0rc3.dist-info}/WHEEL +0 -0
- {ddtrace-3.11.0rc1.dist-info → ddtrace-3.11.0rc3.dist-info}/entry_points.txt +0 -0
- {ddtrace-3.11.0rc1.dist-info → ddtrace-3.11.0rc3.dist-info}/licenses/LICENSE +0 -0
- {ddtrace-3.11.0rc1.dist-info → ddtrace-3.11.0rc3.dist-info}/licenses/LICENSE.Apache +0 -0
- {ddtrace-3.11.0rc1.dist-info → ddtrace-3.11.0rc3.dist-info}/licenses/LICENSE.BSD3 +0 -0
- {ddtrace-3.11.0rc1.dist-info → ddtrace-3.11.0rc3.dist-info}/licenses/NOTICE +0 -0
- {ddtrace-3.11.0rc1.dist-info → ddtrace-3.11.0rc3.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,153 @@
|
|
1
|
+
"""
|
2
|
+
The Botocore integration will trace all AWS calls made with the botocore
|
3
|
+
library. Libraries like Boto3 that use Botocore will also be patched.
|
4
|
+
|
5
|
+
Enabling
|
6
|
+
~~~~~~~~
|
7
|
+
|
8
|
+
The botocore integration is enabled automatically when using
|
9
|
+
:ref:`ddtrace-run<ddtracerun>` or :ref:`import ddtrace.auto<ddtraceauto>`.
|
10
|
+
|
11
|
+
Or use :func:`patch()<ddtrace.patch>` to manually enable the integration::
|
12
|
+
|
13
|
+
from ddtrace import patch
|
14
|
+
patch(botocore=True)
|
15
|
+
|
16
|
+
To patch only specific botocore modules, pass a list of the module names instead::
|
17
|
+
|
18
|
+
from ddtrace import patch
|
19
|
+
patch(botocore=['s3', 'sns'])
|
20
|
+
|
21
|
+
Configuration
|
22
|
+
~~~~~~~~~~~~~
|
23
|
+
|
24
|
+
.. py:data:: ddtrace.config.botocore['distributed_tracing']
|
25
|
+
|
26
|
+
Whether to inject distributed tracing data to requests in SQS, SNS, EventBridge, Kinesis Streams and Lambda.
|
27
|
+
|
28
|
+
Can also be enabled with the ``DD_BOTOCORE_DISTRIBUTED_TRACING`` environment variable.
|
29
|
+
|
30
|
+
Example::
|
31
|
+
|
32
|
+
from ddtrace import config
|
33
|
+
|
34
|
+
# Enable distributed tracing
|
35
|
+
config.botocore['distributed_tracing'] = True
|
36
|
+
|
37
|
+
|
38
|
+
Default: ``True``
|
39
|
+
|
40
|
+
|
41
|
+
.. py:data:: ddtrace.config.botocore['invoke_with_legacy_context']
|
42
|
+
|
43
|
+
This preserves legacy behavior when tracing directly invoked Python and Node Lambda
|
44
|
+
functions instrumented with datadog-lambda-python < v41 or datadog-lambda-js < v3.58.0.
|
45
|
+
|
46
|
+
Legacy support for older libraries is available with
|
47
|
+
``ddtrace.config.botocore.invoke_with_legacy_context = True`` or by setting the environment
|
48
|
+
variable ``DD_BOTOCORE_INVOKE_WITH_LEGACY_CONTEXT=true``.
|
49
|
+
|
50
|
+
|
51
|
+
Default: ``False``
|
52
|
+
|
53
|
+
|
54
|
+
.. py:data:: ddtrace.config.botocore['operations'][<operation>].error_statuses = "<error statuses>"
|
55
|
+
|
56
|
+
Definition of which HTTP status codes to consider for making a span as an error span.
|
57
|
+
|
58
|
+
By default response status codes of ``'500-599'`` are considered as errors for all endpoints.
|
59
|
+
|
60
|
+
Example marking 404, and 5xx as errors for ``s3.headobject`` API calls::
|
61
|
+
|
62
|
+
from ddtrace import config
|
63
|
+
|
64
|
+
config.botocore['operations']['s3.headobject'].error_statuses = '404,500-599'
|
65
|
+
|
66
|
+
|
67
|
+
See :ref:`HTTP - Custom Error Codes<http-custom-error>` documentation for more examples.
|
68
|
+
|
69
|
+
.. py:data:: ddtrace.config.botocore['tag_no_params']
|
70
|
+
|
71
|
+
This opts out of the default behavior of collecting a narrow set of API parameters as span tags.
|
72
|
+
|
73
|
+
To not collect any API parameters, ``ddtrace.config.botocore.tag_no_params = True`` or by setting the environment
|
74
|
+
variable ``DD_AWS_TAG_NO_PARAMS=true``.
|
75
|
+
|
76
|
+
|
77
|
+
Default: ``False``
|
78
|
+
|
79
|
+
|
80
|
+
.. py:data:: ddtrace.config.botocore['instrument_internals']
|
81
|
+
|
82
|
+
This opts into collecting spans for some internal functions, including ``parsers.ResponseParser.parse``.
|
83
|
+
|
84
|
+
Can also be enabled with the ``DD_BOTOCORE_INSTRUMENT_INTERNALS`` environment variable.
|
85
|
+
|
86
|
+
Default: ``False``
|
87
|
+
|
88
|
+
|
89
|
+
.. py:data:: ddtrace.config.botocore['span_prompt_completion_sample_rate']
|
90
|
+
|
91
|
+
Configure the sample rate for the collection of bedrock prompts and completions as span tags.
|
92
|
+
|
93
|
+
Alternatively, you can set this option with the ``DD_BEDROCK_SPAN_PROMPT_COMPLETION_SAMPLE_RATE`` environment
|
94
|
+
variable.
|
95
|
+
|
96
|
+
Default: ``1.0``
|
97
|
+
|
98
|
+
|
99
|
+
.. py:data:: (beta) ddtrace.config.botocore["span_char_limit"]
|
100
|
+
|
101
|
+
Configure the maximum number of characters for bedrock span tags for prompt/response text.
|
102
|
+
|
103
|
+
Text exceeding the maximum number of characters is truncated to the character limit
|
104
|
+
and has ``...`` appended to the end.
|
105
|
+
|
106
|
+
Alternatively, you can set this option with the ``DD_BEDROCK_SPAN_CHAR_LIMIT`` environment
|
107
|
+
variable.
|
108
|
+
|
109
|
+
Default: ``128``
|
110
|
+
|
111
|
+
|
112
|
+
.. py:data:: ddtrace.config.botocore['dynamodb_primary_key_names_for_tables']
|
113
|
+
|
114
|
+
This enables DynamoDB API calls to be instrumented with span pointers. Many
|
115
|
+
DynamoDB API calls do not include the Item's Primary Key fields as separate
|
116
|
+
values, so they need to be provided to the tracer separately. This field
|
117
|
+
should be structured as a ``dict`` keyed by the table names as ``str``.
|
118
|
+
Each value should be the ``set`` of primary key field names (as ``str``)
|
119
|
+
for the associated table. The set may have exactly one or two elements,
|
120
|
+
depending on the Table's Primary Key schema.
|
121
|
+
|
122
|
+
In python this would look like::
|
123
|
+
|
124
|
+
ddtrace.config.botocore['dynamodb_primary_key_names_for_tables'] = {
|
125
|
+
'table_name': {'key1', 'key2'},
|
126
|
+
'other_table': {'other_key'},
|
127
|
+
}
|
128
|
+
|
129
|
+
Can also be enabled with the ``DD_BOTOCORE_DYNAMODB_TABLE_PRIMARY_KEYS``
|
130
|
+
environment variable which is parsed as a JSON object with strings for keys
|
131
|
+
and lists of strings for values.
|
132
|
+
|
133
|
+
This would look something like::
|
134
|
+
|
135
|
+
export DD_BOTOCORE_DYNAMODB_TABLE_PRIMARY_KEYS='{
|
136
|
+
"table_name": ["key1", "key2"],
|
137
|
+
"other_table": ["other_key"]
|
138
|
+
}'
|
139
|
+
|
140
|
+
Default: ``{}``
|
141
|
+
|
142
|
+
|
143
|
+
.. py:data:: ddtrace.config.botocore['add_span_pointers']
|
144
|
+
|
145
|
+
This enables the addition of span pointers to spans associated with
|
146
|
+
successful AWS API calls.
|
147
|
+
|
148
|
+
Alternatively, you can set this option with the
|
149
|
+
``DD_BOTOCORE_ADD_SPAN_POINTERS`` environment variable.
|
150
|
+
|
151
|
+
Default: ``True``
|
152
|
+
|
153
|
+
"""
|
@@ -48,12 +48,9 @@ class TracedBotocoreStreamingBody(wrapt.ObjectProxy):
|
|
48
48
|
self._body.append(json.loads(body))
|
49
49
|
if self.__wrapped__.tell() == int(self.__wrapped__._content_length):
|
50
50
|
formatted_response = _extract_text_and_response_reason(self._execution_ctx, self._body[0])
|
51
|
-
model_provider = self._execution_ctx["model_provider"]
|
52
|
-
model_name = self._execution_ctx["model_name"]
|
53
|
-
should_set_choice_ids = model_provider == _COHERE and "embed" not in model_name
|
54
51
|
core.dispatch(
|
55
52
|
"botocore.bedrock.process_response",
|
56
|
-
[self._execution_ctx, formatted_response
|
53
|
+
[self._execution_ctx, formatted_response],
|
57
54
|
)
|
58
55
|
return body
|
59
56
|
except Exception:
|
@@ -67,12 +64,9 @@ class TracedBotocoreStreamingBody(wrapt.ObjectProxy):
|
|
67
64
|
for line in lines:
|
68
65
|
self._body.append(json.loads(line))
|
69
66
|
formatted_response = _extract_text_and_response_reason(self._execution_ctx, self._body[0])
|
70
|
-
model_provider = self._execution_ctx["model_provider"]
|
71
|
-
model_name = self._execution_ctx["model_name"]
|
72
|
-
should_set_choice_ids = model_provider == _COHERE and "embed" not in model_name
|
73
67
|
core.dispatch(
|
74
68
|
"botocore.bedrock.process_response",
|
75
|
-
[self._execution_ctx, formatted_response
|
69
|
+
[self._execution_ctx, formatted_response],
|
76
70
|
)
|
77
71
|
return lines
|
78
72
|
except Exception:
|
@@ -93,16 +87,10 @@ class TracedBotocoreStreamingBody(wrapt.ObjectProxy):
|
|
93
87
|
finally:
|
94
88
|
if exception_raised:
|
95
89
|
return
|
96
|
-
metadata = _extract_streamed_response_metadata(self._execution_ctx, self._body)
|
97
90
|
formatted_response = _extract_streamed_response(self._execution_ctx, self._body)
|
98
|
-
model_provider = self._execution_ctx["model_provider"]
|
99
|
-
model_name = self._execution_ctx["model_name"]
|
100
|
-
should_set_choice_ids = (
|
101
|
-
model_provider == _COHERE and "is_finished" not in self._body[0] and "embed" not in model_name
|
102
|
-
)
|
103
91
|
core.dispatch(
|
104
92
|
"botocore.bedrock.process_response",
|
105
|
-
[self._execution_ctx, formatted_response
|
93
|
+
[self._execution_ctx, formatted_response],
|
106
94
|
)
|
107
95
|
|
108
96
|
|
@@ -443,18 +431,6 @@ def handle_bedrock_response(
|
|
443
431
|
safe_token_count(cache_write_tokens),
|
444
432
|
)
|
445
433
|
|
446
|
-
# for both converse & invoke, dispatch success event to store basic metrics
|
447
|
-
core.dispatch(
|
448
|
-
"botocore.patched_bedrock_api_call.success",
|
449
|
-
[
|
450
|
-
ctx,
|
451
|
-
str(metadata.get("RequestId", "")),
|
452
|
-
request_latency,
|
453
|
-
str(input_tokens),
|
454
|
-
str(output_tokens),
|
455
|
-
],
|
456
|
-
)
|
457
|
-
|
458
434
|
if ctx["resource"] == "Converse":
|
459
435
|
core.dispatch("botocore.bedrock.process_response_converse", [ctx, result])
|
460
436
|
return result
|
@@ -49,6 +49,7 @@ from ddtrace.internal.utils.formats import asbool
|
|
49
49
|
from ddtrace.internal.utils.importlib import func_name
|
50
50
|
from ddtrace.propagation._database_monitoring import _DBM_Propagator
|
51
51
|
from ddtrace.settings.asm import config as asm_config
|
52
|
+
from ddtrace.settings.asm import endpoint_collection
|
52
53
|
from ddtrace.settings.integration import IntegrationConfig
|
53
54
|
from ddtrace.trace import Pin
|
54
55
|
from ddtrace.vendor.packaging.version import parse as parse_version
|
@@ -81,6 +82,7 @@ config._add(
|
|
81
82
|
use_legacy_resource_format=asbool(os.getenv("DD_DJANGO_USE_LEGACY_RESOURCE_FORMAT", default=False)),
|
82
83
|
_trace_asgi_websocket=os.getenv("DD_ASGI_TRACE_WEBSOCKET", default=False),
|
83
84
|
obfuscate_404_resource=os.getenv("DD_ASGI_OBFUSCATE_404_RESOURCE", default=False),
|
85
|
+
views={},
|
84
86
|
),
|
85
87
|
)
|
86
88
|
|
@@ -598,7 +600,7 @@ def traced_template_render(django, pin, wrapped, instance, args, kwargs):
|
|
598
600
|
return wrapped(*args, **kwargs)
|
599
601
|
|
600
602
|
|
601
|
-
def instrument_view(django, view):
|
603
|
+
def instrument_view(django, view, path=None):
|
602
604
|
"""
|
603
605
|
Helper to wrap Django views.
|
604
606
|
|
@@ -608,10 +610,24 @@ def instrument_view(django, view):
|
|
608
610
|
for cls in reversed(getmro(view)):
|
609
611
|
_instrument_view(django, cls)
|
610
612
|
|
611
|
-
return _instrument_view(django, view)
|
613
|
+
return _instrument_view(django, view, path=path)
|
612
614
|
|
613
615
|
|
614
|
-
def
|
616
|
+
def extract_request_method_list(view):
|
617
|
+
try:
|
618
|
+
while "view_func" in view.__code__.co_freevars:
|
619
|
+
view = view.__closure__[view.__code__.co_freevars.index("view_func")].cell_contents
|
620
|
+
if "request_method_list" in view.__code__.co_freevars:
|
621
|
+
return view.__closure__[view.__code__.co_freevars.index("request_method_list")].cell_contents
|
622
|
+
return []
|
623
|
+
except Exception:
|
624
|
+
return []
|
625
|
+
|
626
|
+
|
627
|
+
_DEFAULT_METHODS = ("get", "delete", "post", "options", "head")
|
628
|
+
|
629
|
+
|
630
|
+
def _instrument_view(django, view, path=None):
|
615
631
|
"""Helper to wrap Django views."""
|
616
632
|
from . import utils
|
617
633
|
|
@@ -620,9 +636,14 @@ def _instrument_view(django, view):
|
|
620
636
|
return view
|
621
637
|
|
622
638
|
# Patch view HTTP methods and lifecycle methods
|
623
|
-
|
639
|
+
|
640
|
+
http_method_names = getattr(view, "http_method_names", ())
|
641
|
+
request_method_list = extract_request_method_list(view) or http_method_names
|
642
|
+
if path is not None:
|
643
|
+
for method in request_method_list or ["*"]:
|
644
|
+
endpoint_collection.add_endpoint(method, path, operation_name="django.request")
|
624
645
|
lifecycle_methods = ("setup", "dispatch", "http_method_not_allowed")
|
625
|
-
for name in list(
|
646
|
+
for name in list(request_method_list or _DEFAULT_METHODS) + list(lifecycle_methods):
|
626
647
|
try:
|
627
648
|
func = getattr(view, name, None)
|
628
649
|
if not func or isinstance(func, wrapt.ObjectProxy):
|
@@ -665,18 +686,20 @@ def traced_urls_path(django, pin, wrapped, instance, args, kwargs):
|
|
665
686
|
try:
|
666
687
|
from_args = False
|
667
688
|
view = kwargs.pop("view", None)
|
689
|
+
path = kwargs.pop("path", None)
|
668
690
|
if view is None:
|
669
691
|
view = args[1]
|
670
692
|
from_args = True
|
693
|
+
if path is None:
|
694
|
+
path = args[0]
|
671
695
|
|
672
696
|
core.dispatch("service_entrypoint.patch", (unwrap(view),))
|
673
|
-
|
674
697
|
if from_args:
|
675
698
|
args = list(args)
|
676
|
-
args[1] = instrument_view(django, view)
|
699
|
+
args[1] = instrument_view(django, view, path=path)
|
677
700
|
args = tuple(args)
|
678
701
|
else:
|
679
|
-
kwargs["view"] = instrument_view(django, view)
|
702
|
+
kwargs["view"] = instrument_view(django, view, path=path)
|
680
703
|
except Exception:
|
681
704
|
log.debug("Failed to instrument Django url path %r %r", args, kwargs, exc_info=True)
|
682
705
|
return wrapped(*args, **kwargs)
|
@@ -6,7 +6,7 @@ from typing import Optional
|
|
6
6
|
|
7
7
|
import wrapt
|
8
8
|
|
9
|
-
from ddtrace.llmobs._integrations.
|
9
|
+
from ddtrace.llmobs._integrations.google_utils import GOOGLE_GENAI_DEFAULT_MODEL_ROLE
|
10
10
|
from ddtrace.llmobs._utils import _get_attr
|
11
11
|
|
12
12
|
|
@@ -32,7 +32,7 @@ def _join_chunks(chunks: List[Any]) -> Optional[Dict[str, Any]]:
|
|
32
32
|
continue
|
33
33
|
|
34
34
|
if role is None:
|
35
|
-
role = _get_attr(content, "role",
|
35
|
+
role = _get_attr(content, "role", GOOGLE_GENAI_DEFAULT_MODEL_ROLE)
|
36
36
|
|
37
37
|
parts = _get_attr(content, "parts", [])
|
38
38
|
for part in parts:
|
@@ -9,7 +9,7 @@ from ddtrace.contrib.internal.trace_utils import unwrap
|
|
9
9
|
from ddtrace.contrib.internal.trace_utils import with_traced_module
|
10
10
|
from ddtrace.contrib.internal.trace_utils import wrap
|
11
11
|
from ddtrace.llmobs._integrations import GoogleGenAIIntegration
|
12
|
-
from ddtrace.llmobs._integrations.
|
12
|
+
from ddtrace.llmobs._integrations.google_utils import extract_provider_and_model_name
|
13
13
|
from ddtrace.trace import Pin
|
14
14
|
|
15
15
|
|
@@ -27,7 +27,7 @@ def get_version() -> str:
|
|
27
27
|
@with_traced_module
|
28
28
|
def traced_generate(genai, pin, func, instance, args, kwargs):
|
29
29
|
integration = genai._datadog_integration
|
30
|
-
provider_name, model_name = extract_provider_and_model_name(kwargs)
|
30
|
+
provider_name, model_name = extract_provider_and_model_name(kwargs=kwargs)
|
31
31
|
with integration.trace(
|
32
32
|
pin,
|
33
33
|
"%s.%s" % (instance.__class__.__name__, func.__name__),
|
@@ -46,7 +46,7 @@ def traced_generate(genai, pin, func, instance, args, kwargs):
|
|
46
46
|
@with_traced_module
|
47
47
|
async def traced_async_generate(genai, pin, func, instance, args, kwargs):
|
48
48
|
integration = genai._datadog_integration
|
49
|
-
provider_name, model_name = extract_provider_and_model_name(kwargs)
|
49
|
+
provider_name, model_name = extract_provider_and_model_name(kwargs=kwargs)
|
50
50
|
with integration.trace(
|
51
51
|
pin,
|
52
52
|
"%s.%s" % (instance.__class__.__name__, func.__name__),
|
@@ -65,7 +65,7 @@ async def traced_async_generate(genai, pin, func, instance, args, kwargs):
|
|
65
65
|
@with_traced_module
|
66
66
|
def traced_generate_stream(genai, pin, func, instance, args, kwargs):
|
67
67
|
integration = genai._datadog_integration
|
68
|
-
provider_name, model_name = extract_provider_and_model_name(kwargs)
|
68
|
+
provider_name, model_name = extract_provider_and_model_name(kwargs=kwargs)
|
69
69
|
span = integration.trace(
|
70
70
|
pin,
|
71
71
|
"%s.%s" % (instance.__class__.__name__, func.__name__),
|
@@ -86,7 +86,7 @@ def traced_generate_stream(genai, pin, func, instance, args, kwargs):
|
|
86
86
|
@with_traced_module
|
87
87
|
async def traced_async_generate_stream(genai, pin, func, instance, args, kwargs):
|
88
88
|
integration = genai._datadog_integration
|
89
|
-
provider_name, model_name = extract_provider_and_model_name(kwargs)
|
89
|
+
provider_name, model_name = extract_provider_and_model_name(kwargs=kwargs)
|
90
90
|
span = integration.trace(
|
91
91
|
pin,
|
92
92
|
"%s.%s" % (instance.__class__.__name__, func.__name__),
|
@@ -107,7 +107,7 @@ async def traced_async_generate_stream(genai, pin, func, instance, args, kwargs)
|
|
107
107
|
@with_traced_module
|
108
108
|
def traced_embed_content(genai, pin, func, instance, args, kwargs):
|
109
109
|
integration = genai._datadog_integration
|
110
|
-
provider_name, model_name = extract_provider_and_model_name(kwargs)
|
110
|
+
provider_name, model_name = extract_provider_and_model_name(kwargs=kwargs)
|
111
111
|
with integration.trace(
|
112
112
|
pin,
|
113
113
|
"%s.%s" % (instance.__class__.__name__, func.__name__),
|
@@ -126,7 +126,7 @@ def traced_embed_content(genai, pin, func, instance, args, kwargs):
|
|
126
126
|
@with_traced_module
|
127
127
|
async def traced_async_embed_content(genai, pin, func, instance, args, kwargs):
|
128
128
|
integration = genai._datadog_integration
|
129
|
-
provider_name, model_name = extract_provider_and_model_name(kwargs)
|
129
|
+
provider_name, model_name = extract_provider_and_model_name(kwargs=kwargs)
|
130
130
|
with integration.trace(
|
131
131
|
pin,
|
132
132
|
"%s.%s" % (instance.__class__.__name__, func.__name__),
|
@@ -11,7 +11,7 @@ from ddtrace.contrib.internal.trace_utils import unwrap
|
|
11
11
|
from ddtrace.contrib.internal.trace_utils import with_traced_module
|
12
12
|
from ddtrace.contrib.internal.trace_utils import wrap
|
13
13
|
from ddtrace.llmobs._integrations import GeminiIntegration
|
14
|
-
from ddtrace.llmobs._integrations.
|
14
|
+
from ddtrace.llmobs._integrations.google_utils import extract_provider_and_model_name
|
15
15
|
from ddtrace.trace import Pin
|
16
16
|
|
17
17
|
|
@@ -40,11 +40,12 @@ def traced_generate(genai, pin, func, instance, args, kwargs):
|
|
40
40
|
integration = genai._datadog_integration
|
41
41
|
stream = kwargs.get("stream", False)
|
42
42
|
generations = None
|
43
|
+
provider_name, model_name = extract_provider_and_model_name(instance=instance, model_name_attr="model_name")
|
43
44
|
span = integration.trace(
|
44
45
|
pin,
|
45
46
|
"%s.%s" % (instance.__class__.__name__, func.__name__),
|
46
|
-
provider=
|
47
|
-
model=
|
47
|
+
provider=provider_name,
|
48
|
+
model=model_name,
|
48
49
|
submit_to_llmobs=True,
|
49
50
|
)
|
50
51
|
try:
|
@@ -68,11 +69,12 @@ async def traced_agenerate(genai, pin, func, instance, args, kwargs):
|
|
68
69
|
integration = genai._datadog_integration
|
69
70
|
stream = kwargs.get("stream", False)
|
70
71
|
generations = None
|
72
|
+
provider_name, model_name = extract_provider_and_model_name(instance=instance, model_name_attr="model_name")
|
71
73
|
span = integration.trace(
|
72
74
|
pin,
|
73
75
|
"%s.%s" % (instance.__class__.__name__, func.__name__),
|
74
|
-
provider=
|
75
|
-
model=
|
76
|
+
provider=provider_name,
|
77
|
+
model=model_name,
|
76
78
|
submit_to_llmobs=True,
|
77
79
|
)
|
78
80
|
try:
|