-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
[Stack Monitoring] Add OpenTelemetry metrics to Monitoring Collection plugin #135999
Changes from 4 commits
d911a31
2638cbb
218a4ff
70d0ed0
bb77bc1
b595d89
4ed979b
f4340ed
67e5a64
6812f29
0c71fa9
b716f3a
92a0862
0991876
76b7780
052b9dd
533bf45
9ab2f05
5c409c4
34f19d5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
{ | ||
"id": "openTelemetryInstrumentedPlugin", | ||
"owner": { | ||
"name": "Stack Monitoring", | ||
"githubTeam": "stack-monitoring-ui" | ||
}, | ||
"version": "1.0.0", | ||
"kibanaVersion": "kibana", | ||
"requiredPlugins": [ | ||
matschaffer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
"monitoringCollection" | ||
], | ||
"optionalPlugins": [], | ||
"server": true, | ||
"ui": false | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
|
||
import { OpenTelemetryUsageTest } from './plugin'; | ||
|
||
export const plugin = () => new OpenTelemetryUsageTest(); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
|
||
import { Counter, Meter } from '@opentelemetry/api-metrics'; | ||
|
||
export class Metrics { | ||
ruleExecutions: Counter; | ||
|
||
constructor(meter: Meter) { | ||
this.ruleExecutions = meter.createCounter('request_count', { | ||
description: 'Counts total number of requests', | ||
}); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
|
||
import { CoreSetup, Plugin } from '@kbn/core/server'; | ||
import { metrics } from '@opentelemetry/api-metrics'; | ||
import { generateOtelMetrics } from './routes'; | ||
import { Metrics } from './monitoring/metrics'; | ||
|
||
export class OpenTelemetryUsageTest implements Plugin { | ||
private metrics: Metrics; | ||
|
||
constructor() { | ||
this.metrics = new Metrics(metrics.getMeter('dummyMetric')); | ||
} | ||
|
||
public setup(core: CoreSetup) { | ||
const router = core.http.createRouter(); | ||
generateOtelMetrics(router, this.metrics); | ||
} | ||
|
||
public start() {} | ||
public stop() {} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
|
||
import { IKibanaResponse, IRouter } from '@kbn/core/server'; | ||
import { Metrics } from '../monitoring/metrics'; | ||
|
||
export const generateOtelMetrics = (router: IRouter, metrics: Metrics) => { | ||
router.post( | ||
{ | ||
path: '/api/generate_otel_metrics', | ||
validate: {}, | ||
}, | ||
async function (_context, _req, res): Promise<IKibanaResponse<{}>> { | ||
metrics.ruleExecutions.add(1); | ||
return res.ok({}); | ||
} | ||
); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
|
||
export * from './generate_otel_metrics'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0; you may not use this file except in compliance with the Elastic License | ||
* 2.0. | ||
*/ | ||
|
||
import { AggregationTemporality, MetricReader } from '@opentelemetry/sdk-metrics-base'; | ||
import { | ||
PrometheusExporter as OpenTelemetryPrometheusExporter, | ||
ExporterConfig, | ||
PrometheusSerializer, | ||
} from '@opentelemetry/exporter-prometheus'; | ||
import { KibanaResponseFactory } from '@kbn/core/server'; | ||
|
||
export class PrometheusExporter extends MetricReader { | ||
private readonly _prefix?: string; | ||
private readonly _appendTimestamp: boolean; | ||
private _serializer: PrometheusSerializer; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this can be just There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you mean without the type? It can, but then TS will understand that this an There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. without the underscore I mean :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For some reason my brain didn't read the underscore from your original comment lol. Yeah, I'll remove the underscore from these properties. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It doesn't hurt to leave them, but there are more examples without _ than with in the codebase. |
||
|
||
constructor(config: ExporterConfig = {}) { | ||
super(); | ||
this._prefix = config.prefix || OpenTelemetryPrometheusExporter.DEFAULT_OPTIONS.prefix; | ||
this._appendTimestamp = | ||
typeof config.appendTimestamp === 'boolean' | ||
? config.appendTimestamp | ||
: OpenTelemetryPrometheusExporter.DEFAULT_OPTIONS.appendTimestamp; | ||
|
||
this._serializer = new PrometheusSerializer(this._prefix, this._appendTimestamp); | ||
} | ||
|
||
selectAggregationTemporality(): AggregationTemporality { | ||
return AggregationTemporality.CUMULATIVE; | ||
} | ||
|
||
protected onForceFlush(): Promise<void> { | ||
return Promise.resolve(undefined); | ||
} | ||
|
||
protected onShutdown(): Promise<void> { | ||
return Promise.resolve(undefined); | ||
} | ||
|
||
/** | ||
* Responds to incoming message with current state of all metrics. | ||
*/ | ||
public async exportMetrics(res: KibanaResponseFactory) { | ||
try { | ||
const collectionResult = await this.collect(); | ||
const { resourceMetrics, errors } = collectionResult; | ||
if (errors.length) { | ||
return res.customError({ | ||
statusCode: 500, | ||
body: `PrometheusExporter: Metrics collection errors ${errors}`, | ||
}); | ||
} | ||
const result = this._serializer.serialize(resourceMetrics); | ||
if (result === '') { | ||
return res.noContent(); | ||
} | ||
return res.ok({ | ||
body: result, | ||
}); | ||
} catch (error) { | ||
return res.customError({ | ||
statusCode: 500, | ||
body: { | ||
message: `PrometheusExporter: Failed to export metrics ${error}`, | ||
}, | ||
}); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's get all the 0.29s out of here and just focus on 0.30