Ilmar Kerm

Oracle, databases, Linux and maybe more

WARNING! This post contains ClickOps methods.

I have a customer running Autota PostgreSQL in AWS and they wanted to monitor and alert certain database users on how much they read rows from the database.

For auditing PostgreSQL database there is a extension pgAudit, which is also by default installed in Aurora PostgreSQL. You can read about how to set it up for your AWS database here.

To enable auditing only on a specific user

ALTER USER "ilmar.kerm" SET pgaudit.log TO 'all';
ALTER USER "ilmar.kerm" SET pgaudit.log_catalog TO 'off';
ALTER USER "ilmar.kerm" SET pgaudit.log_parameter TO 'on';
ALTER USER "ilmar.kerm" SET pgaudit.log_rows TO 'on';

For my use case, the important bit is also to turn ON pgaudit.log_rows.

After that is done, pgAudit will emit a log record into the main PostgreSQL text log, that looks like this:

2024-12-18 02:25:44 UTC:10.20.30.40(53162):ilmar.kerm@egp:[32766]:LOG:  AUDIT: SESSION,94,1,READ,SELECT,,,"SELECT id, value, somethingelse FROM ""APPLSCHEMA1"".""TableName""",<none>,42

This audit record tells me that user “ilmar.kerm” executed SELECT id, value, somethingelse FROM “APPLSCHEMA1″.”TableName”, and that query returned 42 rows.

I now need to extract that value 42 from these audit rows and turn them into CloudWatch metric values.

Cloudwatch Metrics

To extract metric values from CloudWatch Logs, there are Metric filters, but they can only extract values from JSON or SPACE-DELIMITED log records. The pg_audit record above was COMMA-DELIMITED.

Very recently AWS announced an ability to transform logs (into JSON) on ingestion using pre-built or custom parsers. And the transformed logs can also be used to create Metric filters.

Don’t worry, the transformed log is store in addition to the old format, the old format is still accessible as-is. This ofcourse means that the amount of logs CloudWatch stores for PostgreSQL will double. A thing to keep in mind, and not enable auditing for the busy application users.

NB! The examples below use the dreaded ClickOps methodology, since currently AWS Terraform modules do not support this new feature.

First have to turn on the log transformer:

  1. Open the PostgreSQL database CloudWatch Log Group /aws/rds/cluster/CLUSTER_NAME/postgresql
  2. Navigate to Transformer and click Create transformer
  3. Choose a parser: Postgres
  4. Press Add processor
  5. Processor: CSV Source: body Delimiter: , Quote character:
  6. Under Columns it would be possible to give each column under body a proper name, but I’m not going to, since the transformations apply to all PostgreSQL log records, not just pgAudit.
  7. Press Save

Here is how the transformer settings look and also how a new transformed audit record will look like.

Every field is beautifully split into JSON attributes that we can extract for metric values. This is what we’ll do next.

Creating a metric to count all rows affected by audited operations.

  1. Navigate to Metric filters and press Create metric filter
  2. Create filter pattern: { $.body.column_1 = “AUDIT: SESSION” }
  3. Enable metric filter on transformed logs: ON
  4. Next
  5. Filter name: write something yourself
  6. Metric namespace and Metric name – write something yourself, this is how the metric will be named under CloudWatch Metrics
  7. Metric value: $.body.column_10
  8. Unit: Count
  9. Dimension name: operation, Dimension value: $.body.column_4

Something to keep in mind – auditing COPY command

pg_audit always reports that COPY command returns 0 rows. I would alert on all executed COPY commands.

To just count the COPY operations executed, create a new metric filter.

  1. Navigate to Metric filters and press Create metric filter
  2. Create filter pattern: { ($.body.column_1 = “AUDIT: SESSION”) && ($.body.column_4 = “READ”) && ($.body.column_5 = “COPY”) }
  3. Enable metric filter on transformed logs: ON
  4. Next
  5. Filter name: write something yourself
  6. Metric namespace and Metric name – write something yourself, this is how the metric will be named under CloudWatch Metrics
  7. Metric value: 1
  8. Unit: Count