Skip to main content
Collect AWS CloudWatch logs with an OpenTelemetry collector and send them to ClickHouse Observability. Use the demo dataset to try the integration without configuring AWS access.

Prerequisites

  • A ClickHouse Observability service
  • Docker with Docker Compose to run the collector examples, or an existing OpenTelemetry Collector Contrib deployment
  • For your own logs, an AWS account with CloudWatch log groups, AWS CLI v2, and credentials with the permissions below
  • For the demo, curl to download the sample

Connection details

Open ClickHouse Observability and go to Team Settings → Data → Managed Telemetry. Copy your OTLP HTTP endpoint and API key. You can use Copy connection details to copy the configuration, or Reveal key to view the masked key.For the OTLP exporter examples below, set these variables in the terminal where you will run the collector:
Replace the placeholders with the exact endpoint, including its port, and API key from your service. Use the base HTTP endpoint without a /v1/logs suffix; the exporter appends the signal path.
The endpoint must be reachable from the collector container. For a destination collector running on this computer, use http://host.docker.internal:4318. The Docker commands below include the host mapping.

Integration with existing CloudWatch log groups

1

Configure AWS credentials

For AWS SSO, sign in and export temporary credentials in the terminal where you will start the collector:
Replace the profile name and region with your own. If you already use environment credentials, set AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_SESSION_TOKEN for temporary credentials, along with AWS_REGION. These credentials authorize reading AWS logs; they are separate from your destination’s OTLP credentials.The IAM identity needs these permissions. Replace YOUR_REGION and YOUR_ACCOUNT_ID; narrow the log-group resource to the groups you intend to collect where appropriate:
List the available log groups to choose the names for the configuration:
2

Configure the CloudWatch receiver

Save this as cloudwatch-logs.yaml. Replace /aws/lambda/my-function with a log group from your account; add other groups under named as needed.
This configuration starts with the last hour of logs and then polls every minute. Change initial_lookback to adjust the initial window. Without persistent checkpoint storage, restarting the collector can reread that window and produce duplicates.To discover groups by prefix instead, replace the groups block with:
Use either named or autodiscover. For additional options, including persistent checkpoints, see the CloudWatch receiver documentation.
3

Start the collector

Save this as docker-compose.yaml alongside cloudwatch-logs.yaml:
In the terminal where you set the AWS credentials and connection variables, start the collector and view its output:
4

Verify logs

Open Search in ClickHouse Observability, select your Logs source, and filter for ServiceName:cloudwatch. Select Last 2 hours and allow one or two polling intervals for logs to appear.Look for these resource attributes:
  • aws.region: the AWS region
  • cloudwatch.log.group.name: the log group
  • cloudwatch.log.stream: the log stream
The log message appears in Body. The receiver preserves the message but does not infer severity from its text. Severity-based dashboard panels require your logs pipeline to populate SeverityText.

Demo dataset

The sample contains 12,785 logs covering 24 hours of Lambda, ECS, and background-job activity. It includes log groups, streams, and severity values. This path does not require AWS credentials or direct database access.
1

Download the sample

2

Configure the demo collector

Save this as cloudwatch-demo.yaml in the download directory:
The demo configuration reads the sample’s ClickHouse row format and restores its log body, severity, and attributes. The timestamp transform shifts the sample into roughly the past 24 hours, ending two minutes before ingestion. Use the CloudWatch receiver configuration above for your own logs so their original timestamps are preserved.
3

Run the demo collector

Set the connection variables, then run this command from the download directory:
Keep the terminal open while the collector reads and exports the file. Check its output for errors. Running a fresh container again can duplicate the sample logs.
4

Verify the demo logs

Open Search, select your Logs source, filter for ServiceName:cloudwatch-demo, and select Last 2 days. Expand a log to inspect its body, severity, log group, and stream. Stop the demo collector with Ctrl+C after verifying the data.

Dashboards and visualization

1

2

Import the dashboard

  1. Open Dashboards and click Import in the upper-right corner.
  2. Upload cloudwatch-logs-dashboard.json.
  3. Map the charts to your Logs source and click Finish Import.
3

View the dashboard

Filter for ServiceName:cloudwatch-demo and select Last 2 days for the sample, or filter for ServiceName:cloudwatch and select a time range covering your own logs. The dashboard shows log volume, severity, and errors by log group. The demo includes severity values for all panels.

Troubleshooting

No logs appearing

  • Check docker compose logs otel-collector for AWS authentication, access-denied, or OTLP export errors.
  • Confirm AWS_REGION and log-group names match your account, and that the groups contain events within initial_lookback or new events after startup.
  • Check IAM permissions for logs:DescribeLogGroups and logs:FilterLogEvents.
  • Verify the destination endpoint and authentication settings from Connection details.
  • Check the Logs source, service-name filter, and time range. For the demo, select Last 2 days.

AWS credentials expired

For SSO, sign in and export fresh credentials again, then recreate the collector so it receives the new environment variables:
Restarting the existing container alone does not update its credentials. For other temporary credentials, refresh the access key, secret key, and session token before recreating it.

Missing older logs

The example starts with a one-hour lookback. Increase logs.initial_lookback, or replace it with logs.start_from using an RFC3339 timestamp for a specific start time. Do not set both. Restart the collector after changing its configuration; rereading a time window can produce duplicates.

Next steps

  • Set up alerts for error spikes.
  • Create additional dashboards.
  • For production, use an IAM role on your collector’s AWS infrastructure instead of manually exporting temporary credentials. See Sending OpenTelemetry data for deployment guidance.