micrometer-metrics / micrometer

An application observability facade for the most popular observability tools. Think SLF4J, but for observability.
https://micrometer.io
Apache License 2.0
4.45k stars 981 forks source link

Introduce Metric Filtering for CloudWatch Integration #5154

Closed sumanmaity112 closed 3 months ago

sumanmaity112 commented 4 months ago

Please describe the feature request. Implement a filtering mechanism within Micrometer to selectively transmit metrics to CloudWatch.

Rationale We aim to reduce costs associated with excessive metric transmission while ensuring that all essential metrics remain accessible through the spring-boot-actuator /metrics (or similar) endpoint.

Additional context We utilize Micrometer alongside the CloudWatch registry for comprehensive metric monitoring within our application ecosystem. However, with the integration of tools like kafka, we've noticed a significant increase in the number of metrics being published to CloudWatch. This influx of metrics has resulted in unnecessary costs.

Propsed solution to have a Predicate<Meter> which will filter out the unnecessary meters. For example

private static boolean allowPublish(Meter meter) {
    return !meter.getId().getName().startsWith("kafka.consumer.");
}

// https://github.com/micrometer-metrics/micrometer/blob/main/implementations/micrometer-registry-cloudwatch2/src/main/java/io/micrometer/cloudwatch2/CloudWatchMeterRegistry.java#L154-L170 would look like follows

// VisibleForTesting
  List<MetricDatum> metricData(Predicate<Meter> allPublishPredicate) {
    Batch batch = new Batch();
    // @formatter:off
    return getMeters().stream()
        .filter(allPublishPredicate)
        .flatMap(
            m ->
                m.match(
                    batch::gaugeData,
                    batch::counterData,
                    batch::timerData,
                    batch::summaryData,
                    batch::longTaskTimerData,
                    batch::timeGaugeData,
                    batch::functionCounterData,
                    batch::functionTimerData,
                    batch::metricData))
        .collect(toList());
    // @formatter:on
  }

This concept is similar to MeterFilter(https://github.com/micrometer-metrics/micrometer/blob/main/micrometer-core/src/main/java/io/micrometer/core/instrument/config/MeterFilter.java) but it's only applicable for publishing part.

jonatan-ivanov commented 3 months ago

You might want to take a look at the MeterFilter again. You can set it per registry so if you have a MeterFilter on CloudWatchMeterRegistry but not on SimpleMeterRegistry, you should get the expected behavior (Boot sets it on CompositeMeterRegistry by default so it will affect both).

Also, I would be curious why you would not want something in CloudWatch but on the metrics endpoint. That endpoint is for troubleshooting-metrics purposes, you should not scrape it in prod.