- Newest
- Most votes
- Most comments
To effectively drop specific endpoints and reduce costs in CloudWatch Application Signals, you need to use the specific Sampling Rules syntax designed for the AWS Distro for OpenTelemetry (ADOT) collector. The generic "drop" action is often not recognized in the application_signals block; instead, the service relies on sampling logic to filter telemetry.
1. Updated CloudWatch Agent Configuration
Update your sidecar configuration to use sampling_rules. This tells the ADOT collector to ignore these paths before they are processed by the Application Signals managed service:
{
"traces": {
"traces_collected": {
"application_signals": {
"sampling_rules": [
{
"rule_name": "ExcludeHealthChecks",
"selectors": [
{
"dimension": "Operation",
"match": "GET /actuator/health/*"
}
],
"should_sample": false
}
]
}
}
}
}
- Wildcards: The * wildcard is fully supported for the Operation dimension.
- Cost Impact: By setting should_sample: false, these requests are not counted towards your Application Signals managed service charges because the telemetry is discarded at the agent level.
2. Application-Level Exclusion (Java Agent)
For optimal performance on ECS Fargate, you should also prevent the Java instrumentation from generating these spans in the first place. This reduces CPU overhead in your application container. Add this environment variable to your ECS Task Definition:
- Key:
OTEL_JAVAAGENT_EXCLUDED_URLS - Value:
/actuator/health/*
Answers to your specific questions:
- Is this the correct way? Yes, using sampling_rules within the application_signals block is the standard approach for ADOT-based monitoring.
- Traces vs. Logs? Focus on Traces. Application Signals dashboards and metrics are primarily derived from trace data. Filtering traces is the key to cost control.
- How long does it take? Changes take effect immediately upon restarting your ECS Tasks.
- Best Practice: Always use the
OTEL_JAVAAGENT_EXCLUDED_URLSvariable alongside the Agent's sampling rules for a "defense-in-depth" approach to telemetry filtering.
After investigating, I wasn't able to get Application Signals drop rules to reliably filter health check traces. I ended up switching to X-Ray centralized sampling rules with an ADOT Collector sidecar inside the task definition. This approach gave me full control over what gets sampled before traces are even sent.
Architecture
I replaced aws-otel-java-instrumentation + cloudwatch-agent with: ADOT Java agent (public.ecr.aws/aws-observability/adot-autoinstrumentation-java) — init container that copies the agent to a shared volume ADOT Collector sidecar — runs inside the same task, receives traces via OTLP and forwards to X-Ray. Also runs the awsproxy extension which is key for sampling rules to work.
Collector config
extensions:
awsproxy:
endpoint: 0.0.0.0:2000
region: us-east-1
receivers:
otlp:
protocols:
http:
endpoint: 0.0.0.0:4316
processors:
batch:
exporters:
awsxray:
region: us-east-1
service:
extensions: [awsproxy]
pipelines:
traces:
receivers: [otlp]
processors: [batch]
exporters: [awsxray]
Application container environment variables
{"name": "JAVA_TOOL_OPTIONS", "value": "-javaagent:/otel-auto-instrumentation/javaagent.jar"},
{"name": "OTEL_TRACES_SAMPLER", "value": "xray"},
{"name": "OTEL_TRACES_SAMPLER_ARG", "value": "endpoint=http://localhost:2000"},
{"name": "OTEL_TRACES_IDGENERATOR", "value": "xray"},
{"name": "OTEL_EXPORTER_OTLP_TRACES_ENDPOINT", "value": "http://localhost:4316/v1/traces"},
{"name": "OTEL_EXPORTER_OTLP_TRACES_PROTOCOL", "value": "http/protobuf"},
{"name": "OTEL_PROPAGATORS", "value": "tracecontext,baggage,b3,xray"},
{"name": "OTEL_METRICS_EXPORTER", "value": "none"},
{"name": "OTEL_LOGS_EXPORTER", "value": "none"}
Why awsproxy is essential
The ADOT Java agent's XraySamplerClient (activated by OTEL_TRACES_SAMPLER=xray) polls GetSamplingRules and GetSamplingTargets via unsigned plain HTTP. It cannot sign requests with SigV4 itself. The awsproxy extension acts as a local proxy on port 2000 that forwards those calls to the X-Ray API with proper SigV4 signing using the ECS task role credentials.
Without this proxy, the sampler silently fails to load rules. You'll see adaptive_sampling_configured=false on startup spans, and everything falls through to the Default rule (100% sample rate), including health checks.
X-Ray sampling rule to drop health checks
In X-Ray console → Sampling rules, create a rule with priority higher than Default (lower number = higher priority):
Field Value Rule name DropHealthChecks Priority 1 Reservoir size 0 Fixed rate 0% Service name * URL path /actuator/health/* Unsure if wildcard works, I've actually created both rules with wildcards and specific endpoints. Health check traces are dropped before recording. Rules take effect within ~10 seconds of the sampler's next polling cycle.
Critical gotcha: port 2000 must be TCP
The awsproxy extension uses HTTP (TCP). If your ECS security group has port 2000 open as UDP (which is the default for the legacy X-Ray daemon), the sampler will silently fail to contact the proxy and you'll never see sampling rules applied. Change the inbound rule for port 2000 to TCP.
IAM permissions for the task role
{
"Effect": "Allow",
"Action": [
"xray:GetSamplingRules",
"xray:GetSamplingTargets",
"xray:PutTraceSegments",
"xray:PutTelemetryRecords"
],
"Resource": "*"
}
The AWSXRayDaemonWriteAccess managed policy covers all of these.
Based on the available documentation for CloudWatch Application Signals, I can provide guidance on filtering telemetry data, though the specific drop rules configuration you're attempting may not be the standard approach.
Recommended Approaches for Filtering Endpoints
1. Disable Metrics Exporters Selectively
You can control what telemetry is sent by configuring environment variables in your application container. For your Java application on ECS Fargate, you're already using these key variables:
OTEL_AWS_APPLICATION_SIGNALS_ENABLED- Controls whether Application Signals telemetry is sentOTEL_METRICS_EXPORTER- Set tononeto disable other metrics exportersOTEL_LOGS_EXPORTER- Set tononeto disable other logs exporters
2. Application-Level Filtering
The most effective approach for filtering health check endpoints is typically at the application or OpenTelemetry instrumentation level, rather than at the CloudWatch agent level. You can:
- Configure the OpenTelemetry Java agent to exclude specific endpoints from instrumentation
- Use OpenTelemetry's sampling configuration to drop traces for specific patterns
- Implement custom span processors that filter out health check endpoints before they're exported
3. Endpoint Configuration
Ensure your metrics and traces are being sent to the correct endpoints:
OTEL_AWS_APPLICATION_SIGNALS_EXPORTER_ENDPOINTshould be set tohttp://localhost:4316/v1/metricsfor the sidecar configurationOTEL_EXPORTER_OTLP_TRACES_ENDPOINTshould be set tohttp://localhost:4316/v1/traces
Important Considerations
Protocol Setting: Make sure you have OTEL_EXPORTER_OTLP_PROTOCOL set to http/protobuf to properly send metrics and traces to Application Signals.
Version Requirements: Ensure you're using version 1.32.2 or later of the AWS Distro for OpenTelemetry auto-instrumentation agent for Java, as this is required for proper Application Signals functionality.
Alternative Approach
Since the drop rules in the CloudWatch agent configuration may not be the standard method for Application Signals, consider using OpenTelemetry's native filtering capabilities through environment variables or configuration files specific to the Java auto-instrumentation agent. This would allow you to filter traces before they even reach the CloudWatch agent, reducing both network overhead and costs more effectively.
Unfortunately, the specific syntax for drop rules within the Application Signals configuration isn't clearly documented in the standard setup guides, which suggests this may not be the intended filtering mechanism for this service.
Sources
Deploy using the daemon strategy - Amazon CloudWatch
Deploy using the sidecar strategy - Amazon CloudWatch
Thanks for your answer, here's some comments on the above:
- Disable Metrics Exporters Selectively I think this is how I want it to be today, I do want to have signals enabled.
- Application-Level Filtering I was hoping to get away without touching application's code When I used native's OpenTelemetry's sampling configuration to drop the traces (using file config), some of the specific config I was using for AWS got ignored, such as OTEL_AWS_APP_SIGNALS_ENABLED=true, or service name. So I ended up with no traces being tied and displayed next to their corresponding agents.
- Endpoint Configuration I think this is fine today, not representing a problem. Alternative Approach Somehow, using the native library was causing some of the features I wanted in signals to be ignored, for instance I was not able to browse traces by ECS service.
Relevant content
- asked 8 months ago

Thanks for your answer. Unfortunately, this did not work for me. Here are some findings: I noticed should_sample config flag is used in the python's library (aws-observability/aws-otel-python-instrumentation) but not on the java one. Also could not find any use of it on the sidecar I'm using here https://github.com/aws/amazon-cloudwatch-agent Similar to the above, found use of OTEL_PYTHON_EXCLUDED_URLS in the opentelemetry python's config (open-telemetry/opentelemetry-python-contrib) but nothing equivalent for java.