Hi Phoenix team, thanks for the great product! I am writing to expand on the thread by my colleague David above. We're using openinference-instrumentation-bedrock = "^0.1.13" to instrument a stream-oriented interaction with Bedrock but we do not seem to be able to submit custom attributes to the span that's being created. Maybe you could point to where I am doing it wrong? Will elaborate in the thread🧵
To help you better, could you provide more details on how you're attempting to add custom attributes to the span? Specifically, are you using the setAttributes function or any other method to set these attributes? Additionally, please ensure that the attributes you are trying to set are valid span attribute values as per the OpenTelemetry API. You can refer to the OpenInference documentation for guidance on setting context attributes.Sources:
- OpenInference documentation
💡 Hint: Mention RunLLM in the thread for followups.
Here, retrieve_reply_for_chat() is the iterator which contacts AWS Bedrock. This code does post a span to Phoenix — but the custom attributes are not there.
I tried placing the line
current_span = trace.get_current_span()in different places in this code snippet, to no avail.
Let me know if I can provide more relevant information. Thank you!
This is because the current span is no longer active at that point. One simple alternate approach is to add a parent span as show below.
from openinference.instrumentation.bedrock import BedrockInstrumentor
from openinference.semconv.trace import SpanAttributes
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import SimpleSpanProcessor
from opentelemetry.trace import Status, StatusCode
endpoint = "http://127.0.0.1:4317"
tracer_provider = TracerProvider()
tracer_provider.add_span_processor(SimpleSpanProcessor(OTLPSpanExporter(endpoint)))
BedrockInstrumentor().instrument(tracer_provider=tracer_provider)
async def event_generator():
input_value = llm_messages[-1].content
with tracer_provider.get_tracer(__name__).start_as_current_span(
"event_generator",
end_on_exit=False,
attributes={
SpanAttributes.INPUT_VALUE: input_value,
SpanAttributes.SESSION_ID: str(chat_id),
SpanAttributes.USER_ID: user.id,
"user_name": user.name,
"org_id": user.org_id,
"org_name": user.org.name,
},
) as span:
chunks = retrieve_reply_for_chat(llm_messages)
response = ""
try:
for chunk in chunks:
response += chunk
yield DataMessage(text=chunk)
except Exception as e:
span.record_exception(e)
span.set_status(Status(StatusCode.ERROR))
logger.exception("Failed to retrieve reply for chat.")
yield FailureMessage(
error_message=(
"Unable to process your request at this time, "
"please try again later. We apologize for the inconvenience."
),
)
else:
span.set_status(Status(StatusCode.OK))
finally:
span.set_attribute(SpanAttributes.OUTPUT_VALUE, response)
span.end()
yield EndMessage()
I did try that; but, it means that in Phoenix UI, in the spans list, I will see empty inputs and outputs, and I will need to click on each and then drill to the span created by the instrumentation. I thought maybe I could avoid that and instead attach the attributes to the span that the instrumentation creates.
In the code above i tried attaching the input and output values as strings. Would that work for you?
the span the instrumentation creates is invisible in the sense that the instrumentation itself is trying very hard to be invisible, so capturing its span is not easy
I see. Thank you very much! I think I will take this approach. In addition, it would solve the issue I mentioned in another thread. 👍
