HI @dchiesa1 ,
I need assistance understanding the message logging policy used in the post-client flow. My proxy has three conditional flows, each producing distinct input, output, and customized responses for the client. I want to log all three fields (input, output, and response sent to the client) using a single message logging policy in the post-client flow, leveraging Google Cloud Logging.
For one conditional flow, I set up the logging policy as follows:
<CloudLogging>
<LogName>projects/apigee-dev/logs/apigee.googleapis.com%2Fproxy-logging-events</LogName>
<Message contentType="application/json">
{
"apiProxy": "{apiproxy.name}",
"apiProxyRevision": "{apiproxy.revision}",
"inputPayload": "{escapeJSON(requestPayload)}",
"viesPayload": "{escapeJSON(calloutVIESResponse.content)}",
"responseSentToClient": {httpResponse}
}
</Message>
...
This setup works perfectly and logs as expected. However, in another conditional flow, viesPayload is not present, and a different field, such as xPayload, is used. When I modify the payload structure like this:
<CloudLogging>
<LogName>projects/apigee-dev/logs/apigee.googleapis.com%2Fproxy-logging-events</LogName>
<Message contentType="application/json">
{
"apiProxy": "{apiproxy.name}",
"apiProxyRevision": "{apiproxy.revision}",
"inputPayload": "{escapeJSON(requestPayload)}",
"viesPayload": "{escapeJSON(calloutVIESResponse.content)}",
"responseSentToClient": {httpResponse},
"xPayload": "{escapeJSON(calloutXPayload.content)}"
}
</Message>
...
...it does not log anything in Google Cloud Logging.
Does this imply that if certain fields (e.g., viesPayload) are missing, the entire payload fails to log? If so, how can I address this issue to ensure logging works even when specific fields are absent?
Thanks in advance!
Solved! Go to Solution.
ok, now I understand what you're asking ! Sadly the answer is no, today, you cannot set the Trace value on a LogEntry that is sent by the MessageLogging policy. This seems like a reasonable enhancement request. I can see why you'd want this! I've filed a ticket on your behalf. Internal reference: b/382569454 .
Hello @shefali!
There is a way of making this work. I see you are using message templates here, such as escapeJSON(). You can find many additional message templates available to modify the behaviour and contents of variables or runtime data. There is a "Null-coalescing function" template you can find that will be able to help in this specific scenario. You can find the documentation here: #null-coalescing-function.
I created a simple example to achieve something like this with the same message logging policy:
A small difference is to actually apply the first function prior to the construction of the log object, you can also apply it in the extraction of the variables I noticed you might be doing for the first body.
Creating my variable for the body with escapeJSON Template:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<AssignMessage continueOnError="false" enabled="true" name="am-extract-request-body">
<DisplayName>am-extract-request-body</DisplayName>
<Properties/>
<AssignVariable>
<Name>request_body</Name>
<Template>{escapeJSON(request.content)}</Template>
<Value>ErrorOnCopy</Value>
</AssignVariable>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
<AssignTo createNew="false" transport="http" type="request"/>
</AssignMessage>
Setting my variable in the message logging policy applying the second template:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<MessageLogging continueOnError="false" enabled="true" name="ml-ingest-log">
<DisplayName>ml-ingest-log</DisplayName>
<CloudLogging>
<LogName>projects/------/logs/apigee</LogName>
<Message contentType="application/json">{
"timestamp": "{crypto.dateFormat('YYYY-MM-dd HH:mm:ss.SSS')}",
"organization": "{organization.name}",
"network.client.ip": "{client.ip}",
"message_id": "{messageid}",
"env": "{environment.name}",
"message": "{firstnonnull(request_body, 'this request had no request body')}"
}</Message>
</CloudLogging>
</MessageLogging>
The way this template works is that it will start looking for a non null variable left to right and pick the first one it gets.
I think that with a small refactor you can make this work for all logging scenarios in you api.
You could do something like this:
<CloudLogging>
<LogName>projects/apigee-dev/logs/apigee.googleapis.com%2Fproxy-logging-events</LogName>
<Message contentType="application/json">
{
"apiProxy": "{apiproxy.name}",
"apiProxyRevision": "{apiproxy.revision}",
"inputPayload": "{firstnonnull(requestPayload, 'other variable or literal')}",
"responsePayload": "{firstnonnull(calloutVIESResponse.content, calloutXPayload.content)}",
"responseType": "viesPayload/xPayload",
"responseSentToClient": {httpResponse}
}
</Message>
You mentioned that there are 2 object where you expect in different scenarios a payload. So:
What I suggest is creating a single property such as the one in the example above with responsePayload and use the firstnonnull function here to specify both json object. The policy will populate the first it gets as a non null. Additionally you might want to capture the type of response payload you are logging, so I added a responseType. You can use the proxy path suffix flow variable to get some visibility or use it as reference for variable population.
On an additional note, nesting functions is not supported, so you will have to apply the escapeJSON() function prior to creating the log object.
I hope this helps! Let me know.
Hi @ricardosm ,
Thank you for your response! I’m going to try the suggested approach and will share my findings here.
I do have one more question related to the same topic. If I want to add a trace field in the <MessageLogging> policy to filter load balancer logs and their corresponding proxy logs, how can I include it? When I add the trace field inside the <Message> tag, the logs in the Logs Explorer appear as:
However, to enable linking the logs in one click, I need the trace field to be formatted as:
Is there a way to add the trace field outside the jsonPayload while using the <MessageLogging> policy?
I know this is achievable in a service callout using a structure like this:
But I’d like to know if this is achievable with the <MessageLogging> policy as well.
Thanks in advance for your help!
@ricardosm wrote:
But I’d like to know if this is achievable with the <MessageLogging> policy as well.
I don't know just what you mean by "this" when you are asking whether "this" is achievable.
I think you might be asking if you can extract a specific item from a json blob, so you can log that specific item later. If jsonPayload is .... a context variable of type string, and it contains json, and one of the properties there is called trace
like this:
{
"trace" : "projects/systems-apigee-dev/traces/358324e32ec530c8445536b26a3a70f8",
"field2" : 42,
"field3" : [1,2,3]
}
and if your goal is to extract that trace
property value from the jsonPayload string into a new variable.... then ..., yes you can do that. You can use the following AssignMessage, like this:
<AssignMessage continueOnError="false" enabled="true" name="AM-Extract-Trace">
<AssignVariable>
<Name>json_path_1</Name>
<Value>$.trace</Value>
</AssignVariable>
<AssignVariable>
<Name>assigned</Name>
<Value>BADDBEEF</Value>
<Template>{jsonPath(json_path_1,jsonPayload)}</Template>
</AssignVariable>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</AssignMessage>
And after than, the variable assigned
will contain the value "projects/systems-apigee-dev/traces/358324e32ec530c8445536b26a3a70f8", and you can use that variable in subsequent MessageLogging policies.
@dchiesa1 : I think the jsonPayload is from the structured logging as I read from this page:
https://cloud.google.com/logging/docs/structured-logging
and here is the snippet from the above doc:
This document discusses the concept of structured logging and the methods for adding structure to log entry payload fields. When the log payload is formatted as a JSON object and that object is stored in the jsonPayload field, the log entry is called a structured log.
The issue here is : if you see the below screenshot, the trace query is formed like this and it gives only one result.
But the load balancer trace is not visible because that works like this:
so basically I want to know if I can add trace field outside the message tag so that it comes outside of jsonPayload structure.
<CloudLogging>
<LogName>projects/systems-apigee-dev/logs/apigee.googleapis.com%2Fproxy-logging-events</LogName>
<Message contentType="application/json">
{
"apigeeResourceName": "{apiproxy.name}",
"apiProxyRevision": "{apiproxy.revision}",
"inputPayload": "{escapeJSON(requestPayload)}",
"viesPayload": "{escapeJSON(calloutVIESResponse.content)}",
"responseSentToClient": "{escapeJSON(httpResponse)}",
"taxIdPayload": "{escapeJSON(calloutValidateResponse.content)}",
"responseErrorSentToClient":"{escapeJSON(httpErrorResponse)}",
"messageId":"{messageid}"
}
</Message>
<Labels>
<Label>
<Key>apiProxy</Key>
<Value>jsonUpload</Value>
</Label>
</Labels>
<ResourceType>api</ResourceType>
@shefali wrote:
But the load balancer trace is not visible because that works like this:
OK I am having trouble following what problem we are solving at this point. Load balancer?
I am sure there is context that I am missing.
@shefali wrote:
the trace query is formed like this and it gives only one result.
I don't understand this either. I don't know what you mean by "the trace query is formed like this" and "it gives one result." I see one result in your screenshot. But I don't understand the significance here. It seems like the query you provided... selects exactly one record. Is that bad? Is that... something you're not expecting?
can you step back and explain your situation from the beginning? as if I know nothing about what problem you are confronting?
I’d like to clarify my queries:
Question: Adding Fields Outside the <Message> Tag in the Message Logging Policy
Is there a way to add a field in the Message Logging Policy outside the <Message> tag?
For instance, I attempted to add a trace field (highlighted in bold in the example below). I realize this may not be the correct approach because it does not create the trace field in the Google Cloud logs.
Here’s an example of my current configuration:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<MessageLogging continueOnError="false" enabled="true" name="Log-Payloads">
<DisplayName>Log-Payloads</DisplayName>
<CloudLogging>
<LogName>projects/systems-apigee-dev/logs/apigee.googleapis.com%2Fproxy-logging-events</LogName>
<Message contentType="application/json">
{
"apigeeResourceName": "{apiproxy.name}",
"apiProxyRevision": "{apiproxy.revision}",
"inputPayload": "{escapeJSON(requestPayload)}",
"viesPayload": "{escapeJSON(calloutVIESResponse.content)}",
"responseSentToClient": "{escapeJSON(httpResponse)}",
"taxIdPayload": "{escapeJSON(calloutValidateResponse.content)}",
"responseErrorSentToClient":"{escapeJSON(httpErrorResponse)}",
"messageId":"{messageid}"
}
</Message>
<trace>{trace}</trace>
<Labels>
<Label>
<Key>apiProxy</Key>
<Value>jsonUpload</Value>
</Label>
</Labels>
<ResourceType>api</ResourceType>
</CloudLogging>
</MessageLogging>
ok, now I understand what you're asking ! Sadly the answer is no, today, you cannot set the Trace value on a LogEntry that is sent by the MessageLogging policy. This seems like a reasonable enhancement request. I can see why you'd want this! I've filed a ticket on your behalf. Internal reference: b/382569454 .
@dchiesa1 Thank you!! If you can provide a link to track this request, it would be great!
I myself cannot provide an externally-accessible link to track this request. But if you contact Apigee support and ask them to track it for you, they can do that. Open a support ticket and reference this internal feature request ID.
User | Count |
---|---|
1 | |
1 | |
1 | |
1 | |
1 |