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🧵
💡 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. 👍
