ddtrace 3.11.0rc1__cp311-cp311-musllinux_1_2_i686.whl → 3.11.0rc3__cp311-cp311-musllinux_1_2_i686.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-311-i386-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
@@ -3,10 +3,8 @@ import sys
|
|
3
3
|
from typing import Any
|
4
4
|
from typing import Dict
|
5
5
|
from typing import Optional
|
6
|
-
from typing import Union
|
7
6
|
|
8
7
|
import langchain
|
9
|
-
from pydantic import SecretStr
|
10
8
|
|
11
9
|
|
12
10
|
try:
|
@@ -38,11 +36,9 @@ except ImportError:
|
|
38
36
|
import wrapt
|
39
37
|
|
40
38
|
from ddtrace import config
|
41
|
-
from ddtrace.contrib.internal.langchain.constants import API_KEY
|
42
39
|
from ddtrace.contrib.internal.langchain.constants import text_embedding_models
|
43
40
|
from ddtrace.contrib.internal.langchain.constants import vectorstore_classes
|
44
41
|
from ddtrace.contrib.internal.langchain.utils import shared_stream
|
45
|
-
from ddtrace.contrib.internal.langchain.utils import tag_general_message_input
|
46
42
|
from ddtrace.contrib.internal.trace_utils import unwrap
|
47
43
|
from ddtrace.contrib.internal.trace_utils import with_traced_module
|
48
44
|
from ddtrace.contrib.internal.trace_utils import wrap
|
@@ -69,7 +65,6 @@ def get_version():
|
|
69
65
|
config._add(
|
70
66
|
"langchain",
|
71
67
|
{
|
72
|
-
"span_prompt_completion_sample_rate": float(os.getenv("DD_LANGCHAIN_SPAN_PROMPT_COMPLETION_SAMPLE_RATE", 1.0)),
|
73
68
|
"span_char_limit": int(os.getenv("DD_LANGCHAIN_SPAN_CHAR_LIMIT", 128)),
|
74
69
|
},
|
75
70
|
)
|
@@ -87,91 +82,12 @@ def _extract_model_name(instance: Any) -> Optional[str]:
|
|
87
82
|
return None
|
88
83
|
|
89
84
|
|
90
|
-
def _format_api_key(api_key: Union[str, SecretStr]) -> str:
|
91
|
-
"""Obfuscate a given LLM provider API key by returning the last four characters."""
|
92
|
-
if hasattr(api_key, "get_secret_value"):
|
93
|
-
api_key = api_key.get_secret_value()
|
94
|
-
|
95
|
-
if not api_key or len(api_key) < 4:
|
96
|
-
return ""
|
97
|
-
return "...%s" % api_key[-4:]
|
98
|
-
|
99
|
-
|
100
|
-
def _extract_api_key(instance: Any) -> str:
|
101
|
-
"""
|
102
|
-
Extract and format LLM-provider API key from instance.
|
103
|
-
Note that langchain's LLM/ChatModel/Embeddings interfaces do not have a
|
104
|
-
standard attribute name for storing the provider-specific API key, so make a
|
105
|
-
best effort here by checking for attributes that end with `api_key/api_token`.
|
106
|
-
"""
|
107
|
-
api_key_attrs = [a for a in dir(instance) if a.endswith(("api_token", "api_key"))]
|
108
|
-
if api_key_attrs and hasattr(instance, str(api_key_attrs[0])):
|
109
|
-
api_key = getattr(instance, api_key_attrs[0], None)
|
110
|
-
if api_key:
|
111
|
-
return _format_api_key(api_key)
|
112
|
-
return ""
|
113
|
-
|
114
|
-
|
115
|
-
def _tag_openai_token_usage(span: Span, llm_output: Dict[str, Any]) -> None:
|
116
|
-
"""
|
117
|
-
Extract token usage from llm_output, tag on span.
|
118
|
-
Calculate the total cost for each LLM/chat_model, then propagate those values up the trace so that
|
119
|
-
the root span will store the total token_usage/cost of all of its descendants.
|
120
|
-
"""
|
121
|
-
for token_type in ("prompt", "completion", "total"):
|
122
|
-
current_metric_value = span.get_metric("langchain.tokens.%s_tokens" % token_type) or 0
|
123
|
-
metric_value = llm_output["token_usage"].get("%s_tokens" % token_type, 0)
|
124
|
-
span.set_metric("langchain.tokens.%s_tokens" % token_type, current_metric_value + metric_value)
|
125
|
-
|
126
|
-
|
127
|
-
def _is_openai_llm_instance(instance):
|
128
|
-
"""Safely check if a traced instance is an OpenAI LLM.
|
129
|
-
langchain_community does not automatically import submodules which may result in AttributeErrors.
|
130
|
-
"""
|
131
|
-
try:
|
132
|
-
if langchain_openai:
|
133
|
-
return isinstance(instance, langchain_openai.OpenAI)
|
134
|
-
if langchain_community:
|
135
|
-
return isinstance(instance, langchain_community.llms.OpenAI)
|
136
|
-
return False
|
137
|
-
except (AttributeError, ModuleNotFoundError, ImportError):
|
138
|
-
return False
|
139
|
-
|
140
|
-
|
141
|
-
def _is_openai_chat_instance(instance):
|
142
|
-
"""Safely check if a traced instance is an OpenAI Chat Model.
|
143
|
-
langchain_community does not automatically import submodules which may result in AttributeErrors.
|
144
|
-
"""
|
145
|
-
try:
|
146
|
-
if langchain_openai:
|
147
|
-
return isinstance(instance, langchain_openai.ChatOpenAI)
|
148
|
-
if langchain_community:
|
149
|
-
return isinstance(instance, langchain_community.chat_models.ChatOpenAI)
|
150
|
-
return False
|
151
|
-
except (AttributeError, ModuleNotFoundError, ImportError):
|
152
|
-
return False
|
153
|
-
|
154
|
-
|
155
|
-
def _is_pinecone_vectorstore_instance(instance):
|
156
|
-
"""Safely check if a traced instance is a Pinecone VectorStore.
|
157
|
-
langchain_community does not automatically import submodules which may result in AttributeErrors.
|
158
|
-
"""
|
159
|
-
try:
|
160
|
-
if langchain_pinecone:
|
161
|
-
return isinstance(instance, langchain_pinecone.PineconeVectorStore)
|
162
|
-
if langchain_community:
|
163
|
-
return isinstance(instance, langchain_community.vectorstores.Pinecone)
|
164
|
-
return False
|
165
|
-
except (AttributeError, ModuleNotFoundError, ImportError):
|
166
|
-
return False
|
167
|
-
|
168
|
-
|
169
85
|
@with_traced_module
|
170
86
|
def traced_llm_generate(langchain, pin, func, instance, args, kwargs):
|
171
87
|
llm_provider = instance._llm_type
|
172
|
-
prompts = get_argument_value(args, kwargs, 0, "prompts")
|
173
88
|
integration = langchain._datadog_integration
|
174
89
|
model = _extract_model_name(instance)
|
90
|
+
prompts = get_argument_value(args, kwargs, 0, "prompts")
|
175
91
|
span = integration.trace(
|
176
92
|
pin,
|
177
93
|
"%s.%s" % (instance.__module__, instance.__class__.__name__),
|
@@ -179,7 +95,6 @@ def traced_llm_generate(langchain, pin, func, instance, args, kwargs):
|
|
179
95
|
interface_type="llm",
|
180
96
|
provider=llm_provider,
|
181
97
|
model=model,
|
182
|
-
api_key=_extract_api_key(instance),
|
183
98
|
instance=instance,
|
184
99
|
)
|
185
100
|
completions = None
|
@@ -187,39 +102,13 @@ def traced_llm_generate(langchain, pin, func, instance, args, kwargs):
|
|
187
102
|
integration.record_instance(instance, span)
|
188
103
|
|
189
104
|
try:
|
190
|
-
if integration.is_pc_sampled_span(span):
|
191
|
-
for idx, prompt in enumerate(prompts):
|
192
|
-
span.set_tag_str("langchain.request.prompts.%d" % idx, integration.trunc(str(prompt)))
|
193
|
-
for param, val in getattr(instance, "_identifying_params", {}).items():
|
194
|
-
if isinstance(val, dict):
|
195
|
-
for k, v in val.items():
|
196
|
-
span.set_tag_str("langchain.request.%s.parameters.%s.%s" % (llm_provider, param, k), str(v))
|
197
|
-
else:
|
198
|
-
span.set_tag_str("langchain.request.%s.parameters.%s" % (llm_provider, param), str(val))
|
199
|
-
|
200
105
|
completions = func(*args, **kwargs)
|
201
|
-
|
202
106
|
core.dispatch("langchain.llm.generate.after", (prompts, completions))
|
203
|
-
|
204
|
-
if _is_openai_llm_instance(instance):
|
205
|
-
_tag_openai_token_usage(span, completions.llm_output)
|
206
|
-
|
207
|
-
for idx, completion in enumerate(completions.generations):
|
208
|
-
if integration.is_pc_sampled_span(span):
|
209
|
-
span.set_tag_str("langchain.response.completions.%d.text" % idx, integration.trunc(completion[0].text))
|
210
|
-
if completion and completion[0].generation_info is not None:
|
211
|
-
span.set_tag_str(
|
212
|
-
"langchain.response.completions.%d.finish_reason" % idx,
|
213
|
-
str(completion[0].generation_info.get("finish_reason")),
|
214
|
-
)
|
215
|
-
span.set_tag_str(
|
216
|
-
"langchain.response.completions.%d.logprobs" % idx,
|
217
|
-
str(completion[0].generation_info.get("logprobs")),
|
218
|
-
)
|
219
107
|
except Exception:
|
220
108
|
span.set_exc_info(*sys.exc_info())
|
221
109
|
raise
|
222
110
|
finally:
|
111
|
+
kwargs["_dd.identifying_params"] = instance._identifying_params
|
223
112
|
integration.llmobs_set_tags(span, args=args, kwargs=kwargs, response=completions, operation="llm")
|
224
113
|
span.finish()
|
225
114
|
return completions
|
@@ -238,7 +127,6 @@ async def traced_llm_agenerate(langchain, pin, func, instance, args, kwargs):
|
|
238
127
|
interface_type="llm",
|
239
128
|
provider=llm_provider,
|
240
129
|
model=model,
|
241
|
-
api_key=_extract_api_key(instance),
|
242
130
|
instance=instance,
|
243
131
|
)
|
244
132
|
|
@@ -246,39 +134,13 @@ async def traced_llm_agenerate(langchain, pin, func, instance, args, kwargs):
|
|
246
134
|
|
247
135
|
completions = None
|
248
136
|
try:
|
249
|
-
if integration.is_pc_sampled_span(span):
|
250
|
-
for idx, prompt in enumerate(prompts):
|
251
|
-
span.set_tag_str("langchain.request.prompts.%d" % idx, integration.trunc(str(prompt)))
|
252
|
-
for param, val in getattr(instance, "_identifying_params", {}).items():
|
253
|
-
if isinstance(val, dict):
|
254
|
-
for k, v in val.items():
|
255
|
-
span.set_tag_str("langchain.request.%s.parameters.%s.%s" % (llm_provider, param, k), str(v))
|
256
|
-
else:
|
257
|
-
span.set_tag_str("langchain.request.%s.parameters.%s" % (llm_provider, param), str(val))
|
258
|
-
|
259
137
|
completions = await func(*args, **kwargs)
|
260
|
-
|
261
138
|
core.dispatch("langchain.llm.agenerate.after", (prompts, completions))
|
262
|
-
|
263
|
-
if _is_openai_llm_instance(instance):
|
264
|
-
_tag_openai_token_usage(span, completions.llm_output)
|
265
|
-
|
266
|
-
for idx, completion in enumerate(completions.generations):
|
267
|
-
if integration.is_pc_sampled_span(span):
|
268
|
-
span.set_tag_str("langchain.response.completions.%d.text" % idx, integration.trunc(completion[0].text))
|
269
|
-
if completion and completion[0].generation_info is not None:
|
270
|
-
span.set_tag_str(
|
271
|
-
"langchain.response.completions.%d.finish_reason" % idx,
|
272
|
-
str(completion[0].generation_info.get("finish_reason")),
|
273
|
-
)
|
274
|
-
span.set_tag_str(
|
275
|
-
"langchain.response.completions.%d.logprobs" % idx,
|
276
|
-
str(completion[0].generation_info.get("logprobs")),
|
277
|
-
)
|
278
139
|
except Exception:
|
279
140
|
span.set_exc_info(*sys.exc_info())
|
280
141
|
raise
|
281
142
|
finally:
|
143
|
+
kwargs["_dd.identifying_params"] = instance._identifying_params
|
282
144
|
integration.llmobs_set_tags(span, args=args, kwargs=kwargs, response=completions, operation="llm")
|
283
145
|
span.finish()
|
284
146
|
return completions
|
@@ -296,7 +158,6 @@ def traced_chat_model_generate(langchain, pin, func, instance, args, kwargs):
|
|
296
158
|
interface_type="chat_model",
|
297
159
|
provider=llm_provider,
|
298
160
|
model=_extract_model_name(instance),
|
299
|
-
api_key=_extract_api_key(instance),
|
300
161
|
instance=instance,
|
301
162
|
)
|
302
163
|
|
@@ -304,78 +165,13 @@ def traced_chat_model_generate(langchain, pin, func, instance, args, kwargs):
|
|
304
165
|
|
305
166
|
chat_completions = None
|
306
167
|
try:
|
307
|
-
for message_set_idx, message_set in enumerate(chat_messages):
|
308
|
-
for message_idx, message in enumerate(message_set):
|
309
|
-
if integration.is_pc_sampled_span(span):
|
310
|
-
if isinstance(message, dict):
|
311
|
-
span.set_tag_str(
|
312
|
-
"langchain.request.messages.%d.%d.content" % (message_set_idx, message_idx),
|
313
|
-
integration.trunc(str(message.get("content", ""))),
|
314
|
-
)
|
315
|
-
else:
|
316
|
-
span.set_tag_str(
|
317
|
-
"langchain.request.messages.%d.%d.content" % (message_set_idx, message_idx),
|
318
|
-
integration.trunc(str(getattr(message, "content", ""))),
|
319
|
-
)
|
320
|
-
span.set_tag_str(
|
321
|
-
"langchain.request.messages.%d.%d.message_type" % (message_set_idx, message_idx),
|
322
|
-
message.__class__.__name__,
|
323
|
-
)
|
324
|
-
for param, val in getattr(instance, "_identifying_params", {}).items():
|
325
|
-
if isinstance(val, dict):
|
326
|
-
for k, v in val.items():
|
327
|
-
span.set_tag_str("langchain.request.%s.parameters.%s.%s" % (llm_provider, param, k), str(v))
|
328
|
-
else:
|
329
|
-
span.set_tag_str("langchain.request.%s.parameters.%s" % (llm_provider, param), str(val))
|
330
|
-
|
331
168
|
chat_completions = func(*args, **kwargs)
|
332
|
-
|
333
169
|
core.dispatch("langchain.chatmodel.generate.after", (chat_messages, chat_completions))
|
334
|
-
|
335
|
-
if _is_openai_chat_instance(instance):
|
336
|
-
_tag_openai_token_usage(span, chat_completions.llm_output)
|
337
|
-
|
338
|
-
for message_set_idx, message_set in enumerate(chat_completions.generations):
|
339
|
-
for idx, chat_completion in enumerate(message_set):
|
340
|
-
if integration.is_pc_sampled_span(span):
|
341
|
-
text = chat_completion.text
|
342
|
-
message = chat_completion.message
|
343
|
-
# tool calls aren't available on this property for legacy chains
|
344
|
-
tool_calls = getattr(message, "tool_calls", None)
|
345
|
-
|
346
|
-
if text:
|
347
|
-
span.set_tag_str(
|
348
|
-
"langchain.response.completions.%d.%d.content" % (message_set_idx, idx),
|
349
|
-
integration.trunc(chat_completion.text),
|
350
|
-
)
|
351
|
-
if tool_calls:
|
352
|
-
if not isinstance(tool_calls, list):
|
353
|
-
tool_calls = [tool_calls]
|
354
|
-
for tool_call_idx, tool_call in enumerate(tool_calls):
|
355
|
-
span.set_tag_str(
|
356
|
-
"langchain.response.completions.%d.%d.tool_calls.%d.id"
|
357
|
-
% (message_set_idx, idx, tool_call_idx),
|
358
|
-
str(tool_call.get("id", "")),
|
359
|
-
)
|
360
|
-
span.set_tag_str(
|
361
|
-
"langchain.response.completions.%d.%d.tool_calls.%d.name"
|
362
|
-
% (message_set_idx, idx, tool_call_idx),
|
363
|
-
str(tool_call.get("name", "")),
|
364
|
-
)
|
365
|
-
for arg_name, arg_value in tool_call.get("args", {}).items():
|
366
|
-
span.set_tag_str(
|
367
|
-
"langchain.response.completions.%d.%d.tool_calls.%d.args.%s"
|
368
|
-
% (message_set_idx, idx, tool_call_idx, arg_name),
|
369
|
-
integration.trunc(str(arg_value)),
|
370
|
-
)
|
371
|
-
span.set_tag_str(
|
372
|
-
"langchain.response.completions.%d.%d.message_type" % (message_set_idx, idx),
|
373
|
-
chat_completion.message.__class__.__name__,
|
374
|
-
)
|
375
170
|
except Exception:
|
376
171
|
span.set_exc_info(*sys.exc_info())
|
377
172
|
raise
|
378
173
|
finally:
|
174
|
+
kwargs["_dd.identifying_params"] = instance._identifying_params
|
379
175
|
integration.llmobs_set_tags(span, args=args, kwargs=kwargs, response=chat_completions, operation="chat")
|
380
176
|
span.finish()
|
381
177
|
return chat_completions
|
@@ -393,7 +189,6 @@ async def traced_chat_model_agenerate(langchain, pin, func, instance, args, kwar
|
|
393
189
|
interface_type="chat_model",
|
394
190
|
provider=llm_provider,
|
395
191
|
model=_extract_model_name(instance),
|
396
|
-
api_key=_extract_api_key(instance),
|
397
192
|
instance=instance,
|
398
193
|
)
|
399
194
|
|
@@ -401,77 +196,13 @@ async def traced_chat_model_agenerate(langchain, pin, func, instance, args, kwar
|
|
401
196
|
|
402
197
|
chat_completions = None
|
403
198
|
try:
|
404
|
-
for message_set_idx, message_set in enumerate(chat_messages):
|
405
|
-
for message_idx, message in enumerate(message_set):
|
406
|
-
if integration.is_pc_sampled_span(span):
|
407
|
-
if isinstance(message, dict):
|
408
|
-
span.set_tag_str(
|
409
|
-
"langchain.request.messages.%d.%d.content" % (message_set_idx, message_idx),
|
410
|
-
integration.trunc(str(message.get("content", ""))),
|
411
|
-
)
|
412
|
-
else:
|
413
|
-
span.set_tag_str(
|
414
|
-
"langchain.request.messages.%d.%d.content" % (message_set_idx, message_idx),
|
415
|
-
integration.trunc(str(getattr(message, "content", ""))),
|
416
|
-
)
|
417
|
-
span.set_tag_str(
|
418
|
-
"langchain.request.messages.%d.%d.message_type" % (message_set_idx, message_idx),
|
419
|
-
message.__class__.__name__,
|
420
|
-
)
|
421
|
-
for param, val in getattr(instance, "_identifying_params", {}).items():
|
422
|
-
if isinstance(val, dict):
|
423
|
-
for k, v in val.items():
|
424
|
-
span.set_tag_str("langchain.request.%s.parameters.%s.%s" % (llm_provider, param, k), str(v))
|
425
|
-
else:
|
426
|
-
span.set_tag_str("langchain.request.%s.parameters.%s" % (llm_provider, param), str(val))
|
427
|
-
|
428
199
|
chat_completions = await func(*args, **kwargs)
|
429
|
-
|
430
200
|
core.dispatch("langchain.chatmodel.agenerate.after", (chat_messages, chat_completions))
|
431
|
-
|
432
|
-
if _is_openai_chat_instance(instance):
|
433
|
-
_tag_openai_token_usage(span, chat_completions.llm_output)
|
434
|
-
|
435
|
-
for message_set_idx, message_set in enumerate(chat_completions.generations):
|
436
|
-
for idx, chat_completion in enumerate(message_set):
|
437
|
-
if integration.is_pc_sampled_span(span):
|
438
|
-
text = chat_completion.text
|
439
|
-
message = chat_completion.message
|
440
|
-
tool_calls = getattr(message, "tool_calls", None)
|
441
|
-
|
442
|
-
if text:
|
443
|
-
span.set_tag_str(
|
444
|
-
"langchain.response.completions.%d.%d.content" % (message_set_idx, idx),
|
445
|
-
integration.trunc(chat_completion.text),
|
446
|
-
)
|
447
|
-
if tool_calls:
|
448
|
-
if not isinstance(tool_calls, list):
|
449
|
-
tool_calls = [tool_calls]
|
450
|
-
for tool_call_idx, tool_call in enumerate(tool_calls):
|
451
|
-
span.set_tag_str(
|
452
|
-
"langchain.response.completions.%d.%d.tool_calls.%d.id"
|
453
|
-
% (message_set_idx, idx, tool_call_idx),
|
454
|
-
str(tool_call.get("id", "")),
|
455
|
-
)
|
456
|
-
span.set_tag_str(
|
457
|
-
"langchain.response.completions.%d.%d.tool_calls.%d.name"
|
458
|
-
% (message_set_idx, idx, tool_call_idx),
|
459
|
-
str(tool_call.get("name", "")),
|
460
|
-
)
|
461
|
-
for arg_name, arg_value in tool_call.get("args", {}).items():
|
462
|
-
span.set_tag_str(
|
463
|
-
"langchain.response.completions.%d.%d.tool_calls.%d.args.%s"
|
464
|
-
% (message_set_idx, idx, tool_call_idx, arg_name),
|
465
|
-
integration.trunc(str(arg_value)),
|
466
|
-
)
|
467
|
-
span.set_tag_str(
|
468
|
-
"langchain.response.completions.%d.%d.message_type" % (message_set_idx, idx),
|
469
|
-
chat_completion.message.__class__.__name__,
|
470
|
-
)
|
471
201
|
except Exception:
|
472
202
|
span.set_exc_info(*sys.exc_info())
|
473
203
|
raise
|
474
204
|
finally:
|
205
|
+
kwargs["_dd.identifying_params"] = instance._identifying_params
|
475
206
|
integration.llmobs_set_tags(span, args=args, kwargs=kwargs, response=chat_completions, operation="chat")
|
476
207
|
span.finish()
|
477
208
|
return chat_completions
|
@@ -483,11 +214,6 @@ def traced_embedding(langchain, pin, func, instance, args, kwargs):
|
|
483
214
|
This traces both embed_query(text) and embed_documents(texts), so we need to make sure
|
484
215
|
we get the right arg/kwarg.
|
485
216
|
"""
|
486
|
-
try:
|
487
|
-
input_texts = get_argument_value(args, kwargs, 0, "texts")
|
488
|
-
except ArgumentError:
|
489
|
-
input_texts = get_argument_value(args, kwargs, 0, "text")
|
490
|
-
|
491
217
|
provider = instance.__class__.__name__.split("Embeddings")[0].lower()
|
492
218
|
integration = langchain._datadog_integration
|
493
219
|
span = integration.trace(
|
@@ -497,7 +223,6 @@ def traced_embedding(langchain, pin, func, instance, args, kwargs):
|
|
497
223
|
interface_type="embedding",
|
498
224
|
provider=provider,
|
499
225
|
model=_extract_model_name(instance),
|
500
|
-
api_key=_extract_api_key(instance),
|
501
226
|
instance=instance,
|
502
227
|
)
|
503
228
|
|
@@ -505,23 +230,7 @@ def traced_embedding(langchain, pin, func, instance, args, kwargs):
|
|
505
230
|
|
506
231
|
embeddings = None
|
507
232
|
try:
|
508
|
-
if isinstance(input_texts, str):
|
509
|
-
if integration.is_pc_sampled_span(span):
|
510
|
-
span.set_tag_str("langchain.request.inputs.0.text", integration.trunc(input_texts))
|
511
|
-
span.set_metric("langchain.request.input_count", 1)
|
512
|
-
else:
|
513
|
-
if integration.is_pc_sampled_span(span):
|
514
|
-
for idx, text in enumerate(input_texts):
|
515
|
-
span.set_tag_str("langchain.request.inputs.%d.text" % idx, integration.trunc(text))
|
516
|
-
span.set_metric("langchain.request.input_count", len(input_texts))
|
517
|
-
# langchain currently does not support token tracking for OpenAI embeddings:
|
518
|
-
# https://github.com/hwchase17/langchain/issues/945
|
519
233
|
embeddings = func(*args, **kwargs)
|
520
|
-
if isinstance(embeddings, list) and embeddings and isinstance(embeddings[0], list):
|
521
|
-
for idx, embedding in enumerate(embeddings):
|
522
|
-
span.set_metric("langchain.response.outputs.%d.embedding_length" % idx, len(embedding))
|
523
|
-
else:
|
524
|
-
span.set_metric("langchain.response.outputs.embedding_length", len(embeddings))
|
525
234
|
except Exception:
|
526
235
|
span.set_exc_info(*sys.exc_info())
|
527
236
|
raise
|
@@ -563,22 +272,9 @@ def traced_lcel_runnable_sequence(langchain, pin, func, instance, args, kwargs):
|
|
563
272
|
inputs = get_argument_value(args, kwargs, 0, "input")
|
564
273
|
except ArgumentError:
|
565
274
|
inputs = get_argument_value(args, kwargs, 0, "inputs")
|
566
|
-
if
|
567
|
-
|
568
|
-
inputs = [inputs]
|
569
|
-
for idx, inp in enumerate(inputs):
|
570
|
-
if not isinstance(inp, dict):
|
571
|
-
span.set_tag_str("langchain.request.inputs.%d" % idx, integration.trunc(str(inp)))
|
572
|
-
else:
|
573
|
-
for k, v in inp.items():
|
574
|
-
span.set_tag_str("langchain.request.inputs.%d.%s" % (idx, k), integration.trunc(str(v)))
|
275
|
+
if not isinstance(inputs, list):
|
276
|
+
inputs = [inputs]
|
575
277
|
final_output = func(*args, **kwargs)
|
576
|
-
if integration.is_pc_sampled_span(span):
|
577
|
-
final_outputs = final_output # separate variable as to return correct value later
|
578
|
-
if not isinstance(final_outputs, list):
|
579
|
-
final_outputs = [final_outputs]
|
580
|
-
for idx, output in enumerate(final_outputs):
|
581
|
-
span.set_tag_str("langchain.response.outputs.%d" % idx, integration.trunc(str(output)))
|
582
278
|
except Exception:
|
583
279
|
span.set_exc_info(*sys.exc_info())
|
584
280
|
raise
|
@@ -611,22 +307,9 @@ async def traced_lcel_runnable_sequence_async(langchain, pin, func, instance, ar
|
|
611
307
|
inputs = get_argument_value(args, kwargs, 0, "input")
|
612
308
|
except ArgumentError:
|
613
309
|
inputs = get_argument_value(args, kwargs, 0, "inputs")
|
614
|
-
if
|
615
|
-
|
616
|
-
inputs = [inputs]
|
617
|
-
for idx, inp in enumerate(inputs):
|
618
|
-
if not isinstance(inp, dict):
|
619
|
-
span.set_tag_str("langchain.request.inputs.%d" % idx, integration.trunc(str(inp)))
|
620
|
-
else:
|
621
|
-
for k, v in inp.items():
|
622
|
-
span.set_tag_str("langchain.request.inputs.%d.%s" % (idx, k), integration.trunc(str(v)))
|
310
|
+
if not isinstance(inputs, list):
|
311
|
+
inputs = [inputs]
|
623
312
|
final_output = await func(*args, **kwargs)
|
624
|
-
if integration.is_pc_sampled_span(span):
|
625
|
-
final_outputs = final_output # separate variable as to return correct value later
|
626
|
-
if not isinstance(final_outputs, list):
|
627
|
-
final_outputs = [final_outputs]
|
628
|
-
for idx, output in enumerate(final_outputs):
|
629
|
-
span.set_tag_str("langchain.response.outputs.%d" % idx, integration.trunc(str(output)))
|
630
313
|
except Exception:
|
631
314
|
span.set_exc_info(*sys.exc_info())
|
632
315
|
raise
|
@@ -639,8 +322,6 @@ async def traced_lcel_runnable_sequence_async(langchain, pin, func, instance, ar
|
|
639
322
|
@with_traced_module
|
640
323
|
def traced_similarity_search(langchain, pin, func, instance, args, kwargs):
|
641
324
|
integration = langchain._datadog_integration
|
642
|
-
query = get_argument_value(args, kwargs, 0, "query")
|
643
|
-
k = kwargs.get("k", args[1] if len(args) >= 2 else None)
|
644
325
|
provider = instance.__class__.__name__.lower()
|
645
326
|
span = integration.trace(
|
646
327
|
pin,
|
@@ -648,7 +329,6 @@ def traced_similarity_search(langchain, pin, func, instance, args, kwargs):
|
|
648
329
|
submit_to_llmobs=True,
|
649
330
|
interface_type="similarity_search",
|
650
331
|
provider=provider,
|
651
|
-
api_key=_extract_api_key(instance),
|
652
332
|
instance=instance,
|
653
333
|
)
|
654
334
|
|
@@ -656,37 +336,7 @@ def traced_similarity_search(langchain, pin, func, instance, args, kwargs):
|
|
656
336
|
|
657
337
|
documents = []
|
658
338
|
try:
|
659
|
-
if integration.is_pc_sampled_span(span):
|
660
|
-
span.set_tag_str("langchain.request.query", integration.trunc(query))
|
661
|
-
if k is not None:
|
662
|
-
span.set_tag_str("langchain.request.k", str(k))
|
663
|
-
for kwarg_key, v in kwargs.items():
|
664
|
-
span.set_tag_str("langchain.request.%s" % kwarg_key, str(v))
|
665
|
-
if _is_pinecone_vectorstore_instance(instance) and hasattr(instance._index, "configuration"):
|
666
|
-
span.set_tag_str(
|
667
|
-
"langchain.request.pinecone.environment",
|
668
|
-
instance._index.configuration.server_variables.get("environment", ""),
|
669
|
-
)
|
670
|
-
span.set_tag_str(
|
671
|
-
"langchain.request.pinecone.index_name",
|
672
|
-
instance._index.configuration.server_variables.get("index_name", ""),
|
673
|
-
)
|
674
|
-
span.set_tag_str(
|
675
|
-
"langchain.request.pinecone.project_name",
|
676
|
-
instance._index.configuration.server_variables.get("project_name", ""),
|
677
|
-
)
|
678
|
-
api_key = instance._index.configuration.api_key.get("ApiKeyAuth", "")
|
679
|
-
span.set_tag_str(API_KEY, _format_api_key(api_key)) # override api_key for Pinecone
|
680
339
|
documents = func(*args, **kwargs)
|
681
|
-
span.set_metric("langchain.response.document_count", len(documents))
|
682
|
-
for idx, document in enumerate(documents):
|
683
|
-
span.set_tag_str(
|
684
|
-
"langchain.response.document.%d.page_content" % idx, integration.trunc(str(document.page_content))
|
685
|
-
)
|
686
|
-
for kwarg_key, v in document.metadata.items():
|
687
|
-
span.set_tag_str(
|
688
|
-
"langchain.response.document.%d.metadata.%s" % (idx, kwarg_key), integration.trunc(str(v))
|
689
|
-
)
|
690
340
|
except Exception:
|
691
341
|
span.set_exc_info(*sys.exc_info())
|
692
342
|
raise
|
@@ -702,17 +352,6 @@ def traced_chain_stream(langchain, pin, func, instance, args, kwargs):
|
|
702
352
|
|
703
353
|
def _on_span_started(span: Span):
|
704
354
|
integration.record_instance(instance, span)
|
705
|
-
inputs = get_argument_value(args, kwargs, 0, "input")
|
706
|
-
if not integration.is_pc_sampled_span(span):
|
707
|
-
return
|
708
|
-
if not isinstance(inputs, list):
|
709
|
-
inputs = [inputs]
|
710
|
-
for idx, inp in enumerate(inputs):
|
711
|
-
if not isinstance(inp, dict):
|
712
|
-
span.set_tag_str("langchain.request.inputs.%d" % idx, integration.trunc(str(inp)))
|
713
|
-
continue
|
714
|
-
for k, v in inp.items():
|
715
|
-
span.set_tag_str("langchain.request.inputs.%d.%s" % (idx, k), integration.trunc(str(v)))
|
716
355
|
|
717
356
|
def _on_span_finished(span: Span, streamed_chunks):
|
718
357
|
maybe_parser = instance.steps[-1] if instance.steps else None
|
@@ -735,9 +374,6 @@ def traced_chain_stream(langchain, pin, func, instance, args, kwargs):
|
|
735
374
|
# best effort to join chunks together
|
736
375
|
content = "".join([str(chunk) for chunk in streamed_chunks])
|
737
376
|
integration.llmobs_set_tags(span, args=args, kwargs=kwargs, response=content, operation="chain")
|
738
|
-
if span.error or not integration.is_pc_sampled_span(span):
|
739
|
-
return
|
740
|
-
span.set_tag_str("langchain.response.outputs", integration.trunc(content))
|
741
377
|
|
742
378
|
return shared_stream(
|
743
379
|
integration=integration,
|
@@ -760,41 +396,13 @@ def traced_chat_stream(langchain, pin, func, instance, args, kwargs):
|
|
760
396
|
|
761
397
|
def _on_span_started(span: Span):
|
762
398
|
integration.record_instance(instance, span)
|
763
|
-
if not integration.is_pc_sampled_span(span):
|
764
|
-
return
|
765
|
-
chat_messages = get_argument_value(args, kwargs, 0, "input")
|
766
|
-
tag_general_message_input(span, chat_messages, integration, langchain_core)
|
767
|
-
|
768
|
-
for param, val in getattr(instance, "_identifying_params", {}).items():
|
769
|
-
if not isinstance(val, dict):
|
770
|
-
span.set_tag_str("langchain.request.%s.parameters.%s" % (llm_provider, param), str(val))
|
771
|
-
continue
|
772
|
-
for k, v in val.items():
|
773
|
-
span.set_tag_str("langchain.request.%s.parameters.%s.%s" % (llm_provider, param, k), str(v))
|
774
399
|
|
775
400
|
def _on_span_finished(span: Span, streamed_chunks):
|
776
401
|
joined_chunks = streamed_chunks[0]
|
777
402
|
for chunk in streamed_chunks[1:]:
|
778
403
|
joined_chunks += chunk # base message types support __add__ for concatenation
|
404
|
+
kwargs["_dd.identifying_params"] = instance._identifying_params
|
779
405
|
integration.llmobs_set_tags(span, args=args, kwargs=kwargs, response=joined_chunks, operation="chat")
|
780
|
-
if (
|
781
|
-
span.error
|
782
|
-
or not integration.is_pc_sampled_span(span)
|
783
|
-
or streamed_chunks is None
|
784
|
-
or len(streamed_chunks) == 0
|
785
|
-
):
|
786
|
-
return
|
787
|
-
content = str(getattr(joined_chunks, "content", joined_chunks))
|
788
|
-
role = joined_chunks.__class__.__name__.replace("Chunk", "") # AIMessageChunk --> AIMessage
|
789
|
-
span.set_tag_str("langchain.response.content", integration.trunc(content))
|
790
|
-
if role:
|
791
|
-
span.set_tag_str("langchain.response.message_type", role)
|
792
|
-
|
793
|
-
usage = streamed_chunks and getattr(streamed_chunks[-1], "usage_metadata", None)
|
794
|
-
if not usage or not isinstance(usage, dict):
|
795
|
-
return
|
796
|
-
for k, v in usage.items():
|
797
|
-
span.set_tag_str("langchain.response.usage_metadata.%s" % k, str(v))
|
798
406
|
|
799
407
|
return shared_stream(
|
800
408
|
integration=integration,
|
@@ -806,7 +414,6 @@ def traced_chat_stream(langchain, pin, func, instance, args, kwargs):
|
|
806
414
|
interface_type="chat_model",
|
807
415
|
on_span_started=_on_span_started,
|
808
416
|
on_span_finished=_on_span_finished,
|
809
|
-
api_key=_extract_api_key(instance),
|
810
417
|
provider=llm_provider,
|
811
418
|
model=model,
|
812
419
|
)
|
@@ -820,23 +427,11 @@ def traced_llm_stream(langchain, pin, func, instance, args, kwargs):
|
|
820
427
|
|
821
428
|
def _on_span_start(span: Span):
|
822
429
|
integration.record_instance(instance, span)
|
823
|
-
if not integration.is_pc_sampled_span(span):
|
824
|
-
return
|
825
|
-
inp = get_argument_value(args, kwargs, 0, "input")
|
826
|
-
tag_general_message_input(span, inp, integration, langchain_core)
|
827
|
-
for param, val in getattr(instance, "_identifying_params", {}).items():
|
828
|
-
if not isinstance(val, dict):
|
829
|
-
span.set_tag_str("langchain.request.%s.parameters.%s" % (llm_provider, param), str(val))
|
830
|
-
continue
|
831
|
-
for k, v in val.items():
|
832
|
-
span.set_tag_str("langchain.request.%s.parameters.%s.%s" % (llm_provider, param, k), str(v))
|
833
430
|
|
834
431
|
def _on_span_finished(span: Span, streamed_chunks):
|
835
432
|
content = "".join([str(chunk) for chunk in streamed_chunks])
|
433
|
+
kwargs["_dd.identifying_params"] = instance._identifying_params
|
836
434
|
integration.llmobs_set_tags(span, args=args, kwargs=kwargs, response=content, operation="llm")
|
837
|
-
if span.error or not integration.is_pc_sampled_span(span):
|
838
|
-
return
|
839
|
-
span.set_tag_str("langchain.response.content", integration.trunc(content))
|
840
435
|
|
841
436
|
return shared_stream(
|
842
437
|
integration=integration,
|
@@ -848,7 +443,6 @@ def traced_llm_stream(langchain, pin, func, instance, args, kwargs):
|
|
848
443
|
interface_type="llm",
|
849
444
|
on_span_started=_on_span_start,
|
850
445
|
on_span_finished=_on_span_finished,
|
851
|
-
api_key=_extract_api_key(instance),
|
852
446
|
provider=llm_provider,
|
853
447
|
model=model,
|
854
448
|
)
|
@@ -876,28 +470,15 @@ def traced_base_tool_invoke(langchain, pin, func, instance, args, kwargs):
|
|
876
470
|
for attribute in ("name", "description"):
|
877
471
|
value = getattr(instance, attribute, None)
|
878
472
|
tool_info[attribute] = value
|
879
|
-
if value is not None:
|
880
|
-
span.set_tag_str("langchain.request.tool.%s" % attribute, str(value))
|
881
473
|
|
882
474
|
metadata = getattr(instance, "metadata", {})
|
883
475
|
if metadata:
|
884
476
|
tool_info["metadata"] = metadata
|
885
|
-
for key, meta_value in metadata.items():
|
886
|
-
span.set_tag_str("langchain.request.tool.metadata.%s" % key, str(meta_value))
|
887
477
|
tags = getattr(instance, "tags", [])
|
888
478
|
if tags:
|
889
479
|
tool_info["tags"] = tags
|
890
|
-
for idx, tag in tags:
|
891
|
-
span.set_tag_str("langchain.request.tool.tags.%d" % idx, str(value))
|
892
|
-
|
893
|
-
if tool_input and integration.is_pc_sampled_span(span):
|
894
|
-
span.set_tag_str("langchain.request.input", integration.trunc(str(tool_input)))
|
895
|
-
if config:
|
896
|
-
span.set_tag_str("langchain.request.config", safe_json(config))
|
897
480
|
|
898
481
|
tool_output = func(*args, **kwargs)
|
899
|
-
if tool_output and integration.is_pc_sampled_span(span):
|
900
|
-
span.set_tag_str("langchain.response.output", integration.trunc(str(tool_output)))
|
901
482
|
except Exception:
|
902
483
|
span.set_exc_info(*sys.exc_info())
|
903
484
|
raise
|
@@ -930,28 +511,15 @@ async def traced_base_tool_ainvoke(langchain, pin, func, instance, args, kwargs)
|
|
930
511
|
for attribute in ("name", "description"):
|
931
512
|
value = getattr(instance, attribute, None)
|
932
513
|
tool_info[attribute] = value
|
933
|
-
if value is not None:
|
934
|
-
span.set_tag_str("langchain.request.tool.%s" % attribute, str(value))
|
935
514
|
|
936
515
|
metadata = getattr(instance, "metadata", {})
|
937
516
|
if metadata:
|
938
517
|
tool_info["metadata"] = metadata
|
939
|
-
for key, meta_value in metadata.items():
|
940
|
-
span.set_tag_str("langchain.request.tool.metadata.%s" % key, str(meta_value))
|
941
518
|
tags = getattr(instance, "tags", [])
|
942
519
|
if tags:
|
943
520
|
tool_info["tags"] = tags
|
944
|
-
for idx, tag in tags:
|
945
|
-
span.set_tag_str("langchain.request.tool.tags.%d" % idx, str(value))
|
946
|
-
|
947
|
-
if tool_input and integration.is_pc_sampled_span(span):
|
948
|
-
span.set_tag_str("langchain.request.input", integration.trunc(str(tool_input)))
|
949
|
-
if config:
|
950
|
-
span.set_tag_str("langchain.request.config", safe_json(config))
|
951
521
|
|
952
522
|
tool_output = await func(*args, **kwargs)
|
953
|
-
if tool_output and integration.is_pc_sampled_span(span):
|
954
|
-
span.set_tag_str("langchain.response.output", integration.trunc(str(tool_output)))
|
955
523
|
except Exception:
|
956
524
|
span.set_exc_info(*sys.exc_info())
|
957
525
|
raise
|