Memoized renderering (#37)
Pre-render metrics on discovery once and then reuse rendered response.
This commit is contained in:
parent
565f423dd9
commit
65304798de
4 changed files with 19 additions and 18 deletions
|
@ -28,5 +28,5 @@ export interface HttpServer {
|
|||
onMetrics(): HttpResponse
|
||||
onNotFound(): HttpResponse
|
||||
onError(error: Error): HttpResponse
|
||||
updateMetrics(metrics: Metric[]): void
|
||||
onMetricsDiscovery(metrics: Metric[]): void
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ export class PrometheusExporterPlatform implements IndependentPlatformPlugin {
|
|||
discover({ log: this.log, config: this.config })
|
||||
.then((devices) => {
|
||||
const metrics = aggregate(devices, new Date())
|
||||
this.httpServer.updateMetrics(metrics)
|
||||
this.httpServer.onMetricsDiscovery(metrics)
|
||||
this.log.debug('HAP discovery completed, %d metrics discovered', metrics.length)
|
||||
this.startHapDiscovery()
|
||||
})
|
||||
|
|
|
@ -44,13 +44,17 @@ function headers(contentType: string, headers: Record<string, string> = {}): Rec
|
|||
}
|
||||
|
||||
export class PrometheusServer implements HttpServer {
|
||||
private metricsInitialized = false
|
||||
private metrics: Metric[] = []
|
||||
private metricsDiscovered = false
|
||||
private metricsResponse = ''
|
||||
|
||||
constructor(public readonly config: HttpConfig, public readonly log: Logger | undefined = undefined) {}
|
||||
constructor(
|
||||
public readonly config: HttpConfig,
|
||||
public readonly log: Logger | undefined = undefined,
|
||||
private readonly renderer: MetricsRenderer = new MetricsRenderer(config.prefix),
|
||||
) {}
|
||||
|
||||
onRequest(): HttpResponse | undefined {
|
||||
if (!this.metricsInitialized) {
|
||||
if (!this.metricsDiscovered) {
|
||||
return {
|
||||
statusCode: 503,
|
||||
headers: headers(textContentType, { 'Retry-After': String(retryAfterWhileDiscovery) }),
|
||||
|
@ -60,13 +64,10 @@ export class PrometheusServer implements HttpServer {
|
|||
}
|
||||
|
||||
onMetrics(): HttpResponse {
|
||||
const renderer = new MetricsRenderer(this.config.prefix)
|
||||
const metrics = this.metrics.map((metric) => renderer.render(metric)).join('\n')
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
headers: headers(metricsContentType),
|
||||
body: metrics,
|
||||
body: this.metricsResponse,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,9 +87,9 @@ export class PrometheusServer implements HttpServer {
|
|||
}
|
||||
}
|
||||
|
||||
updateMetrics(metrics: Metric[]): void {
|
||||
this.metrics = metrics
|
||||
this.metricsInitialized = true
|
||||
onMetricsDiscovery(metrics: Metric[]): void {
|
||||
this.metricsResponse = metrics.map((metric) => this.renderer.render(metric)).join('\n')
|
||||
this.metricsDiscovered = true
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ describe('Fastify HTTP adapter', () => {
|
|||
|
||||
test('Serves 404 on / when metrics are available', () => {
|
||||
const testServer = createTestServer()
|
||||
testServer.prometheus.updateMetrics([])
|
||||
testServer.prometheus.onMetricsDiscovery([])
|
||||
|
||||
return request(testServer.http)
|
||||
.get('/')
|
||||
|
@ -58,7 +58,7 @@ describe('Fastify HTTP adapter', () => {
|
|||
test('Serves metrics', () => {
|
||||
const testServer = createTestServer()
|
||||
const timestamp = new Date('2020-01-01 00:00:00 UTC')
|
||||
testServer.prometheus.updateMetrics([
|
||||
testServer.prometheus.onMetricsDiscovery([
|
||||
new Metric('metric', 0.1, timestamp, { name: 'metric' }),
|
||||
new Metric('total_something', 100, timestamp, { name: 'counter' }),
|
||||
])
|
||||
|
@ -79,7 +79,7 @@ describe('Fastify HTTP adapter', () => {
|
|||
|
||||
test('Basic auth denied without user', () => {
|
||||
const testServer = createTestServerWithBasicAuth({ joanna: secretAsBcrypt })
|
||||
testServer.prometheus.updateMetrics([])
|
||||
testServer.prometheus.onMetricsDiscovery([])
|
||||
|
||||
return request(testServer.http)
|
||||
.get('/metrics')
|
||||
|
@ -90,7 +90,7 @@ describe('Fastify HTTP adapter', () => {
|
|||
|
||||
test('Basic auth denied with incorrect user', () => {
|
||||
const testServer = createTestServerWithBasicAuth({ joanna: secretAsBcrypt })
|
||||
testServer.prometheus.updateMetrics([])
|
||||
testServer.prometheus.onMetricsDiscovery([])
|
||||
|
||||
return request(testServer.http)
|
||||
.get('/metrics')
|
||||
|
@ -103,7 +103,7 @@ describe('Fastify HTTP adapter', () => {
|
|||
test('Basic auth grants access', () => {
|
||||
const testServer = createTestServerWithBasicAuth({ joanna: secretAsBcrypt })
|
||||
const timestamp = new Date('2020-01-01 00:00:00 UTC')
|
||||
testServer.prometheus.updateMetrics([
|
||||
testServer.prometheus.onMetricsDiscovery([
|
||||
new Metric('metric', 0.1, timestamp, { name: 'metric' }),
|
||||
new Metric('total_something', 100, timestamp, { name: 'counter' }),
|
||||
])
|
||||
|
|
Loading…
Reference in a new issue