"""Opt-in OTLP or local JSON spans; tool payloads and credentials are not attributes.""" import atexit, functools, os from opentelemetry import trace def configure(): if not (os.getenv("OPS_TRACE_FILE") or os.getenv("OTEL_EXPORTER_OTLP_ENDPOINT")):return from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExporter from opentelemetry.sdk.resources import Resource provider=TracerProvider(resource=Resource.create({"service.name":"opspilot"})) if os.getenv("OPS_TRACE_FILE"): stream=open(os.environ["OPS_TRACE_FILE"],"a") atexit.register(stream.close);exporter=ConsoleSpanExporter(out=stream) else: from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter exporter=OTLPSpanExporter() provider.add_span_processor(BatchSpanProcessor(exporter));trace.set_tracer_provider(provider) atexit.register(provider.shutdown) def instrument(fn): @functools.wraps(fn) def wrapper(state): with trace.get_tracer("opspilot.graph").start_as_current_span(fn.__name__) as span: span.set_attribute("run.id",state["id"]);span.set_attribute("evidence.count",len(state.get("observations",{}))) return fn(state) return wrapper configure()