Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
d3fb068
CAMEL-23861: Add GenAI observability for langchain4j and OpenAI (Phas…
cursoragent Aug 5, 2026
f0e29bf
CAMEL-23861: Fix tracer lookup and add OTel span tests
cursoragent Aug 5, 2026
64b3588
CAMEL-23861: Address review findings for GenAI observability
cursoragent Aug 5, 2026
8aa23ff
CAMEL-23861: Address davsclaus review feedback on GenAI observability
cursoragent Aug 5, 2026
16f964f
CAMEL-23861: Fix docs xref for ai-observability in upgrade guide
cursoragent Aug 5, 2026
f4a8253
CAMEL-23861: Fix CI, optional Micrometer, and round-2 review feedback
cursoragent Aug 5, 2026
ada7a3f
CAMEL-23861: Fix upgrade guide xref for unreleased ai-observability doc
cursoragent Aug 5, 2026
f357808
CAMEL-23861: Commit regenerated BOM, catalog, and formatter output
cursoragent Aug 5, 2026
e0664cf
CAMEL-23861: Split observability API and address latest review feedback
cursoragent Aug 5, 2026
0142d16
CAMEL-23861: Address round-3 PR review feedback
cursoragent Aug 6, 2026
a10956d
CAMEL-23861: Regenerate endpoint DSL for RESPONSE_MODEL header metadata
cursoragent Aug 6, 2026
a366252
CAMEL-23861: Address round-4 PR review feedback
cursoragent Aug 6, 2026
e069e8b
CAMEL-23861: Restore camel-jbang-configuration-metadata.json from main
cursoragent Aug 8, 2026
0b8bb33
CAMEL-23861: Rebase on main and target Camel 4.23.0
cursoragent Aug 11, 2026
b88c31f
CAMEL-23861: Move GenAI observability upgrade guide entry to 4.23
cursoragent Aug 11, 2026
7c4282e
Merge branch 'main' into cursor/CAMEL-23861-genai-observability-c587
davsclaus Aug 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions bom/camel-bom/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,16 @@
<artifactId>camel-activemq6</artifactId>
<version>4.23.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-ai-observability</artifactId>
<version>4.22.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-ai-observability-api</artifactId>
<version>4.22.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-ai-tool</artifactId>
Expand Down
10 changes: 10 additions & 0 deletions catalog/camel-allcomponents/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,16 @@
<artifactId>camel-activemq6</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-ai-observability</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-ai-observability-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-ai-tool</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,10 @@
"CamelLangChain4jAgentInputTokenCount": { "index": 7, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The Input Token Count.", "constantName": "org.apache.camel.component.langchain4j.agent.api.Headers#INPUT_TOKEN_COUNT" },
"CamelLangChain4jAgentOutputTokenCount": { "index": 8, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The Output Token Count.", "constantName": "org.apache.camel.component.langchain4j.agent.api.Headers#OUTPUT_TOKEN_COUNT" },
"CamelLangChain4jAgentTotalTokenCount": { "index": 9, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The Total Token Count.", "constantName": "org.apache.camel.component.langchain4j.agent.api.Headers#TOTAL_TOKEN_COUNT" },
"CamelLangChain4jAgentSources": { "index": 10, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "java.util.List<dev.langchain4j.rag.content.Content>", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "RAG sources retrieved during agent invocation.", "constantName": "org.apache.camel.component.langchain4j.agent.api.Headers#SOURCES" },
"CamelLangChain4jAgentToolExecutions": { "index": 11, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "java.util.List<dev.langchain4j.service.tool.ToolExecution>", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Tool executions performed during agent invocation.", "constantName": "org.apache.camel.component.langchain4j.agent.api.Headers#TOOL_EXECUTIONS" }
"CamelLangChain4jAgentRequestModel": { "index": 10, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The request model name.", "constantName": "org.apache.camel.component.langchain4j.agent.api.Headers#REQUEST_MODEL" },
"CamelLangChain4jAgentResponseModel": { "index": 11, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The response model name. Not set by the agent producer when langchain4j Result does not expose it.", "constantName": "org.apache.camel.component.langchain4j.agent.api.Headers#RESPONSE_MODEL" },
"CamelLangChain4jAgentSources": { "index": 12, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "java.util.List<dev.langchain4j.rag.content.Content>", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "RAG sources retrieved during agent invocation.", "constantName": "org.apache.camel.component.langchain4j.agent.api.Headers#SOURCES" },
"CamelLangChain4jAgentToolExecutions": { "index": 13, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "java.util.List<dev.langchain4j.service.tool.ToolExecution>", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Tool executions performed during agent invocation.", "constantName": "org.apache.camel.component.langchain4j.agent.api.Headers#TOOL_EXECUTIONS" }
},
"properties": {
"agentId": { "index": 0, "kind": "path", "displayName": "Agent Id", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The Agent id" },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@
"CamelLangChain4jChatFinishReason": { "index": 2, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "dev.langchain4j.model.output.FinishReason", "enum": [ "STOP", "LENGTH", "TOOL_EXECUTION", "CONTENT_FILTER", "OTHER" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The Finish Reason.", "constantName": "org.apache.camel.component.langchain4j.chat.LangChain4jChatHeaders#FINISH_REASON" },
"CamelLangChain4jChatInputTokenCount": { "index": 3, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The Input Token Count.", "constantName": "org.apache.camel.component.langchain4j.chat.LangChain4jChatHeaders#INPUT_TOKEN_COUNT" },
"CamelLangChain4jChatOutputTokenCount": { "index": 4, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The Output Token Count.", "constantName": "org.apache.camel.component.langchain4j.chat.LangChain4jChatHeaders#OUTPUT_TOKEN_COUNT" },
"CamelLangChain4jChatTotalTokenCount": { "index": 5, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The Total Token Count.", "constantName": "org.apache.camel.component.langchain4j.chat.LangChain4jChatHeaders#TOTAL_TOKEN_COUNT" }
"CamelLangChain4jChatTotalTokenCount": { "index": 5, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The Total Token Count.", "constantName": "org.apache.camel.component.langchain4j.chat.LangChain4jChatHeaders#TOTAL_TOKEN_COUNT" },
"CamelLangChain4jChatRequestModel": { "index": 6, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The request model name.", "constantName": "org.apache.camel.component.langchain4j.chat.LangChain4jChatHeaders#REQUEST_MODEL" },
"CamelLangChain4jChatResponseModel": { "index": 7, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The response model name.", "constantName": "org.apache.camel.component.langchain4j.chat.LangChain4jChatHeaders#RESPONSE_MODEL" }
},
"properties": {
"chatId": { "index": 0, "kind": "path", "displayName": "Chat Id", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The id" },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,11 @@
"CamelLangChain4jEmbeddingsInputTokenCount": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The Input Token Count.", "constantName": "org.apache.camel.component.langchain4j.embeddings.LangChain4jEmbeddingsHeaders#INPUT_TOKEN_COUNT" },
"CamelLangChain4jEmbeddingsOutputTokenCount": { "index": 2, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The Output Token Count.", "constantName": "org.apache.camel.component.langchain4j.embeddings.LangChain4jEmbeddingsHeaders#OUTPUT_TOKEN_COUNT" },
"CamelLangChain4jEmbeddingsTotalTokenCount": { "index": 3, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The Total Token Count.", "constantName": "org.apache.camel.component.langchain4j.embeddings.LangChain4jEmbeddingsHeaders#TOTAL_TOKEN_COUNT" },
"CamelLangChain4jEmbeddingsEmbedding": { "index": 4, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "dev.langchain4j.data.embedding.Embedding", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Embedding representation of a text", "constantName": "org.apache.camel.component.langchain4j.embeddings.LangChain4jEmbeddingsHeaders#EMBEDDING" },
"CamelLangChain4jEmbeddingsVector": { "index": 5, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "float[]", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "A dense vector embedding of a text", "constantName": "org.apache.camel.component.langchain4j.embeddings.LangChain4jEmbeddingsHeaders#VECTOR" },
"CamelLangChain4jEmbeddingsTextSegment": { "index": 6, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": " dev.langchain4j.data.segment.TextSegment", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "A TextSegment representation of the vector embedding input text", "constantName": "org.apache.camel.component.langchain4j.embeddings.LangChain4jEmbeddingsHeaders#TEXT_SEGMENT" }
"CamelLangChain4jEmbeddingsRequestModel": { "index": 4, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The request model name.", "constantName": "org.apache.camel.component.langchain4j.embeddings.LangChain4jEmbeddingsHeaders#REQUEST_MODEL" },
"CamelLangChain4jEmbeddingsResponseModel": { "index": 5, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The response model name.", "constantName": "org.apache.camel.component.langchain4j.embeddings.LangChain4jEmbeddingsHeaders#RESPONSE_MODEL" },
"CamelLangChain4jEmbeddingsEmbedding": { "index": 6, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "dev.langchain4j.data.embedding.Embedding", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Embedding representation of a text", "constantName": "org.apache.camel.component.langchain4j.embeddings.LangChain4jEmbeddingsHeaders#EMBEDDING" },
"CamelLangChain4jEmbeddingsVector": { "index": 7, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "float[]", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "A dense vector embedding of a text", "constantName": "org.apache.camel.component.langchain4j.embeddings.LangChain4jEmbeddingsHeaders#VECTOR" },
"CamelLangChain4jEmbeddingsTextSegment": { "index": 8, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": " dev.langchain4j.data.segment.TextSegment", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "A TextSegment representation of the vector embedding input text", "constantName": "org.apache.camel.component.langchain4j.embeddings.LangChain4jEmbeddingsHeaders#TEXT_SEGMENT" }
},
"properties": {
"embeddingId": { "index": 0, "kind": "path", "displayName": "Embedding Id", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The id" },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@
"CamelLangChain4jToolsFinishReason": { "index": 0, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "dev.langchain4j.model.output.FinishReason", "enum": [ "STOP", "LENGTH", "TOOL_EXECUTION", "CONTENT_FILTER", "OTHER" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The Finish Reason.", "constantName": "org.apache.camel.component.langchain4j.tools.LangChain4jToolsHeaders#FINISH_REASON" },
"CamelLangChain4jToolsInputTokenCount": { "index": 1, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The Input Token Count.", "constantName": "org.apache.camel.component.langchain4j.tools.LangChain4jToolsHeaders#INPUT_TOKEN_COUNT" },
"CamelLangChain4jToolsOutputTokenCount": { "index": 2, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The Output Token Count.", "constantName": "org.apache.camel.component.langchain4j.tools.LangChain4jToolsHeaders#OUTPUT_TOKEN_COUNT" },
"CamelLangChain4jToolsTotalTokenCount": { "index": 3, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The Total Token Count.", "constantName": "org.apache.camel.component.langchain4j.tools.LangChain4jToolsHeaders#TOTAL_TOKEN_COUNT" }
"CamelLangChain4jToolsTotalTokenCount": { "index": 3, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The Total Token Count.", "constantName": "org.apache.camel.component.langchain4j.tools.LangChain4jToolsHeaders#TOTAL_TOKEN_COUNT" },
"CamelLangChain4jToolsRequestModel": { "index": 4, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The request model name.", "constantName": "org.apache.camel.component.langchain4j.tools.LangChain4jToolsHeaders#REQUEST_MODEL" },
"CamelLangChain4jToolsResponseModel": { "index": 5, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The response model name.", "constantName": "org.apache.camel.component.langchain4j.tools.LangChain4jToolsHeaders#RESPONSE_MODEL" }
},
"properties": {
"toolId": { "index": 0, "kind": "path", "displayName": "Tool Id", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The tool id" },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ a2aSubTask-eip
activemq-component
activemq6-component
aggregate-eip
ai-observability
ai-patterns
ai-tool-component
amqp-component
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
= AI Observability Component
:doctitle: AI Observability
:shortname: ai-observability
:artifactid: camel-ai-observability
:description: GenAI observability support for Camel AI components (OpenTelemetry and Micrometer)
:since: 4.23
:supportlevel: Preview
:tabs-sync-option:

*Since Camel {since}*

The `camel-ai-observability` module provides GenAI observability for Camel AI components following the
OpenTelemetry semantic conventions for GenAI (stable subset aligned with Spring AI).

AI producers depend on the lightweight `camel-ai-observability-api` module. Add `camel-ai-observability` to your
application classpath together with a tracing or metrics backend to enable span and metric emission.

When `camel-opentelemetry2` and/or `camel-micrometer` is on the classpath, langchain4j and OpenAI producers
emit child spans and metrics per LLM call with attributes such as `gen_ai.operation.name`, `gen_ai.system`,
`gen_ai.request.model`, `gen_ai.usage.input_tokens`, and `gen_ai.usage.output_tokens`.

Global toggle: set `camel.ai.observability.enabled=false` to disable GenAI observability across all AI
components (default is `true` when a tracing or metrics backend is present).

Phase 1 coverage: `langchain4j-chat`, `langchain4j-tools`, `langchain4j-agent`, `langchain4j-embeddings`,
and `openai`.

New exchange headers for model identification on langchain4j components:

* `CamelLangChain4jChatRequestModel` / `CamelLangChain4jChatResponseModel`
* `CamelLangChain4jToolsRequestModel` / `CamelLangChain4jToolsResponseModel`
* `CamelLangChain4jAgentRequestModel` / `CamelLangChain4jAgentResponseModel`
* `CamelLangChain4jEmbeddingsRequestModel` / `CamelLangChain4jEmbeddingsResponseModel`

Metrics recorded (when Micrometer is available):

* `gen_ai.client.operation` — operation duration timer
* `gen_ai.client.token.usage` — token usage counter (tags: `gen_ai.token.type=input|output`)
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
ai-observability
attachments
azure-schema-registry
cli-connector
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"other": {
"kind": "other",
"name": "ai-observability",
"title": "AI Observability",
"description": "GenAI observability support for Camel AI components (OpenTelemetry and Micrometer)",
"deprecated": false,
"firstVersion": "4.23.0",
"label": "ai",
"supportLevel": "Preview",
"groupId": "org.apache.camel",
"artifactId": "camel-ai-observability",
"version": "4.23.0-SNAPSHOT"
}
}
Loading