user3474985
user3474985

Reputation: 1063

How do I define an AWS MetricFilter FilterPattern to match a JSON-formatted log event in CloudWatch?

I am trying to define a metric filter, in an AWS CloudFormation template, to match JSON-formatted log events from CloudWatch. Here is an example of the log event:

{
    "httpMethod": "GET",
    "resourcePath": "/deployment",
    "status": "403",
    "protocol": "HTTP/1.1",
    "responseLength": "42"
}

Here is my current attempt to create a MetricFilter to match the status field using the examples given from the documentation here: FilterAndPatternSyntax

"DeploymentApiGatewayMetricFilter": {
  "Type": "AWS::Logs::MetricFilter",
  "Properties": {
    "LogGroupName": "/aws/apigateway/DeploymentApiGatewayLogGroup",
    "FilterPattern": "{ $.status = \"403\" }",
    "MetricTransformations": [
      {
        "MetricValue": "1",
        "MetricNamespace": "ApiGateway",
        "DefaultValue": 0,
        "MetricName": "DeploymentApiGatewayUnauthorized"
      }
    ]
  }
}

I get a "Invalid metric filter pattern" message in CloudFormation.

Other variations I've tried that didn't work:

"{ $.status = 403 }" <- no escaped characters
{ $.status = 403 } <- using a json object instead of string

I've been able to successfully filter for space-delimited log events using the bracket notation defined in a similar manner but the json-formatted log events don't follow the same convention.

Upvotes: 4

Views: 8634

Answers (2)

xxkazunarixx
xxkazunarixx

Reputation: 74

I kept running into this error too, because I had the metric filter formatted with double quotes on the outside like this.

      FilterPattern: "{ ($.errorCode = '*UnauthorizedOperation') || ($.errorCode = 'AccessDenied*') }"

The docs say:

Strings that consist entirely of alphanumeric characters do not need to be quoted. Strings that have unicode and other characters such as ‘@,‘ ‘$,' ‘,' etc. must be enclosed in double quotes to be valid.

It didn't explicitly list the splat/wildcard * character, so I thought it would be OK inside single quotes, but it kept saying the metric filter pattern was bad because of the * in single quotes

I could have used single quotes around the outside of the pattern and double quotes around the strings inside, but I opted for escaping the double quotes like this instead.

      FilterPattern: "{ ($.errorCode = \"*UnauthorizedOperation\") || ($.errorCode = \"AccessDenied*\") }"

Upvotes: 0

dheffx
dheffx

Reputation: 140

Ran into the same problem and was able to figure it out by writing a few lines with the aws-cdk to generate the filter pattern template to see the difference between that and what I had.

Seems like it needs each piece of criteria wrapped in parenthesis.

- FilterPattern: '{ $.priority = "ERROR" && $.message != "*SomeMessagePattern*" }'
+ FilterPattern: '{ ($.priority = "ERROR") && ($.message != "*SomeMessagePattern*") }'

It is unfortunate that the AWS docs for MetricFilter in CloudFormation have no examples of JSON patterns.

Upvotes: 8

Related Questions