Issue with Cloud Logging from a FaultRule

Hello,

I'm attempting to write a policy which sends fault properties to Cloud Logging any time a fault occurs due to a bad revision in Apigee. So far I have the following:

Fault Rule in Proxy Endpoint Config

<FaultRules>
    <FaultRule name="logonfault">
      <Step>
        <Name>ML-onfault</Name>
        <Condition>(fault.name notequals null) </Condition>
      </Step>
      <AlwaysEnforce>true</AlwaysEnforce>
    </FaultRule>
  </FaultRules>

On Fault Message Logging Policy:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<MessageLogging continueOnError="true" enabled="true" name="ML-onfault">
  <DisplayName>ML-onfault</DisplayName>
  <CloudLogging>
    <LogName>projects/{organization.name}/logs/apigee</LogName>
    <Message contentType="application/json">
        {
         "org": "{organization.name}",
         "gcp.project.id": "{organization.name}",
         "environment_name": "{environment.name}",
         "proxy_name": "{apiproxy.name}",
         "proxy_revision": "{apiproxy.revision}",
         "fault": "{fault.name}",
         "error": "{error.reason.phrase}",
         "error_message": "{error.content}",
         "trace_id": "{xxx}"
        }
    </Message>
    <Labels>
    </Labels>
    <ResourceType>gce_instance</ResourceType>
  </CloudLogging>
</MessageLogging>

When debugging, I see the following:

2024-03-08_13-26-32.png

 The onfault policy seems to be executed, but no logs are produced. Is there something I'm missing?

Solved Solved
2 2 91
1 ACCEPTED SOLUTION

I suspect the JSON payload that results from that policy, is broken.

You have this line in the message template for your MessageLogging policy:

 

"error_message": "{error.content}",

 

And  from your screenshot I can see that error.content is a JSON payload. The result of that template is a json payload wrapped within double quotes. That won't work. That will not result in a valid JSON.

To see what I mean, try this. Here's a simple JSON payload: { "foo": "bar" } . Suppose that is the value held by error.content.

Now when Apigee evaluates the message template for this line:

 

"error_message": "{error.content}",

 

...the result will be:

 

"error_message": "{ "foo": "bar" }",

 

Do you see? That's not valid JSON!  It looks sort of json-ish, the quotes are balanced.  But it's not valid.  Your error.content is a bit more involved, but it's still JSON, and the result of wrapping quotes around it, will similarly result in something that is not a valid JSON value. If the GCP logging endpoint receives malformed JSON, it ignores it. That is why you see no log messages.

What can you do?

  1. you could NOT wrap it in quotes. If error.content is always json, then the following would result in valid JSON output:

    "error_message": {error.content},
  2. you could escape it. This is probably safer, if the error.content might not always be guaranteed to be valid json.

    "error_message": "{escapeJSON(error.content)}",

View solution in original post

2 REPLIES 2

I suspect the JSON payload that results from that policy, is broken.

You have this line in the message template for your MessageLogging policy:

 

"error_message": "{error.content}",

 

And  from your screenshot I can see that error.content is a JSON payload. The result of that template is a json payload wrapped within double quotes. That won't work. That will not result in a valid JSON.

To see what I mean, try this. Here's a simple JSON payload: { "foo": "bar" } . Suppose that is the value held by error.content.

Now when Apigee evaluates the message template for this line:

 

"error_message": "{error.content}",

 

...the result will be:

 

"error_message": "{ "foo": "bar" }",

 

Do you see? That's not valid JSON!  It looks sort of json-ish, the quotes are balanced.  But it's not valid.  Your error.content is a bit more involved, but it's still JSON, and the result of wrapping quotes around it, will similarly result in something that is not a valid JSON value. If the GCP logging endpoint receives malformed JSON, it ignores it. That is why you see no log messages.

What can you do?

  1. you could NOT wrap it in quotes. If error.content is always json, then the following would result in valid JSON output:

    "error_message": {error.content},
  2. you could escape it. This is probably safer, if the error.content might not always be guaranteed to be valid json.

    "error_message": "{escapeJSON(error.content)}",

Interesting. The invalid json shown in the error message is from the previous policy, which I broke on purpose to enforce the "onfault" policy. I don't see any message about invalid json from the onfault policy which seems to throw no error. I'm assuming thats because I use:

continueOnError="true"

 for purposes of keeping functional code graceful...

I did however change the error_message attribute to contain the JSON and, sure enough, it worked. So thank you very much for the second pair of eyes!