diff --git a/packages/opentelemetry-exporter-prometheus/src/PrometheusExporter.ts b/packages/opentelemetry-exporter-prometheus/src/PrometheusExporter.ts index d47745980c..cbd22623d6 100644 --- a/packages/opentelemetry-exporter-prometheus/src/PrometheusExporter.ts +++ b/packages/opentelemetry-exporter-prometheus/src/PrometheusExporter.ts @@ -29,6 +29,7 @@ import { PrometheusLabelsBatcher } from './PrometheusLabelsBatcher'; export class PrometheusExporter implements MetricExporter { static readonly DEFAULT_OPTIONS = { + host: undefined, port: 9464, endpoint: '/metrics', prefix: '', @@ -36,6 +37,7 @@ export class PrometheusExporter implements MetricExporter { }; private readonly _logger: api.Logger; + private readonly _host?: string; private readonly _port: number; private readonly _endpoint: string; private readonly _server: Server; @@ -55,7 +57,14 @@ export class PrometheusExporter implements MetricExporter { */ constructor(config: ExporterConfig = {}, callback?: () => void) { this._logger = config.logger || new api.NoopLogger(); - this._port = config.port || PrometheusExporter.DEFAULT_OPTIONS.port; + this._host = + config.host || + process.env.OTEL_EXPORTER_PROMETHEUS_HOST || + PrometheusExporter.DEFAULT_OPTIONS.host; + this._port = + config.port || + Number(process.env.OTEL_EXPORTER_PROMETHEUS_PORT) || + PrometheusExporter.DEFAULT_OPTIONS.port; this._prefix = config.prefix || PrometheusExporter.DEFAULT_OPTIONS.prefix; this._appendTimestamp = typeof config.appendTimestamp === 'boolean' @@ -72,7 +81,9 @@ export class PrometheusExporter implements MetricExporter { ).replace(/^([^/])/, '/$1'); if (config.preventServerStart !== true) { - this.startServer().then(callback); + this.startServer() + .then(callback) + .catch(err => this._logger.error(err)); } else if (callback) { callback(); } @@ -148,12 +159,18 @@ export class PrometheusExporter implements MetricExporter { */ startServer(): Promise { return new Promise(resolve => { - this._server.listen(this._port, () => { - this._logger.debug( - `Prometheus exporter started on port ${this._port} at endpoint ${this._endpoint}` - ); - resolve(); - }); + this._server.listen( + { + port: this._port, + host: this._host, + }, + () => { + this._logger.debug( + `Prometheus exporter server started: ${this._host}:${this._port}/${this._endpoint}` + ); + resolve(); + } + ); }); } diff --git a/packages/opentelemetry-exporter-prometheus/src/export/types.ts b/packages/opentelemetry-exporter-prometheus/src/export/types.ts index 40efc413cf..ad0e6e03ca 100644 --- a/packages/opentelemetry-exporter-prometheus/src/export/types.ts +++ b/packages/opentelemetry-exporter-prometheus/src/export/types.ts @@ -39,6 +39,11 @@ export interface ExporterConfig { */ endpoint?: string; + /** + * @default undefined (all interfaces) + */ + host?: string; + /** * Port number for Prometheus exporter server * diff --git a/packages/opentelemetry-exporter-prometheus/test/PrometheusExporter.test.ts b/packages/opentelemetry-exporter-prometheus/test/PrometheusExporter.test.ts index cb5ccb93bc..fe88e6c477 100644 --- a/packages/opentelemetry-exporter-prometheus/test/PrometheusExporter.test.ts +++ b/packages/opentelemetry-exporter-prometheus/test/PrometheusExporter.test.ts @@ -33,6 +33,11 @@ describe('PrometheusExporter', () => { mockAggregator(LastValueAggregator); mockAggregator(HistogramAggregator); + afterEach(() => { + delete process.env.OTEL_EXPORTER_PROMETHEUS_HOST; + delete process.env.OTEL_EXPORTER_PROMETHEUS_PORT; + }); + describe('constructor', () => { it('should construct an exporter', done => { const exporter = new PrometheusExporter(); @@ -62,7 +67,7 @@ describe('PrometheusExporter', () => { }); describe('server', () => { - it('it should start on startServer() and call the callback', done => { + it('should start on startServer() and call the callback', done => { const exporter = new PrometheusExporter({ port: 9722, preventServerStart: true, @@ -74,7 +79,7 @@ describe('PrometheusExporter', () => { }); }); - it('it should listen on the default port and default endpoint', done => { + it('should listen on the default port and default endpoint', done => { const port = PrometheusExporter.DEFAULT_OPTIONS.port; const endpoint = PrometheusExporter.DEFAULT_OPTIONS.endpoint; const exporter = new PrometheusExporter({}, () => { @@ -88,7 +93,7 @@ describe('PrometheusExporter', () => { }); }); - it('it should listen on a custom port and endpoint if provided', done => { + it('should listen on a custom port and endpoint if provided', done => { const port = 9991; const endpoint = '/metric'; @@ -109,7 +114,17 @@ describe('PrometheusExporter', () => { ); }); - it('it should not require endpoints to start with a slash', done => { + it('should listen on environmentally set host and port', () => { + process.env.OTEL_EXPORTER_PROMETHEUS_HOST = '127.0.0.1'; + process.env.OTEL_EXPORTER_PROMETHEUS_PORT = '1234'; + const exporter = new PrometheusExporter({}, async () => { + await exporter.shutdown(); + }); + assert.strictEqual(exporter['_host'], '127.0.0.1'); + assert.strictEqual(exporter['_port'], 1234); + }); + + it('should not require endpoints to start with a slash', done => { const port = 9991; const endpoint = 'metric'; @@ -144,7 +159,7 @@ describe('PrometheusExporter', () => { ); }); - it('it should return a HTTP status 404 if the endpoint does not match', done => { + it('should return a HTTP status 404 if the endpoint does not match', done => { const port = 9912; const endpoint = '/metrics'; const exporter = new PrometheusExporter(