From 0beea0caef710ef19c0317bcfb6f65dcba7de979 Mon Sep 17 00:00:00 2001 From: Manasjyoti Sharma Date: Thu, 16 Apr 2026 18:53:37 +0530 Subject: [PATCH] Rebrand traceloop.* attribute keys to fortifyroot.* across all signals Change semconv constant string values from "traceloop.*" to "fortifyroot.*", add backward-compatible TRACELOOP_* aliases, and update SDK tracing/decorator code to use FORTIFYROOT_* constant names. Update test assertions to match. --- .../opentelemetry/semconv_ai/__init__.py | 66 +++++++++++++------ .../tests/test_prompt_management.py | 2 +- .../traceloop-sdk/tests/test_workflows.py | 16 ++--- .../traceloop/sdk/decorators/base.py | 14 ++-- .../traceloop/sdk/tracing/tracing.py | 26 ++++---- 5 files changed, 77 insertions(+), 47 deletions(-) diff --git a/packages/opentelemetry-semantic-conventions-ai/opentelemetry/semconv_ai/__init__.py b/packages/opentelemetry-semantic-conventions-ai/opentelemetry/semconv_ai/__init__.py index 0cae486211..abae7203e4 100644 --- a/packages/opentelemetry-semantic-conventions-ai/opentelemetry/semconv_ai/__init__.py +++ b/packages/opentelemetry-semantic-conventions-ai/opentelemetry/semconv_ai/__init__.py @@ -1,3 +1,7 @@ +# NOTE: +# This file has been modified by FortifyRoot. +# Original source: https://github.com/traceloop/openllmetry + from enum import Enum SUPPRESS_LANGUAGE_MODEL_INSTRUMENTATION_KEY = "suppress_language_model_instrumentation" @@ -118,27 +122,45 @@ class SpanAttributes: PINECONE_QUERY_QUERIES = "pinecone.query.queries" PINECONE_QUERY_TOP_K = "pinecone.query.top_k" - # LLM Workflows - TRACELOOP_SPAN_KIND = "traceloop.span.kind" - TRACELOOP_WORKFLOW_NAME = "traceloop.workflow.name" - TRACELOOP_ENTITY_NAME = "traceloop.entity.name" - TRACELOOP_ENTITY_PATH = "traceloop.entity.path" - TRACELOOP_ENTITY_VERSION = "traceloop.entity.version" - TRACELOOP_ENTITY_INPUT = "traceloop.entity.input" - TRACELOOP_ENTITY_OUTPUT = "traceloop.entity.output" - TRACELOOP_ASSOCIATION_PROPERTIES = "traceloop.association.properties" - - # Prompts - TRACELOOP_PROMPT_MANAGED = "traceloop.prompt.managed" - TRACELOOP_PROMPT_KEY = "traceloop.prompt.key" - TRACELOOP_PROMPT_VERSION = "traceloop.prompt.version" - TRACELOOP_PROMPT_VERSION_NAME = "traceloop.prompt.version_name" - TRACELOOP_PROMPT_VERSION_HASH = "traceloop.prompt.version_hash" - TRACELOOP_PROMPT_TEMPLATE = "traceloop.prompt.template" - TRACELOOP_PROMPT_TEMPLATE_VARIABLES = "traceloop.prompt.template_variables" + # LLM Workflows (FortifyRoot-branded attribute keys) + FORTIFYROOT_SPAN_KIND = "fortifyroot.span.kind" + FORTIFYROOT_WORKFLOW_NAME = "fortifyroot.workflow.name" + FORTIFYROOT_ENTITY_NAME = "fortifyroot.entity.name" + FORTIFYROOT_ENTITY_PATH = "fortifyroot.entity.path" + FORTIFYROOT_ENTITY_VERSION = "fortifyroot.entity.version" + FORTIFYROOT_ENTITY_INPUT = "fortifyroot.entity.input" + FORTIFYROOT_ENTITY_OUTPUT = "fortifyroot.entity.output" + FORTIFYROOT_ASSOCIATION_PROPERTIES = "fortifyroot.association.properties" + + # Prompts (FortifyRoot-branded attribute keys) + FORTIFYROOT_PROMPT_MANAGED = "fortifyroot.prompt.managed" + FORTIFYROOT_PROMPT_KEY = "fortifyroot.prompt.key" + FORTIFYROOT_PROMPT_VERSION = "fortifyroot.prompt.version" + FORTIFYROOT_PROMPT_VERSION_NAME = "fortifyroot.prompt.version_name" + FORTIFYROOT_PROMPT_VERSION_HASH = "fortifyroot.prompt.version_hash" + FORTIFYROOT_PROMPT_TEMPLATE = "fortifyroot.prompt.template" + FORTIFYROOT_PROMPT_TEMPLATE_VARIABLES = "fortifyroot.prompt.template_variables" # Deprecated - TRACELOOP_CORRELATION_ID = "traceloop.correlation.id" + FORTIFYROOT_CORRELATION_ID = "fortifyroot.correlation.id" + + # Backward-compatible aliases (all resolve to fortifyroot.* values above) + TRACELOOP_SPAN_KIND = FORTIFYROOT_SPAN_KIND + TRACELOOP_WORKFLOW_NAME = FORTIFYROOT_WORKFLOW_NAME + TRACELOOP_ENTITY_NAME = FORTIFYROOT_ENTITY_NAME + TRACELOOP_ENTITY_PATH = FORTIFYROOT_ENTITY_PATH + TRACELOOP_ENTITY_VERSION = FORTIFYROOT_ENTITY_VERSION + TRACELOOP_ENTITY_INPUT = FORTIFYROOT_ENTITY_INPUT + TRACELOOP_ENTITY_OUTPUT = FORTIFYROOT_ENTITY_OUTPUT + TRACELOOP_ASSOCIATION_PROPERTIES = FORTIFYROOT_ASSOCIATION_PROPERTIES + TRACELOOP_PROMPT_MANAGED = FORTIFYROOT_PROMPT_MANAGED + TRACELOOP_PROMPT_KEY = FORTIFYROOT_PROMPT_KEY + TRACELOOP_PROMPT_VERSION = FORTIFYROOT_PROMPT_VERSION + TRACELOOP_PROMPT_VERSION_NAME = FORTIFYROOT_PROMPT_VERSION_NAME + TRACELOOP_PROMPT_VERSION_HASH = FORTIFYROOT_PROMPT_VERSION_HASH + TRACELOOP_PROMPT_TEMPLATE = FORTIFYROOT_PROMPT_TEMPLATE + TRACELOOP_PROMPT_TEMPLATE_VARIABLES = FORTIFYROOT_PROMPT_TEMPLATE_VARIABLES + TRACELOOP_CORRELATION_ID = FORTIFYROOT_CORRELATION_ID # Watson/genai LLM LLM_DECODING_METHOD = "llm.watsonx.decoding_method" @@ -287,9 +309,13 @@ class LLMRequestTypeValues(Enum): UNKNOWN = "unknown" -class TraceloopSpanKindValues(Enum): +class FortifyrootSpanKindValues(Enum): WORKFLOW = "workflow" TASK = "task" AGENT = "agent" TOOL = "tool" UNKNOWN = "unknown" + + +# Backward-compatible alias +TraceloopSpanKindValues = FortifyrootSpanKindValues diff --git a/packages/traceloop-sdk/tests/test_prompt_management.py b/packages/traceloop-sdk/tests/test_prompt_management.py index 6394177897..ff2aa16ad2 100644 --- a/packages/traceloop-sdk/tests/test_prompt_management.py +++ b/packages/traceloop-sdk/tests/test_prompt_management.py @@ -239,7 +239,7 @@ def test_prompt_management(exporter, openai_client): == "Tell me a joke about OpenTelemetry, pirate style" ) assert open_ai_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") - assert open_ai_span.attributes.get("traceloop.prompt.key") == "joke_generator" + assert open_ai_span.attributes.get("fortifyroot.prompt.key") == "joke_generator" @pytest.mark.vcr diff --git a/packages/traceloop-sdk/tests/test_workflows.py b/packages/traceloop-sdk/tests/test_workflows.py index b38f9a5e46..daa7107449 100644 --- a/packages/traceloop-sdk/tests/test_workflows.py +++ b/packages/traceloop-sdk/tests/test_workflows.py @@ -49,10 +49,10 @@ def joke_workflow(): open_ai_span = next(span for span in spans if span.name == "openai.chat") assert open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about OpenTelemetry" assert open_ai_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") - assert open_ai_span.attributes.get("traceloop.prompt.template") == "Tell me a {what} about {subject}" - assert open_ai_span.attributes.get("traceloop.prompt.template_variables.what") == "joke" - assert open_ai_span.attributes.get("traceloop.prompt.template_variables.subject") == "OpenTelemetry" - assert open_ai_span.attributes.get("traceloop.prompt.version") == "5" + assert open_ai_span.attributes.get("fortifyroot.prompt.template") == "Tell me a {what} about {subject}" + assert open_ai_span.attributes.get("fortifyroot.prompt.template_variables.what") == "joke" + assert open_ai_span.attributes.get("fortifyroot.prompt.template_variables.subject") == "OpenTelemetry" + assert open_ai_span.attributes.get("fortifyroot.prompt.version") == "5" workflow_span = next(span for span in spans if span.name == "pirate_joke_generator.workflow") task_span = next(span for span in spans if span.name == "something_creator.task") @@ -95,10 +95,10 @@ async def joke_workflow(): open_ai_span = next(span for span in spans if span.name == "openai.chat") assert open_ai_span.attributes[f"{GenAIAttributes.GEN_AI_PROMPT}.0.content"] == "Tell me a joke about OpenTelemetry" assert open_ai_span.attributes.get(f"{GenAIAttributes.GEN_AI_COMPLETION}.0.content") - assert open_ai_span.attributes.get("traceloop.prompt.template") == "Tell me a {what} about {subject}" - assert open_ai_span.attributes.get("traceloop.prompt.template_variables.what") == "joke" - assert open_ai_span.attributes.get("traceloop.prompt.template_variables.subject") == "OpenTelemetry" - assert open_ai_span.attributes.get("traceloop.prompt.version") == "5" + assert open_ai_span.attributes.get("fortifyroot.prompt.template") == "Tell me a {what} about {subject}" + assert open_ai_span.attributes.get("fortifyroot.prompt.template_variables.what") == "joke" + assert open_ai_span.attributes.get("fortifyroot.prompt.template_variables.subject") == "OpenTelemetry" + assert open_ai_span.attributes.get("fortifyroot.prompt.version") == "5" workflow_span = next(span for span in spans if span.name == "pirate_joke_generator.workflow") task_span = next(span for span in spans if span.name == "something_creator.task") diff --git a/packages/traceloop-sdk/traceloop/sdk/decorators/base.py b/packages/traceloop-sdk/traceloop/sdk/decorators/base.py index dee1e41de2..50c8b8b9e9 100644 --- a/packages/traceloop-sdk/traceloop/sdk/decorators/base.py +++ b/packages/traceloop-sdk/traceloop/sdk/decorators/base.py @@ -1,3 +1,7 @@ +# NOTE: +# This file has been modified by FortifyRoot. +# Original source: https://github.com/traceloop/openllmetry + import json from functools import wraps import os @@ -158,10 +162,10 @@ def _setup_span(entity_name, tlp_span_kind, version): entity_path = get_chained_entity_path(entity_name) set_entity_path(entity_path) - span.set_attribute(SpanAttributes.TRACELOOP_SPAN_KIND, tlp_span_kind.value) - span.set_attribute(SpanAttributes.TRACELOOP_ENTITY_NAME, entity_name) + span.set_attribute(SpanAttributes.FORTIFYROOT_SPAN_KIND, tlp_span_kind.value) + span.set_attribute(SpanAttributes.FORTIFYROOT_ENTITY_NAME, entity_name) if version: - span.set_attribute(SpanAttributes.TRACELOOP_ENTITY_VERSION, version) + span.set_attribute(SpanAttributes.FORTIFYROOT_ENTITY_VERSION, version) return span, ctx, ctx_token @@ -175,7 +179,7 @@ def _handle_span_input(span, args, kwargs, cls=None): ) truncated_json = _truncate_json_if_needed(json_input) span.set_attribute( - SpanAttributes.TRACELOOP_ENTITY_INPUT, + SpanAttributes.FORTIFYROOT_ENTITY_INPUT, truncated_json, ) except TypeError: @@ -189,7 +193,7 @@ def _handle_span_output(span, res, cls=None): json_output = json.dumps(res, **({"cls": cls} if cls else {})) truncated_json = _truncate_json_if_needed(json_output) span.set_attribute( - SpanAttributes.TRACELOOP_ENTITY_OUTPUT, + SpanAttributes.FORTIFYROOT_ENTITY_OUTPUT, truncated_json, ) except TypeError: diff --git a/packages/traceloop-sdk/traceloop/sdk/tracing/tracing.py b/packages/traceloop-sdk/traceloop/sdk/tracing/tracing.py index b758a928cd..4473518cc5 100644 --- a/packages/traceloop-sdk/traceloop/sdk/tracing/tracing.py +++ b/packages/traceloop-sdk/traceloop/sdk/tracing/tracing.py @@ -265,7 +265,7 @@ def set_association_properties(properties: dict) -> None: def _set_association_properties_attributes(span, properties: dict) -> None: for key, value in properties.items(): span.set_attribute( - f"{SpanAttributes.TRACELOOP_ASSOCIATION_PROPERTIES}.{key}", value + f"{SpanAttributes.FORTIFYROOT_ASSOCIATION_PROPERTIES}.{key}", value ) @@ -378,7 +378,7 @@ def default_span_processor_on_start(span: Span, parent_context: Context | None = """ workflow_name = get_value("workflow_name") if workflow_name is not None: - span.set_attribute(SpanAttributes.TRACELOOP_WORKFLOW_NAME, str(workflow_name)) + span.set_attribute(SpanAttributes.FORTIFYROOT_WORKFLOW_NAME, str(workflow_name)) agent_name = get_value("agent_name") if agent_name is not None: @@ -390,7 +390,7 @@ def default_span_processor_on_start(span: Span, parent_context: Context | None = entity_path = get_value("entity_path") if entity_path is not None: - span.set_attribute(SpanAttributes.TRACELOOP_ENTITY_PATH, str(entity_path)) + span.set_attribute(SpanAttributes.FORTIFYROOT_ENTITY_PATH, str(entity_path)) association_properties = get_value("association_properties") if association_properties is not None and isinstance(association_properties, dict): @@ -400,35 +400,35 @@ def default_span_processor_on_start(span: Span, parent_context: Context | None = managed_prompt = get_value("managed_prompt") if managed_prompt is not None: span.set_attribute( - SpanAttributes.TRACELOOP_PROMPT_MANAGED, str(managed_prompt) + SpanAttributes.FORTIFYROOT_PROMPT_MANAGED, str(managed_prompt) ) prompt_key = get_value("prompt_key") if prompt_key is not None: - span.set_attribute(SpanAttributes.TRACELOOP_PROMPT_KEY, str(prompt_key)) + span.set_attribute(SpanAttributes.FORTIFYROOT_PROMPT_KEY, str(prompt_key)) prompt_version = get_value("prompt_version") if prompt_version is not None: span.set_attribute( - SpanAttributes.TRACELOOP_PROMPT_VERSION, str(prompt_version) + SpanAttributes.FORTIFYROOT_PROMPT_VERSION, str(prompt_version) ) prompt_version_name = get_value("prompt_version_name") if prompt_version_name is not None: span.set_attribute( - SpanAttributes.TRACELOOP_PROMPT_VERSION_NAME, str(prompt_version_name) + SpanAttributes.FORTIFYROOT_PROMPT_VERSION_NAME, str(prompt_version_name) ) prompt_version_hash = get_value("prompt_version_hash") if prompt_version_hash is not None: span.set_attribute( - SpanAttributes.TRACELOOP_PROMPT_VERSION_HASH, str(prompt_version_hash) + SpanAttributes.FORTIFYROOT_PROMPT_VERSION_HASH, str(prompt_version_hash) ) prompt_template = get_value("prompt_template") if prompt_template is not None: span.set_attribute( - SpanAttributes.TRACELOOP_PROMPT_TEMPLATE, str(prompt_template) + SpanAttributes.FORTIFYROOT_PROMPT_TEMPLATE, str(prompt_template) ) prompt_template_variables = get_value("prompt_template_variables") @@ -437,7 +437,7 @@ def default_span_processor_on_start(span: Span, parent_context: Context | None = ): for key, value in prompt_template_variables.items(): span.set_attribute( - f"{SpanAttributes.TRACELOOP_PROMPT_TEMPLATE_VARIABLES}.{key}", + f"{SpanAttributes.FORTIFYROOT_PROMPT_TEMPLATE_VARIABLES}.{key}", value, ) @@ -1191,17 +1191,17 @@ def metrics_common_attributes(): common_attributes = {} workflow_name = get_value("workflow_name") if workflow_name is not None: - common_attributes[SpanAttributes.TRACELOOP_WORKFLOW_NAME] = workflow_name + common_attributes[SpanAttributes.FORTIFYROOT_WORKFLOW_NAME] = workflow_name entity_name = get_value("entity_name") if entity_name is not None: - common_attributes[SpanAttributes.TRACELOOP_ENTITY_NAME] = entity_name + common_attributes[SpanAttributes.FORTIFYROOT_ENTITY_NAME] = entity_name association_properties = get_value("association_properties") if association_properties is not None: for key, value in association_properties.items(): common_attributes[ - f"{SpanAttributes.TRACELOOP_ASSOCIATION_PROPERTIES}.{key}" + f"{SpanAttributes.FORTIFYROOT_ASSOCIATION_PROPERTIES}.{key}" ] = value return common_attributes