Skip to content
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

Metrics not exported when multiple exporters are present #1900

Closed
chippment opened this issue Jan 15, 2024 · 4 comments
Closed

Metrics not exported when multiple exporters are present #1900

chippment opened this issue Jan 15, 2024 · 4 comments
Labels
bug Something isn't working

Comments

@chippment
Copy link

chippment commented Jan 15, 2024

What version of OpenTelemetry are you using?

    "@opentelemetry/api": "1.7.0",
    "@opentelemetry/auto-instrumentations-node": "0.40.2",
    "@opentelemetry/exporter-metrics-otlp-grpc": "0.46.0",
    "@opentelemetry/exporter-metrics-otlp-proto": "0.46.0",
    "@opentelemetry/exporter-prometheus": "0.47.0",
    "@opentelemetry/host-metrics": "0.34.1",
    "@opentelemetry/sdk-node": "0.46.0",

What version of Node are you using?

v21.5.0

What did you do?

My use case is that the instrumentation shall use two separate exporters to export to two different endpoints. However, the data only gets exported via the first configured exporter. The second exporter receives an empty list of scope metrics in the export function.

Here is a sample application that reproduces the issue:

monitoring.js:

const { HostMetrics } = require('@opentelemetry/host-metrics');
const { PrometheusExporter } = require('@opentelemetry/exporter-prometheus');
const { NodeSDK } = require("@opentelemetry/sdk-node")
const { PeriodicExportingMetricReader, ConsoleMetricExporter } = require("@opentelemetry/sdk-metrics");
const { metrics } = require('@opentelemetry/api');

const exporter = new PrometheusExporter(
  {
    startServer: true
  }, () => {
    console.log('prometheus scrape endpoint: http://localhost:9464/metrics')
  }
);

const sdk = new NodeSDK({
    metricReader: exporter
});

sdk.start();

const hostMetrics = new HostMetrics({ name: 'example-host-metrics' });
hostMetrics.start();

const periodicReader = new PeriodicExportingMetricReader({
    exportIntervalMillis: 5000,
    exporter: new ConsoleMetricExporter() // this will never print any of the host metrics
});

metrics.getMeterProvider().addMetricReader(periodicReader) // expecting this to be the one global meter provider

app.js:

const express = require('express')
const app = express()

app.get('/', function (req, res) {
  res.send('Hello World')
})

app.listen(3000)

start via: node -r ./monitoring.js app.js

What did you expect to see?

Metrics being exported to two different endpoints via two different exporters.

What did you see instead?

Only the first exporter receiving a list of scope metrics while the second one receives an empty list. Thus, nothing gets exported via the second exporter.

Additional context

@chippment chippment added the bug Something isn't working label Jan 15, 2024
@pichlermarc
Copy link
Member

This was actually never intended to be used in that way and it's a problem with how we designed the Metrics SDK (see open-telemetry/opentelemetry-js#4112 (comment)) as it actually looks like this could work. To work around this, we could add a feature the @opentelemetry/sdk-node so that multiple readers can be added on SDK creation.

Also note that this is actually getting the API type of the MeterProvider which does not advertise having such a method.

@chippment
Copy link
Author

Is there any workaround available for the time being?

@pichlermarc
Copy link
Member

pichlermarc commented Jan 16, 2024

A workaround may be to call addMetricReader() before creating any instruments (in the example above, do something like this):

const { HostMetrics } = require('@opentelemetry/host-metrics');
const { PrometheusExporter } = require('@opentelemetry/exporter-prometheus');
const { NodeSDK } = require("@opentelemetry/sdk-node")
const { PeriodicExportingMetricReader, ConsoleMetricExporter } = require("@opentelemetry/sdk-metrics");
const { metrics } = require('@opentelemetry/api');

const exporter = new PrometheusExporter(
  {
    startServer: true
  }, () => {
    console.log('prometheus scrape endpoint: http://localhost:9464/metrics')
  }
);

const sdk = new NodeSDK({
    metricReader: exporter
});

sdk.start();

// Add metric reader before using host metrics
const periodicReader = new PeriodicExportingMetricReader({
    exportIntervalMillis: 5000,
    exporter: new ConsoleMetricExporter()
});

metrics.getMeterProvider().addMetricReader(periodicReader) // expecting this to be the one global meter provider

// Start up host metrics after registering the MetricReader
const hostMetrics = new HostMetrics({ name: 'example-host-metrics' });
hostMetrics.start();

this would cause the instruments in HostMetrics to be created AFTER registering the MetricReader.

@dyladan
Copy link
Member

dyladan commented Jan 17, 2024

I see your 👍 . Can you please close this issue if it is resolved? If not I will close it in 2 weeks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants