Effect CommunityEC
Effect Community14mo ago
12 replies
EnderSpirit

Exporting Metrics to Prometheus in Effect with OpenTelemetry

Hello, I'm still kind of an Effect noob and I'm trying to export my metrics to Prometheus by exposing an endpoint on localhost:9464/metrics, I managed to increment my metric but I don't understand how to expose this route.

I searched in the effect.website documentation but there was nothing about exporting metrics (but there was a nice tutorial for Tracing).
I especially searched on this page: https://effect.website/docs/observability/metrics/
I created a NodeSdk Layer which seems to accept a MetricReader, I passed a PrometheusExporter but of course it doesn't actually start the HTTP server, which is what I want.

I really feel like this use-case should be documented, the documentation currently talks about how to define Metrics but never about exporting them which is equally important to do anything useful.
It is very likely a skill issue coming from my side, but as a beginner I am completely unable to understand how Metrics should actually be exported in a real-world Effect application. :/

Here is my attempt:
import { Effect, Metric } from "effect"
import { NodeSdk } from "@effect/opentelemetry"
import { PrometheusExporter } from "@opentelemetry/exporter-prometheus"
import { NodeRuntime } from "@effect/platform-node"
import express from 'express'

const NodeSdkLive = NodeSdk.layer(() => ({
  resource: { serviceName: "example" },
  metricReader: new PrometheusExporter({
    port: 9464,
    endpoint: '/metrics',
  }),
}))

const requestCount = Metric.counter("request_count", {
  incremental: true,
})

const incrementCounter = Effect.gen(function* () {
  // Increment the counter by 1
  yield* requestCount(Effect.succeed(1))
  const state = yield* Metric.value(requestCount)
  console.log(state.count)
  return state.count
})

const mainProgram = Effect.sync(() => {
  const app = express()
  const port = 3000

  app.get('/', (req, res) => {
    const counterResult = Effect.runSync(incrementCounter)
    res.send('Hello World!' + counterResult) // <-- this works
  })

  app.listen(port, () => {
    console.log(`Example app listening on port ${port}`)
  })
})

const instrumented = mainProgram.pipe(Effect.provide(NodeSdkLive))

NodeRuntime.runMain(instrumented)
Was this page helpful?