Raymond created CAMEL-22963:
-------------------------------

             Summary: [camel-api] Get Exchange as Json
                 Key: CAMEL-22963
                 URL: https://issues.apache.org/jira/browse/CAMEL-22963
             Project: Camel
          Issue Type: Wish
          Components: came-core
    Affects Versions: 4.17.0
            Reporter: Raymond


With the log data component, you can get the data from an exchange. The output 
looks something like this:
{code:java}
Exchange[ Headers: {breadcrumbId=97D358D813160DB-000000000000002D, 
CamelServletContextPath=/tst, ComponentInitTime=1770306467630, 
Connection=close} BodyType: org.apache.camel.converter.stream.InputStreamCache 
Body: <persons> <person> <name>John Doe</name> </person> <person> <name>Jane 
Doe</name> </person> </persons> ] 
{code}

This is nice, and you can even customize is it using a custom 
exchangeFormatter. 

I would like to get the exchange data as JSON programmatically from the 
Exchange API. Similarly, as how to get/dump route stats as JSON (on the 
ManagedRouteMBean).

The methods could be added to regular Exchange api, or to the extended exchange 
api (ExchangeExtension()).


*Example methods:*

1. exchange.getAsJson()

This would get the full exchange as JSON.

2. exchange.getAsJson(includeProperties, includeVariables, includeException, 
includeHeaders, includeAttachment, includeeBodyType, includeBody)

This would give the developer fine grain control of what the JSON contains.

3. exchange.get(exchangeFormatter);

This allows to use as custom exchangeFormatter to get the data, which can be as 
JSON or formatted in some other way.

I used here exchange.getAsJson(), but the method could be called 
exchange.dumpAsJson() as well (in accordance with how other methods are when 
'dumping' data).

Probably, the JSON could be created with exchangeFormatter and the 
camel-util-json. An example of the output:


{code:java}
{
    "exchange": {
        "timestamp": "2025-03-17T15:08:40.085+0000", 
        "exchangeId": "C6D8944F2120FA5-0000000000000000",
        "groupId": "orders",
        "routeId": "64f0a356a810a200c4000684",
        "fromRouteId": "8934a56a810a200c4000270",
        "pattern": "InOut",
        "properties": {
            "myProperty1": "myPropertyValue",
            "myProperty2": "myPropertyValue2"
        },
        "variables": {
            "myVariable": "myVarValue",
            "myVariable2": "myVarValue2"
        },
        "exception": {
            "cause": "Some cause"
        },
        "message": {
            "headers": {
                "Accept": 
"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
                "Priority": "u=0, i",
                "Connection": "keep-alive",
                "breadcrumbId": "C6D8944F2120FA5-0000000000000000",
                "Upgrade-Insecure-Requests": "1",
                "CamelServletContextPath": "/test",
                "Content-Type": "text/plain"
            },
            "attachments": {
                "attachement": "key1",
                "attachement": "key2"
            },
            "bodyType": "java.lang.String",
            "body": "My Test Body"
        }
    }
} {code}

*Sidenote 1: Getting properties/variables/headers*

Maybe the following ticket "Exchange getPropertyAsList, getPropertyAsMap":

https://issues.apache.org/jira/browse/CAMEL-22910

can be of help.

*Sidenote 2: maxChars*
Like in the log data component it maybe useful to set the maxChars for values 
such as the body, headers, variables, properties. ** 

*Sidenote 3: Object types*
In the example I included the bodyType (type of object) however there maybe 
cases where the object type is also useful for headers/properties/variables. ** 

*Side note 4: Meta information*
For our platform we already created a JSON that works like this:

1. Collect event with the EventNotifier
2. Turn exchange data into a json
3. Send/Offload json to a database (for example ElasticSearch) 

The reason is that with observability you get a lot of metrics, but most users 
like to have more insight in the content of messages as well. The JSON we 
create looks like this:


{code:java}
{
    "exchangeId": "C6D8944F2120FA5-0000000000000000",
    "breadCrumbId": "C6D8944F2120FA5356654",
    "groupId": "orders",
    "routeId": "64f0a356a810a200c4000684",
    "previousRouteId": "64f0a356a810a200c4000684",
    "fromRouteId": "8934a56a810a200c4000270",
    "stepId": "64f0a356a810a200c4000684_3256",
    "failedExchange": false,
    "timestamp": "2025-03-17T15:08:40.085+0000",
    "expiryDate": "2025-03-17T16:08:40.086+0000",
    "body": "aGVsbG8gd29ybGQ=\r\n",
    "headers": {
        "Accept": 
"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
        "Priority": "u=0, i",
        "Connection": "keep-alive",
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:136.0) 
Gecko/20100101 Firefox/136.0",
        "Sec-Fetch-Dest": "document",
        "Sec-Fetch-Site": "none",
        "Host": "localhost:9001",
        "Accept-Encoding": "gzip, deflate, br, zstd",
        "Sec-Fetch-Mode": "navigate",
        "breadcrumbId": "C6D8944F2120FA5-0000000000000000",
        "CamelServletContextPath": "/test",
        "Sec-Fetch-User": "?1",
        "Accept-Language": "en-US,en;q=0.5",
        "Content-Type": "text/plain"
    },
    "metadata": [{
            "unit": "",
            "name": "ExchangePattern",
            "value": "InOut"
        }, {
            "unit": "ISO 8601",
            "name": "Timestamp",
            "value": "2025-03-17T16:08:40.086+0000"
        }, {
            "unit": "long",
            "name": "UnixTimestamp",
            "value": "1770305720"
        }, {
            "unit": "milliseconds",
            "name": "ResponseTime",
            "value": "4"
        }, {
            "unit": "object",
            "name": "BodyType",
            "value": "InputStreamCache"
        }, {
            "unit": "bytes",
            "name": "BodySize",
            "value": 18
        }, {
            "unit": "bytes",
            "name": "HeadersSize",
            "value": 566
        }
    ],
} {code}

Some remarks:

1. BreadCrumbId: We include the breadcrumb id as "transaction ID" to track 
messages.
2. We also include the previousRouteId and previousStepId so we can show the 
flow of the message.
3. We convert all values to String if possible to make them readable in the 
frontend.
4. We include an expiryDate. This date shows how long the exchange needs to be 
persistent in the database before deletion.
5. Metadata: We include metadata such as the size of the body and headers, Unix 
timestamp, timestamp in nanoseconds (to order the messages), responseTime (how 
long it took for a route to process the exchange). This metadata helps the user 
get more insight.


------------------------------------------------------

Formalizing a JSON format is practically for external tools or users to read a 
Camel exchange would be a great enhancement. It can be used for debugging, 
tracing purposes and more.





 

 

 



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to