Logging database errors and queries to Amazon Web Services CloudWatch Logs
July 8, 2025
Exemplifies a PHP way to use Amazon Web Services CloudWatch to log database errors and queries run. (Yes, PHP in 2025!).

Ever grow tired of storing logs on a server then having to manage access to the logs for individual users working in a collaborative development team? This post explores an alternative method to manage database logging by making use of the Amazon Web Services (AWS) CloudWatch Logs service. After reading this post you should have an idea of how to code PHP to send database logs to AWS CloudWatch. This approach offers several advantages over storing logs on a server filesystem, including:
- Infrastructure is managed by AWS.
- Permissions to logs are orchestrated through AWS IAM which can greatly improve means of access when working within a development team.
- Can be integrated as part of an organization wide logging structure with AWS CloudWatch Logs.
- Can use CloudWatch metric filters to create data visualizations of the log data and generate alarms from those metrics using CloudWatch Alarms.
This post depends on setting up a database configuration file which is covered in a previous post: Connecting Python to a Postgresql database.
Requirements
- PHP 8 (preferably running on Ubuntu)
- PHP composer
- PHP composer packages: aws/aws-sdk-php, legalthings/cloudwatch-logger
- AWS: Programmatic Access
- AWS: Key Management Service (KMS) Customer managed symmetric key
- AWS: CloudWatch Logs - Log Groups and Streams
- Postgresql database cluster (needs to accept TCP/IP connections)
- Database created on Postgresql cluster
Set up Log Group and Log Streams in AWS
First we need to create a log group and two log streams within the group which will store our database sql queries and errors. A log group named 'sdk' with two log streams named 'php/database/sql/' and 'php/database/errors/' have been created. After creating the log group and streams, ensure that the programmatic AWS user has the necessary AWS IAM credentials to write to the log streams which is the PutLogEvents API call. The simplest way to try out the example in this post is to attach the managed policy CloudWatchLogsFullAccess to the IAM user or group. The log stream structure looks like the below from the AWS console:

Create CloudWatch Logs / KMS / CloudWatchLogger instances in PHP
Use PHP composer to install the AWS PHP SDK and logging packages - note the cloudwatch-logger package from legalthings is used here. Then create the CloudWatch Logs / KMS / CloudWatchLogger instances in the PHP program. Since the instances are essential to the rest of the program, a try / catch block with an exit statement is used in their instantiation. If unable to connect to the AWS CloudWatch Logs or KMS services, check the IaM permissions for the programmatic user.
Read database connection properties from encrypted configuration file
Now we will need to identify the database and user details used to connect to a PostgreSQL cluster and database. From the previous post, Connecting Python to a Postgresql database, the connection details will be read from a file storing the sensitive data in encrypted format. Then the AWS KMS key used to encrypt the data will be used to decrypt the connection details so a connection can be made to the PostgreSQL database.
Capture decryption errors in AWS CloudWatch Logs
If an error was encountered during the encryption attempt there will be a log in the AWS CloudWatch Logs log stream previously configured: php/database/errors/. For simulation's sake we have generated an error to create a log record which appears in the AWS CloudWatch logs console as shown below.

Connect to PostgreSQL database and capture connection errors in AWS CloudWatch Logs
Finally it is time to connect to the database. PHP's PDO data access layer is great for abstracting calls to database operations and easy to instantiate. To show the usefulness of CloudWatch logs a simulation of a failed connection attempt is run here.
In using a bogus port of 65535 while attempting to connect via PHP PDO to a PostgreSQL database the try / catch entered the catch block and generated a log to the php/database/errors/ logstream. The log from the AWS CloudWatch logs console is shown below.

Log a succesfully run query
// Run an example query. Log successful queries to the sql log stream
// and any errors to the error log stream in CloudWatch Logs.
try {
$qry = 'SELECT datname, datcollate FROM pg_database;';
$stmt = $pdo->query($qry);
$sql_logger->log(["User: ${db_user}: Query: " => $qry]);
}
// Log failed query prepare statements to CloudWatch Logs.
catch (PDOException $e) {
$error_logger->log(['Problem with query ' => $e->getMessage()]);
exit("Unable to prepare query : ${qry}.");
}
And this time the log goes to the php/database/sql/ logstream.

What can be learned from this article
Making use of AWS CloudWatch logs can simplify database error and query logging, especially if working collaboratively within a team which uses an AWS infrastructure. Instead of manually logging to files on a workstation's filesystem during development, the approach in this post emphasizes sending log data to CloudWatch logs where the logs can be analyzed further. AWS SDK's make logging simple when combined with a robust logging client such as the CloudWatchLogger from LegalThings.