Monitoring AWS CloudWatch logs
This guide walks you through forwarding AWS CloudWatch logs into Managed ClickStack using the OpenTelemetry awscloudwatch receiver, then viewing them in the ClickStack UI.
We'll run a separate collector that polls CloudWatch via the AWS API and forwards events to your ClickStack collector via OTLP. Keep this collector in the same AWS account and region as the log groups to minimise API latency and cost.
This guide assumes you've completed Setting up your OpenTelemetry Collector and have a ClickStack collector running.
The ClickStack collector can be deployed either as a Docker container (see Setting up your OpenTelemetry Collector) or as a Helm release in Kubernetes via the upstream OpenTelemetry Helm chart with the ClickStack collector image (see Deploying the collector). Ensure you have recorded its OTLP endpoint and the OTLP_AUTH_TOKEN you set when deploying it.
Gather your prerequisites
You'll need:
- An AWS account with one or more CloudWatch log groups and credentials with the IAM permissions below.
- A host with Docker installed, AWS API access, and outbound network access to your ClickStack collector. Typically this is an EC2 instance in the same AWS account and region as the log groups.
- The OTLP endpoint of your ClickStack collector, reachable from this host. If it's running in Docker on the same machine, use
http://host.docker.internal:4318(see the callout in Configure the CloudWatch receiver). For a remote collector, use its full URL, for examplehttps://otel.example.com:4318. - The
OTLP_AUTH_TOKENvalue you set on your ClickStack collector. If you didn't secure it, you can drop theauthorizationheader from the config below.
Configure AWS credentials
The receiver picks up AWS credentials from the standard environment variables. Export them on the host that will run the collector.
For AWS SSO users:
For IAM users with long-term credentials:
The credentials need the following IAM policy to read CloudWatch logs:
Replace YOUR_ACCOUNT_ID with your AWS account ID.
For production, prefer instance-attached credentials over long-term keys: an IAM role on EC2, IRSA on EKS, or a task role on ECS. The same collector config below works without any credential env vars when the receiver can resolve credentials from the instance metadata service.
Configure the CloudWatch receiver
Export your ClickStack collector endpoint and auth token, then create an otel-collector-config.yaml.
The example below assumes the ClickStack collector and this CloudWatch collector run on the same host, so the receiver connects to it via host.docker.internal (the Docker host's address from inside a container). If your ClickStack collector lives elsewhere (an in-cluster service, a public URL, a private IP), substitute its address in OTEL_COLLECTOR_ENDPOINT below.
Discover the log groups available in your account
Before editing the config, list the log groups that exist in your region so you can pick real names (and confirm the region is correct):
Example output:
Use the names from this list directly in the groups.named block of Example 1 below. For the account above, the named-groups section would become:
Alternatively, if the groups you want share a common prefix (here /aws-glue/), use Example 2 with prefix: /aws-glue/ instead of listing them individually.
Example 1: Named log groups (recommended)
Example 2: Autodiscover log groups by prefix
Key settings to adjust:
regionto match where your log groups live.poll_interval(1mdefault). Lower values give near-real-time logs at the cost of more AWS API calls.groups.namedfor an explicit list, orgroups.autodiscover.prefixto pick up every group matching a prefix.
For the full set of options, see the CloudWatch receiver documentation.
On first run, the receiver checkpoints at the current time and only fetches logs from that point forward. Historical logs aren't backfilled.
Start the receiver collector
Create a docker-compose.yaml alongside otel-collector-config.yaml. The extra_hosts entry lets the container reach a ClickStack collector running on the same host via host.docker.internal; the long-form bind mount errors explicitly if the config file is missing, rather than silently creating an empty directory:
Start the collector:
Tail its logs to confirm it's polling CloudWatch and exporting to your ClickStack collector:
Confirm in the ClickStack UI
Open your service in the ClickHouse Cloud console and select ClickStack from the left menu.
In the Search view, switch the source to Logs and set the time range to Last 15 minutes. CloudWatch events should appear within a couple of poll intervals.
Each event carries the source group and stream as resource attributes:
ResourceAttributes['aws.region']: the AWS region (for exampleeu-central-1)ResourceAttributes['cloudwatch.log.group.name']: the source log groupResourceAttributes['cloudwatch.log.stream']: the source log streamBody: the original log line
Modify the search to Timestamp, SeverityText as level, ResourceAttributes['aws.region'], ResourceAttributes['cloudwatch.log.group.name'], ResourceAttributes['cloudwatch.log.stream'], Body to include these attributes:
Select a log entry to inspect is metadata:
If nothing shows up:
- Run
aws sts get-caller-identityon the collector host to confirm credentials are valid. - Tail the collector with
docker compose logs -f otel-collectorand look forAccessDeniedException(IAM),security tokenerrors (expired SSO credentials),ResourceNotFoundException(log group name typo or wrong region), orconnection refused(your ClickStack collector endpoint is unreachable from inside the container, see thehost.docker.internalnote in Configure the CloudWatch receiver). - Verify
OTEL_COLLECTOR_ENDPOINTis reachable from inside the container:docker compose exec otel-collector wget -qO- ${OTEL_COLLECTOR_ENDPOINT}/v1/logs -S 2>&1 | head -5. - Confirm
OTLP_AUTH_TOKENmatches the value set on your ClickStack collector.
Import the CloudWatch dashboard (optional)
A pre-built dashboard with log volume, severity breakdown, and error distribution is available for download.
Download cloudwatch-logs-dashboard.json, then in the ClickStack UI navigate to Dashboards, click Import.
Upload the JSON file and click Finish Import.
Further reading
- AWS CloudWatch logs integration reference for the demo dataset, full troubleshooting, and tuning options.
- Securing the collector with TLS on the OTLP endpoint and least-privilege ingestion users.
- Processing, filtering, and enriching events at the collector.
- Going to production for recommendations when going to production.