Skip to content

Commit 1b98f9f

Browse files
authored
Merge branch 'main' into langchain-agent-spans
2 parents d3b2528 + dec8600 commit 1b98f9f

File tree

3 files changed

+63
-18
lines changed

3 files changed

+63
-18
lines changed

util/opentelemetry-util-genai/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1313
([https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3798](#3798))
1414
- Record content-type and use canonical paths in fsspec genai uploader
1515
([https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3795](#3795))
16+
- Make inputs / outputs / system instructions optional params to `on_completion`,
17+
([https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3802](#3802)).
1618

1719
## Version 0.1b0 (2025-09-25)
1820

util/opentelemetry-util-genai/src/opentelemetry/util/genai/_upload/completion_hook.py

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,9 @@
6060

6161
@dataclass
6262
class Completion:
63-
inputs: list[types.InputMessage]
64-
outputs: list[types.OutputMessage]
65-
system_instruction: list[types.MessagePart]
63+
inputs: list[types.InputMessage] | None
64+
outputs: list[types.OutputMessage] | None
65+
system_instruction: list[types.MessagePart] | None
6666

6767

6868
@dataclass
@@ -210,10 +210,13 @@ def on_completion(
210210
log_record: LogRecord | None = None,
211211
**kwargs: Any,
212212
) -> None:
213+
if not any([inputs, outputs, system_instruction]):
214+
return
215+
# An empty list will not be uploaded.
213216
completion = Completion(
214-
inputs=inputs,
215-
outputs=outputs,
216-
system_instruction=system_instruction,
217+
inputs=inputs or None,
218+
outputs=outputs or None,
219+
system_instruction=system_instruction or None,
217220
)
218221
# generate the paths to upload to
219222
ref_names = self._calculate_ref_path()
@@ -225,23 +228,36 @@ def to_dict(
225228
) -> JsonEncodeable:
226229
return [asdict(dc) for dc in dataclass_list]
227230

231+
references = [
232+
(ref_name, ref, ref_attr)
233+
for ref_name, ref, ref_attr in [
234+
(
235+
ref_names.inputs_ref,
236+
completion.inputs,
237+
GEN_AI_INPUT_MESSAGES_REF,
238+
),
239+
(
240+
ref_names.outputs_ref,
241+
completion.outputs,
242+
GEN_AI_OUTPUT_MESSAGES_REF,
243+
),
244+
(
245+
ref_names.system_instruction_ref,
246+
completion.system_instruction,
247+
GEN_AI_SYSTEM_INSTRUCTIONS_REF,
248+
),
249+
]
250+
if ref
251+
]
228252
self._submit_all(
229253
{
230-
# Use partial to defer as much as possible to the background threads
231-
ref_names.inputs_ref: partial(to_dict, completion.inputs),
232-
ref_names.outputs_ref: partial(to_dict, completion.outputs),
233-
ref_names.system_instruction_ref: partial(
234-
to_dict, completion.system_instruction
235-
),
236-
},
254+
ref_name: partial(to_dict, ref)
255+
for ref_name, ref, _ in references
256+
}
237257
)
238258

239259
# stamp the refs on telemetry
240-
references = {
241-
GEN_AI_INPUT_MESSAGES_REF: ref_names.inputs_ref,
242-
GEN_AI_OUTPUT_MESSAGES_REF: ref_names.outputs_ref,
243-
GEN_AI_SYSTEM_INSTRUCTIONS_REF: ref_names.system_instruction_ref,
244-
}
260+
references = {ref_attr: name for name, _, ref_attr in references}
245261
if span:
246262
span.set_attributes(references)
247263
if log_record:

util/opentelemetry-util-genai/tests/test_upload.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,33 @@ def test_upload_then_shutdown(self):
162162
"should have uploaded 3 files",
163163
)
164164

165+
def test_upload_when_inputs_outputs_empty(self):
166+
record = LogRecord()
167+
self.hook.on_completion(
168+
inputs=[],
169+
outputs=[],
170+
system_instruction=FAKE_SYSTEM_INSTRUCTION,
171+
log_record=record,
172+
)
173+
# all items should be consumed
174+
self.hook.shutdown()
175+
176+
self.assertEqual(
177+
self.mock_fs.open.call_count,
178+
1,
179+
"should have uploaded 1 file",
180+
)
181+
assert record.attributes is not None
182+
for ref_key in [
183+
"gen_ai.input.messages_ref",
184+
"gen_ai.output.messages_ref",
185+
"gen_ai.system_instructions_ref",
186+
]:
187+
if ref_key == "gen_ai.system_instructions_ref":
188+
self.assertIn(ref_key, record.attributes)
189+
else:
190+
self.assertNotIn(ref_key, record.attributes)
191+
165192
def test_upload_blocked(self):
166193
with self.block_upload():
167194
# fill the queue

0 commit comments

Comments
 (0)