Created
November 7, 2023 07:08
-
-
Save anuraaga/1e50f8b2382628287dd486550322393c to your computer and use it in GitHub Desktop.
Exporting prisma metrics with OTel
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const prismaProducer = new PrismaMetricProducer(); | |
export function setPrisma(prisma: PrismaClient) { | |
prismaProducer.client = prisma; | |
} | |
const metricReader = new PeriodicExportingMetricReader({ | |
exportIntervalMillis: 10_000, | |
exporter: metricExporter, | |
metricProducers: [prismaProducer], | |
}) | |
export const otelSdk = new NodeSDK({ | |
instrumentations: [ | |
... | |
new PrismaInstrumentation(), | |
], | |
metricReader, | |
... | |
}); | |
otelSdk.start(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { PrismaClient } from 'generatedprisma'; | |
import { | |
AggregationTemporality, | |
CollectionResult, | |
DataPointType, | |
InstrumentType, | |
MetricCollectOptions, | |
ScopeMetrics, | |
} from '@opentelemetry/sdk-metrics'; | |
import { Resource } from '@opentelemetry/resources'; | |
import { HrTime, ValueType } from '@opentelemetry/api'; | |
import { hrTime } from '@opentelemetry/core'; | |
export class PrismaMetricProducer { | |
client?: PrismaClient; | |
private readonly startTime: HrTime = hrTime(); | |
async collect(options?: MetricCollectOptions): Promise<CollectionResult> { | |
const result: CollectionResult = { | |
resourceMetrics: { | |
resource: Resource.EMPTY, | |
scopeMetrics: [], | |
}, | |
errors: [], | |
}; | |
if (!this.client) { | |
return result; | |
} | |
const endTime = hrTime(); | |
const metrics = await this.client.$metrics.json(); | |
const scopeMetrics: ScopeMetrics = { | |
scope: { | |
name: 'prisma', | |
}, | |
metrics: [], | |
}; | |
for (const counter of metrics.counters) { | |
scopeMetrics.metrics.push({ | |
descriptor: { | |
name: `prisma.${counter.key}`, | |
description: 'Prisma counter', | |
unit: '1', | |
type: InstrumentType.COUNTER, | |
valueType: ValueType.INT, | |
}, | |
dataPointType: DataPointType.SUM, | |
aggregationTemporality: AggregationTemporality.CUMULATIVE, | |
dataPoints: [ | |
{ | |
startTime: this.startTime, | |
endTime: endTime, | |
value: counter.value, | |
attributes: counter.labels, | |
}, | |
], | |
isMonotonic: true, | |
}); | |
} | |
for (const gauge of metrics.gauges) { | |
scopeMetrics.metrics.push({ | |
descriptor: { | |
name: `prisma.${gauge.key}`, | |
description: 'Prisma gauge', | |
unit: '1', | |
type: InstrumentType.UP_DOWN_COUNTER, | |
valueType: ValueType.INT, | |
}, | |
dataPointType: DataPointType.GAUGE, | |
aggregationTemporality: AggregationTemporality.CUMULATIVE, | |
dataPoints: [ | |
{ | |
startTime: this.startTime, | |
endTime: endTime, | |
value: gauge.value, | |
attributes: gauge.labels, | |
}, | |
], | |
}); | |
} | |
for (const histogram of metrics.histograms) { | |
const boundaries = []; | |
const counts = []; | |
for (const [boundary, count] of histogram.value.buckets) { | |
boundaries.push(boundary); | |
counts.push(count); | |
} | |
scopeMetrics.metrics.push({ | |
descriptor: { | |
name: `prisma.${histogram.key}`, | |
description: 'Prisma histogram', | |
unit: 'ms', | |
type: InstrumentType.HISTOGRAM, | |
valueType: ValueType.DOUBLE, | |
}, | |
dataPointType: DataPointType.HISTOGRAM, | |
aggregationTemporality: AggregationTemporality.CUMULATIVE, | |
dataPoints: [ | |
{ | |
startTime: this.startTime, | |
endTime: endTime, | |
value: { | |
buckets: { | |
boundaries, | |
counts, | |
}, | |
count: histogram.value.count, | |
sum: histogram.value.sum, | |
}, | |
attributes: histogram.labels, | |
}, | |
], | |
}); | |
} | |
result.resourceMetrics.scopeMetrics.push(scopeMetrics); | |
return result; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment