Skip to content

6195: DelegatingMetricData. #7229

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

vasantteja
Copy link
Contributor

This Change

Context

This PR tries to solve this ticket. I preserved the original PR that was initially raised to add this class but I added a couple other enhancements that were mentioned in the PR. @jack-berg proposed two approaches for exposing other PointData interfaces:

  1. Creating Delegating Classes
  2. Adding Static Create Methods to Interfaces

I went with the second approach because it keeps the API simpler, consistent and avoids code duplication..

Implementation Example

Finally I am thinking people might be using this class with Metric Exporter as below:

import io.opentelemetry.sdk.common.CompletableResultCode;
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
import io.opentelemetry.sdk.metrics.data.Data;
import io.opentelemetry.sdk.metrics.data.DelegatingMetricData;
import io.opentelemetry.sdk.metrics.data.MetricData;
import io.opentelemetry.sdk.metrics.data.MetricDataType;
import io.opentelemetry.sdk.metrics.export.MetricExporter;
import io.opentelemetry.sdk.resources.Resource;

import java.util.ArrayList;
import java.util.Collection;
import java.util.function.Function;

/**
 * A MetricExporter that transforms metrics using a custom DelegatingMetricData implementation
 * before exporting them through a delegate exporter.
 */
public class TransformingMetricExporter implements MetricExporter {
    private final MetricExporter delegate;
    private final Function<MetricData, MetricData> transformer;

    /**
     * Creates a new TransformingMetricExporter.
     *
     * @param delegate The underlying exporter to send metrics to
     * @param namePrefix Prefix to add to all metric names
     * @param scaleFactor Factor to multiply all numeric values by (if applicable)
     */
    public TransformingMetricExporter(MetricExporter delegate, String namePrefix, double scaleFactor) {
        this.delegate = delegate;
        this.transformer = metric -> new CustomMetricData(metric, namePrefix, scaleFactor);
    }

    @Override
    public CompletableResultCode export(Collection<MetricData> metrics) {
        // Transform each metric before delegating to the wrapped exporter
        Collection<MetricData> transformedMetrics = new ArrayList<>(metrics.size());
        for (MetricData metric : metrics) {
            transformedMetrics.add(transformer.apply(metric));
        }
        return delegate.export(transformedMetrics);
    }

    @Override
    public CompletableResultCode flush() {
        return delegate.flush();
    }

    @Override
    public CompletableResultCode shutdown() {
        return delegate.shutdown();
    }

    /**
     * Custom implementation of DelegatingMetricData that modifies metric names and scales values.
     */
    private static class CustomMetricData extends DelegatingMetricData {
        private final String name;
        private final double scaleFactor;

        CustomMetricData(MetricData delegate, String namePrefix, double scaleFactor) {
            super(delegate);
            this.name = namePrefix + delegate.getName();
            this.scaleFactor = scaleFactor;
        }

        @Override
        public String getName() {
            return name;
        }

        @Override
        public Data<?> getData() {
            // Here you could implement value scaling logic based on the metric type
            // For example, you could create custom scaled versions of:
            // - LongSumData/DoubleSumData values
            // - HistogramData/ExponentialHistogramData values
            // - etc.
            
            return super.getData();
        }
        
        @Override
        public String toString() {
            return "CustomMetricData{name='" + name + "', scaled by " + scaleFactor + 
                   ", delegate=" + super.toString() + "}";
        }
    }
}

@vasantteja vasantteja requested a review from a team as a code owner March 30, 2025 23:25
Copy link

codecov bot commented Mar 30, 2025

Codecov Report

Attention: Patch coverage is 89.61039% with 8 lines in your changes missing coverage. Please review.

Project coverage is 89.96%. Comparing base (10eda19) to head (055fe19).
Report is 7 commits behind head on main.

Files with missing lines Patch % Lines
...ntelemetry/sdk/testing/metrics/TestMetricData.java 61.53% 5 Missing ⚠️
...lemetry/sdk/metrics/data/DelegatingMetricData.java 95.65% 0 Missing and 2 partials ⚠️
...io/opentelemetry/sdk/metrics/data/SummaryData.java 0.00% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main    #7229      +/-   ##
============================================
- Coverage     89.98%   89.96%   -0.02%     
- Complexity     6685     6719      +34     
============================================
  Files           749      765      +16     
  Lines         20191    20268      +77     
  Branches       1977     1985       +8     
============================================
+ Hits          18168    18234      +66     
- Misses         1431     1439       +8     
- Partials        592      595       +3     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Member

@jack-berg jack-berg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a handful of small comments. Looks pretty good!

*
* @return a ExponentialHistogramBuckets.
*/
@SuppressWarnings("TooManyParameters")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like you lifted this from ImmutableExponentialHistogramBuckets.create, but I don't think its needed in either place

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried resolving it but the build was failing with parameter overload error. I had to keep this in place to resolve it. Any suggestion on how I can resolve it?

@jack-berg
Copy link
Member

This PR also resolves #4389.

Copy link
Member

@jack-berg jack-berg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a handful of minor comments!

Copy link
Member

@jack-berg jack-berg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@jack-berg jack-berg merged commit 9cb6365 into open-telemetry:main Apr 11, 2025
28 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants