Skip to content

OtlpJsonLoggingMetricExporter to accept a custom logger #8370

@Dainerx

Description

@Dainerx

Is your feature request related to a problem? Please describe.
We want to export the metrics into files and controlling the output files paths using SLF4J, the current implementation relies on the java.util.logging. In order to get it done we are under oblication to install a jul-sl4fj bridge for every service using the SDK.

Describe the solution you'd like
Make OtlpJsonLoggingMetricExporter accepting a custom logger on creation.

Describe alternatives you've considered
I had to write my own CustomOtlpJsonLoggingMetricExporter

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.io.SegmentedStringWriter;

import io.opentelemetry.exporter.internal.otlp.metrics.ResourceMetricsMarshaler;
import io.opentelemetry.sdk.common.CompletableResultCode;
import io.opentelemetry.sdk.metrics.InstrumentType;
import io.opentelemetry.sdk.metrics.data.AggregationTemporality;
import io.opentelemetry.sdk.metrics.data.MetricData;
import io.opentelemetry.sdk.metrics.export.MetricExporter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.Collection;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * This class duplicates {@link io.opentelemetry.exporter.logging.otlp.OtlpJsonLoggingMetricExporter}
 * and uses org.slf4j.Logger instead of java.util.logging.Logger.
 */
final class CustomOtlpJsonLoggingMetricExporter implements MetricExporter {
    private static final Logger logger = LoggerFactory.getLogger("io.opentelemetry.exporter.logging.otlp.OtlpJsonLoggingMetricExporter");
    private final AtomicBoolean isShutdown = new AtomicBoolean();
    private final AggregationTemporality aggregationTemporality;

    public static MetricExporter create(AggregationTemporality aggregationTemporality) {
        return new MurexOtlpJsonLoggingMetricExporter(aggregationTemporality);
    }

    private CustomOtlpJsonLoggingMetricExporter  (AggregationTemporality aggregationTemporality) {
        this.aggregationTemporality = aggregationTemporality;
    }

    /**
     * @deprecated
     */
    @Deprecated
    public AggregationTemporality getPreferredTemporality() {
        return this.aggregationTemporality;
    }

    public AggregationTemporality getAggregationTemporality(InstrumentType instrumentType) {
        return this.aggregationTemporality;
    }

    public CompletableResultCode export(Collection<MetricData> metrics) {
        if (this.isShutdown.get()) {
            return CompletableResultCode.ofFailure();
        } else {
            ResourceMetricsMarshaler[] allResourceMetrics = ResourceMetricsMarshaler.create(metrics);

            for (ResourceMetricsMarshaler resourceMetrics : allResourceMetrics) {
                SegmentedStringWriter sw = new SegmentedStringWriter(JsonUtil.JSON_FACTORY._getBufferRecycler());

                try {
                    JsonGenerator gen = JsonUtil.create(sw);

                    try {
                        resourceMetrics.writeJsonTo(gen);
                    } catch (Throwable var13) {
                        if (gen != null) {
                            try {
                                gen.close();
                            } catch (Throwable var11) {
                                var13.addSuppressed(var11);
                            }
                        }

                        throw var13;
                    }

                    if (gen != null) {
                        gen.close();
                    }
                } catch (IOException var14) {
                    continue;
                }

                try {
                    logger.info(sw.getAndClear());
                } catch (IOException e) {
                    logger.warn("Unable to read OTLP JSON metrics", e);
                }
            }

            return CompletableResultCode.ofSuccess();
        }
    }

    public CompletableResultCode flush() {
        return CompletableResultCode.ofSuccess();
    }

    public CompletableResultCode shutdown() {
        return CompletableResultCode.ofSuccess();
    }

    final class JsonUtil {
        static final JsonFactory JSON_FACTORY = new JsonFactory();

        static JsonGenerator create(SegmentedStringWriter stringWriter) {
            try {
                return JSON_FACTORY.createGenerator(stringWriter);
            } catch (IOException e) {
                throw new IllegalStateException("Unable to create in-memory JsonGenerator, can't happen.", e);
            }
        }

        private JsonUtil() {
        }
    }


}

Additional context
N/A
Tip: React with 👍 to help prioritize this issue. Please use comments to provide useful context, avoiding +1 or me too, to help us triage it. Learn more here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Feature RequestSuggest an idea for this project

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions