### Example Usage of Type-Safe HTTP Metrics Source: https://context7.com/davenverse/epimetheus/llms.txt Demonstrates the usage of the type-safe HttpMetrics algebra by recording requests and latencies for GET and POST methods. This example shows how to instantiate and use the metrics. ```scala import io.chrisdavenport.epimetheus._ import cats.effect._ import cats.effect.unsafe.implicits.global // Define a sealed trait for type-safe labels sealed trait HttpMethod case object GET extends HttpMethod case object POST extends HttpMethod case object PUT extends HttpMethod case object DELETE extends HttpMethod // Label transformation function def methodToLabel(m: HttpMethod): Sized[IndexedSeq[String], _1] = m match { case GET => Sized("GET") case POST => Sized("POST") case PUT => Sized("PUT") case DELETE => Sized("DELETE") } // Define an algebra for HTTP metrics trait HttpMetrics[F[_]] { def recordRequest(method: HttpMethod): F[Unit] def recordLatency(method: HttpMethod, seconds: Double): F[Unit] } object HttpMetrics { def apply[F[_]: Sync](pr: PrometheusRegistry[F]): F[HttpMetrics[F]] = for { requestCounter <- Counter.labelled( pr, Name("http_requests"), "HTTP requests", Sized(Label("method")), methodToLabel ) latencyHistogram <- Histogram.labelled( pr, Name("http_request_duration_seconds"), "HTTP latency", Sized(Label("method")), methodToLabel ) } yield new HttpMetrics[F] { def recordRequest(method: HttpMethod): F[Unit] = requestCounter.label(method).inc def recordLatency(method: HttpMethod, seconds: Double): F[Unit] = latencyHistogram.label(method).observe(seconds) } } // Usage val httpMetricsExample = { for { pr <- PrometheusRegistry.build[IO] metrics <- HttpMetrics[IO](pr) _ <- metrics.recordRequest(GET) _ <- metrics.recordRequest(GET) _ <- metrics.recordRequest(POST) _ <- metrics.recordLatency(GET, 0.05) _ <- metrics.recordLatency(POST, 0.12) output <- pr.write004 } yield output }.unsafeRunSync() ``` -------------------------------- ### Demonstrate compilation failure Source: https://github.com/davenverse/epimetheus/blob/main/docs/docs/01-Introduction.md Example of code that is expected to fail compilation. ```scala woozle(nel) // doesn't compile ``` -------------------------------- ### Create a Summary with labels Source: https://github.com/davenverse/epimetheus/blob/main/docs/docs/08-Summary.md Example of initializing a Summary metric with labels and observing values for specific label sets. ```scala val withLabelsSummaryExample = { for { pr <- PrometheusRegistry.build[IO] s <- Summary.labelled( pr, Name("example_summary"), "Example Summary", Sized(Label("foo")), {s: String => Sized(s)}, Summary.quantile(0.5,0.05) ) _ <- s.label("bar").observe(0.1) _ <- s.label("baz").observe(0.2) _ <- s.label("baz").observe(1.0) currentMetrics <- pr.write004 _ <- IO(println(currentMetrics)) } yield () } withLabelsSummaryExample.unsafeRunSync() ``` -------------------------------- ### Create a Summary Metric Source: https://github.com/davenverse/epimetheus/blob/main/docs/index.md Example of creating and observing values in a summary without labels. ```scala val noLabelsSummaryExample = { for { pr <- PrometheusRegistry.build[IO] s <- Summary.noLabels(pr, Name("example_summary"), "Example Summary", Summary.quantile(0.5,0.05)) _ <- s.observe(0.1) _ <- s.observe(0.2) _ <- s.observe(1.0) currentMetrics <- pr.write004 } yield currentMetrics } noLabelsSummaryExample.unsafeRunSync() ``` -------------------------------- ### Create a Counter with labels Source: https://github.com/davenverse/epimetheus/blob/main/docs/docs/05-Counter.md Example of creating and using a `Counter` metric with labels. Labels allow for categorizing the metric, and values are incremented for specific label combinations. ```scala val labelledExample = { for { pr <- PrometheusRegistry.build[IO] counter <- Counter.labelled( pr, Name("example"), "Example Counter", Sized(Label("foo")), {s: String => Sized(s)} ) _ <- counter.label("bar").inc _ <- counter.label("baz").inc out <- pr.write004 } yield out } labelledExample.unsafeRunSync() ``` -------------------------------- ### Define data structures Source: https://github.com/davenverse/epimetheus/blob/main/docs/docs/01-Introduction.md Example of defining a case class and a NonEmptyList for use in examples. ```scala case class Person(name: String, age: Int) val nel = NonEmptyList.of(Person("Bob", 12), Person("Alice", 14)) ``` -------------------------------- ### Create a Summary without labels Source: https://github.com/davenverse/epimetheus/blob/main/docs/docs/08-Summary.md Example of initializing a Summary metric without labels and observing values. ```scala val noLabelsSummaryExample = { for { pr <- PrometheusRegistry.build[IO] s <- Summary.noLabels( pr, Name("example_summary"), "Example Summary", Summary.quantile(0.5,0.05) ) _ <- s.observe(0.1) _ <- s.observe(0.2) _ <- s.observe(1.0) currentMetrics <- pr.write004 _ <- IO(println(currentMetrics)) } yield () } noLabelsSummaryExample.unsafeRunSync() ``` -------------------------------- ### Create a Counter Metric Source: https://github.com/davenverse/epimetheus/blob/main/docs/index.md Example of creating and incrementing a counter without labels. ```scala val noLabelsCounterExample = { for { pr <- PrometheusRegistry.build[IO] counter <- Counter.noLabels(pr, Name("counter"), "Example Counter") _ <- counter.inc currentMetrics <- pr.write004 } yield currentMetrics } noLabelsCounterExample.unsafeRunSync() ``` -------------------------------- ### Create a Histogram Metric Source: https://github.com/davenverse/epimetheus/blob/main/docs/index.md Example of creating and observing values in a histogram without labels. ```scala val noLabelsHistogramExample = { for { pr <- PrometheusRegistry.build[IO] h <- Histogram.noLabels(pr, Name("example_histogram"), "Example Histogram") _ <- h.observe(0.2) _ <- h.timed(Temporal[IO].sleep(1.second), SECONDS) currentMetrics <- pr.write004 } yield currentMetrics } noLabelsHistogramExample.unsafeRunSync() ``` -------------------------------- ### Histogram with Linear Buckets Source: https://context7.com/davenverse/epimetheus/llms.txt Creates a histogram using linear buckets defined by a start value, width, and count. Useful for metrics with a consistent interval. ```scala // Histogram with linear buckets (start, width, count) val histogramLinear = { for { pr <- PrometheusRegistry.build[IO] histogram <- Histogram.noLabelsLinearBuckets( pr, Name("response_time"), "Response times", 0.1, 0.1, 10 // Buckets: 0.1, 0.2, 0.3, ..., 1.0 ) _ <- histogram.observe(0.25) output <- pr.write004 } yield output }.unsafeRunSync() ``` -------------------------------- ### Create a Counter without labels Source: https://github.com/davenverse/epimetheus/blob/main/docs/docs/05-Counter.md Example of creating and using a `Counter` metric that does not have labels. It increments on success or failure of an action. ```scala val noLabelsExample = { for { pr <- PrometheusRegistry.build[IO] successCounter <- Counter.noLabels( pr, Name("example_success"), "Example Counter of Success" ) failureCounter <- Counter.noLabels( pr, Name("example_failure"), "Example Counter of Failure" ) _ <- IO(println("Action Here")).guaranteeCase{ case Outcome.Succeeded(_) => successCounter.inc case _ => failureCounter.inc } out <- pr.write004 } yield out } noLabelsExample.unsafeRunSync() ``` -------------------------------- ### Histogram with Exponential Buckets Source: https://context7.com/davenverse/epimetheus/llms.txt Creates a histogram using exponential buckets defined by a start value, a multiplication factor, and a count. Ideal for metrics spanning several orders of magnitude. ```scala // Histogram with exponential buckets (start, factor, count) val histogramExponential = { for { pr <- PrometheusRegistry.build[IO] histogram <- Histogram.noLabelsExponentialBuckets( pr, Name("request_size"), "Request body sizes", 100, 2, 8 // Buckets: 100, 200, 400, 800, 1600, 3200, 6400, 12800 ) _ <- histogram.observe(350) output <- pr.write004 } yield output }.unsafeRunSync() ``` -------------------------------- ### Create Summary With Labels Source: https://context7.com/davenverse/epimetheus/llms.txt Use Summary.labelled to create a summary metric that includes labels. This is useful for categorizing observations based on different dimensions, such as 'table' in this database query duration example. ```scala // Summary with labels val summaryWithLabels = { for { pr <- PrometheusRegistry.build[IO] summary <- Summary.labelled( pr, Name("db_query_duration_seconds"), "Database query duration by table", Sized(Label("table")), { s: String => Sized(s) }, Summary.quantile(0.5, 0.05), Summary.quantile(0.99, 0.001) ) _ <- summary.label("users").observe(0.01) _ <- summary.label("orders").observe(0.05) _ <- summary.label("users").observe(0.02) output <- pr.write004 } yield output }.unsafeRunSync() ``` -------------------------------- ### Building a registry with default metrics Source: https://github.com/davenverse/epimetheus/blob/main/docs/docs/04-CollectorRegistry.md Creates a registry pre-populated with default Hotspot metrics. ```scala { for { pr <- PrometheusRegistry.buildWithDefaults[IO] } yield pr } ``` -------------------------------- ### Creating a Histogram with labels Source: https://github.com/davenverse/epimetheus/blob/main/docs/docs/07-Histogram.md Demonstrates initializing a histogram with dynamic labels and observing values for specific label instances. ```scala val labelledHistogramExample = { for { pr <- PrometheusRegistry.build[IO] h <- Histogram.labelled( pr, Name("example_histogram"), "Example Histogram", Sized(Label("foo")), {s: String => Sized(s)} ) _ <- h.label("bar").observe(0.2) _ <- h.label("baz").timed(Temporal[IO].sleep(1.second), SECONDS) currentMetrics <- pr.write004 _ <- IO(println(currentMetrics)) } yield () } labelledHistogramExample.unsafeRunSync() ``` -------------------------------- ### Interact with data in REPL Source: https://github.com/davenverse/epimetheus/blob/main/docs/docs/01-Introduction.md Demonstrates basic operations on a NonEmptyList. ```scala nel.head nel.tail ``` -------------------------------- ### Creating a Histogram without labels Source: https://github.com/davenverse/epimetheus/blob/main/docs/docs/07-Histogram.md Demonstrates initializing a basic histogram and observing values, including timing an effect. ```scala val noLabelsHistogramExample = { for { pr <- PrometheusRegistry.build[IO] h <- Histogram.noLabels(pr, Name("example_histogram"), "Example Histogram") _ <- h.observe(0.2) _ <- h.timed(Temporal[IO].sleep(1.second), SECONDS) currentMetrics <- pr.write004 _ <- IO(println(currentMetrics)) } yield () } noLabelsHistogramExample.unsafeRunSync() ``` -------------------------------- ### Create Counters With Labels Source: https://context7.com/davenverse/epimetheus/llms.txt Demonstrates creating `Counter` metrics with labels, ensuring compile-time safety using Shapeless's `Sized`. Requires `cats.effect` and `io.chrisdavenport.epimetheus` imports. ```scala import io.chrisdavenport.epimetheus._ import cats.effect._ import cats.effect.unsafe.implicits.global // Counter with labels - compile-time safety via Sized val counterWithLabels = { for { pr <- PrometheusRegistry.build[IO] counter <- Counter.labelled( pr, Name("http_requests"), "HTTP requests by method and status", Sized(Label("method"), Label("status")), { case (method: String, status: String) => Sized(method, status) } ) _ <- counter.label(("GET", "200")).inc _ <- counter.label(("GET", "200")).inc _ <- counter.label(("POST", "201")).inc _ <- counter.label(("GET", "404")).inc output <- pr.write004 } yield output }.unsafeRunSync() // Output: // # HELP http_requests_total HTTP requests by method and status // # TYPE http_requests_total counter // http_requests_total{method="GET",status="200"} 2.0 // http_requests_total{method="POST",status="201"} 1.0 // http_requests_total{method="GET",status="404"} 1.0 ``` -------------------------------- ### Programmatic Quantile Construction Source: https://context7.com/davenverse/epimetheus/llms.txt Construct Summary.Quantile instances programmatically for dynamic quantile values. Use 'impl' for Either-based error handling or 'implF' for effectful computation. ```scala // Programmatic quantile construction (for dynamic values) val dynamicQuantile = Summary.Quantile.impl(0.75, 0.02) // Returns Either[IllegalArgumentException, Quantile] val quantileF = Summary.Quantile.implF[IO](0.75, 0.02) // Returns F[Quantile] ``` -------------------------------- ### Create and use a labelled Gauge Source: https://github.com/davenverse/epimetheus/blob/main/docs/docs/06-Gauge.md Demonstrates initializing a Gauge with labels and updating specific label values. ```scala val labelledGaugeExample = { for { pr <- PrometheusRegistry.build[IO] gauge <- Gauge.labelled( pr, Name("gaugetotal"), "Example Gauge", Sized(Label("foo")), {s: String => Sized(s)} ) _ <- gauge.label("bar").inc _ <- gauge.label("baz").inc _ <- gauge.label("bar").inc _ <- gauge.label("baz").inc _ <- gauge.label("bar").dec currentMetrics <- pr.write004 } yield currentMetrics } labelledGaugeExample.unsafeRunSync() ``` -------------------------------- ### Configure build.sbt dependencies Source: https://github.com/davenverse/epimetheus/blob/main/docs/docs/01-Introduction.md Add the Epimetheus library and necessary compiler flags to your Scala project. ```scala scalaVersion := "{{site.scalaVersion}}" // Scala {{site.scalaVersions}} scalacOptions += "-Ypartial-unification" // 2.11.9+ lazy val epimetheusV = "{{site.epimetheusVersion}}" libraryDependencies ++= Seq( "io.chrisdavenport" %% "epimetheus" % epimetheusV ) ``` -------------------------------- ### Building a custom registry Source: https://github.com/davenverse/epimetheus/blob/main/docs/docs/04-CollectorRegistry.md Instantiates a new PrometheusRegistry for managing application-specific metrics. ```scala { for { pr <- PrometheusRegistry.build[IO] } yield pr } ``` -------------------------------- ### Import Epimetheus modules Source: https://github.com/davenverse/epimetheus/blob/main/docs/docs/01-Introduction.md Standard imports used throughout the documentation. ```scala import cats._, cats.data._ import io.chrisdavenport.epimetheus._ ``` -------------------------------- ### Create Summary Without Labels Source: https://context7.com/davenverse/epimetheus/llms.txt Use Summary.noLabels to create a summary metric without labels. Configure quantiles for desired percentiles and error margins. Observe values to record observations. ```scala import io.chrisdavenport.epimetheus._ import cats.effect._ import cats.effect.unsafe.implicits.global // Summary without labels val summaryNoLabels = { for { pr <- PrometheusRegistry.build[IO] summary <- Summary.noLabels( pr, Name("request_latency_seconds"), "Request latency distribution", Summary.quantile(0.5, 0.05), // 50th percentile (median) with 5% error Summary.quantile(0.9, 0.01), // 90th percentile with 1% error Summary.quantile(0.99, 0.001) // 99th percentile with 0.1% error ) _ <- summary.observe(0.1) _ <- summary.observe(0.2) _ <- summary.observe(0.15) _ <- summary.observe(0.5) _ <- summary.observe(1.2) output <- pr.write004 } yield output }.unsafeRunSync() ``` -------------------------------- ### Build and Manage Prometheus Registries Source: https://context7.com/davenverse/epimetheus/llms.txt Demonstrates creating empty, default, and custom Prometheus registries. Includes exporting metrics in Prometheus 0.0.4 and OpenMetrics 1.0.0 formats. Requires `cats.effect` and `io.chrisdavenport.epimetheus` imports. ```scala import io.chrisdavenport.epimetheus._ import cats.effect._ import cats.effect.unsafe.implicits.global // Build a new empty registry val customRegistry = PrometheusRegistry.build[IO].unsafeRunSync() ``` ```scala // Build a registry with JVM default metrics (memory, GC, threads, etc.) val registryWithDefaults = PrometheusRegistry.buildWithDefaults[IO].unsafeRunSync() ``` ```scala // Or manually register JVM defaults val manualDefaults = { for { pr <- PrometheusRegistry.build[IO] _ <- Collector.Defaults.registerDefaults(pr) } yield pr }.unsafeRunSync() ``` ```scala // Access the global default registry (for Java interop) val globalRegistry = PrometheusRegistry.defaultRegistry[IO] ``` ```scala // Export metrics in Prometheus 0.0.4 format val metricsOutput = { for { pr <- PrometheusRegistry.buildWithDefaults[IO] output <- pr.write004 } yield output }.unsafeRunSync() // Output: # HELP jvm_memory_used_bytes Used bytes of a given JVM memory area... ``` ```scala // Export in OpenMetrics 1.0.0 format val openMetricsOutput = { for { pr <- PrometheusRegistry.buildWithDefaults[IO] output <- pr.writeOpenMetrics100 } yield output }.unsafeRunSync() ``` -------------------------------- ### Import Epimetheus dependencies Source: https://github.com/davenverse/epimetheus/blob/main/docs/docs/06-Gauge.md Required imports for working with Epimetheus metrics and Cats Effect. ```scala import io.chrisdavenport.epimetheus._ import cats.effect._ import cats.effect.unsafe.implicits.global ``` -------------------------------- ### Histogram without Labels (Default Buckets) Source: https://context7.com/davenverse/epimetheus/llms.txt Creates a histogram with default buckets optimized for web/RPC requests. Observes several values and writes the Prometheus output. ```scala import io.chrisdavenport.epimetheus._ import io.chrisdavenport.epimetheus.implicits._ import cats.effect._ import scala.concurrent.duration._ import cats.effect.unsafe.implicits.global // Histogram without labels (default buckets) val histogramNoLabels = { for { pr <- PrometheusRegistry.build[IO] histogram <- Histogram.noLabels(pr, Name("http_request_duration_seconds"), "HTTP request latency") _ <- histogram.observe(0.05) // Observe a value _ <- histogram.observe(0.12) _ <- histogram.observe(0.89) _ <- histogram.observe(2.1) output <- pr.write004 } yield output }.unsafeRunSync() // Output includes _bucket, _sum, and _count metrics ``` -------------------------------- ### Importing Epimetheus dependencies Source: https://github.com/davenverse/epimetheus/blob/main/docs/docs/07-Histogram.md Required imports for working with Epimetheus metrics and Cats Effect. ```scala import io.chrisdavenport.epimetheus._ import io.chrisdavenport.epimetheus.implicits._ import cats.effect._ import scala.concurrent.duration._ import cats.effect.unsafe.implicits.global ``` -------------------------------- ### Counter with algebraic data types Source: https://github.com/davenverse/epimetheus/blob/main/docs/docs/05-Counter.md Demonstrates using a `Counter` with labels that are derived from an algebraic data type. This allows for type-safe labeling of metrics. ```scala sealed trait Foo case object Bar extends Foo case object Baz extends Foo def fooLabel(f: Foo) = { f match { case Bar => Sized("bar") case Baz => Sized("baz") } } trait FooAlg[F[_]]{ def bar: F[Unit] def baz: F[Unit] } object FooAlg { def impl[F[_]](c: Counter.UnlabelledCounter[F, Foo]) = new FooAlg[F]{ def bar: F[Unit] = c.label(Bar).inc def baz: F[Unit] = c.label(Baz).inc } } val fooAgebraExample = { for { pr <- PrometheusRegistry.build[IO] counter <- Counter.labelled( pr, Name("example"), "Example Counter", Sized(Label("foo")), fooLabel ) foo = FooAlg.impl(counter) _ <- foo.bar _ <- foo.bar _ <- foo.baz out <- pr.write004 } yield out } fooAgebraExample.unsafeRunSync() ``` -------------------------------- ### Configure Summary with Custom Time Window Source: https://context7.com/davenverse/epimetheus/llms.txt Use Summary.noLabelsQuantiles to create a summary with a custom time window and age buckets. This allows for more granular control over how observations are aggregated over time. ```scala // Summary with custom time window configuration val summaryCustomWindow = { for { pr <- PrometheusRegistry.build[IO] summary <- Summary.noLabelsQuantiles( pr, Name("api_response_time"), "API response time", 300L, // maxAgeSeconds: 5 minutes 3, // ageBuckets: 3 buckets (switched every ~100 seconds) Summary.quantile(0.5, 0.05), Summary.quantile(0.95, 0.01) ) _ <- summary.observe(0.05) output <- pr.write004 } yield output }.unsafeRunSync() ``` -------------------------------- ### Create and use an unlabelled Gauge Source: https://github.com/davenverse/epimetheus/blob/main/docs/docs/06-Gauge.md Demonstrates initializing a Gauge without labels and performing increment and decrement operations. ```scala val noLabelsGaugeExample = { for { pr <- PrometheusRegistry.build[IO] gauge <- Gauge.noLabels(pr, Name("gaugetotal"), "Example Gauge") _ <- gauge.inc _ <- gauge.inc _ <- gauge.dec currentMetrics <- pr.write004 } yield currentMetrics } noLabelsGaugeExample.unsafeRunSync() ``` -------------------------------- ### Bracket-Style Gauge for In-Flight Operations Source: https://context7.com/davenverse/epimetheus/llms.txt Illustrates using a Gauge in a bracket-style pattern to automatically increment before an operation and decrement after, ensuring accurate tracking of concurrent tasks even if errors occur. ```scala import io.chrisdavenport.epimetheus._ import cats.effect._ import cats.effect.unsafe.implicits.global // Bracket-style gauge for tracking in-flight operations val bracketGauge = { for { pr <- PrometheusRegistry.build[IO] inFlight <- Gauge.noLabels(pr, Name("requests_in_flight"), "Current requests being processed") result <- Gauge.incIn(inFlight, IO.sleep(100.millis) *> IO.pure("done")) output <- pr.write004 } yield (result, output) }.unsafeRunSync() // Gauge increments before operation, decrements after (even on error) ``` -------------------------------- ### Histogram with Custom Buckets Source: https://context7.com/davenverse/epimetheus/llms.txt Creates a histogram with custom-defined buckets for specific value ranges, suitable for tracking metrics like file sizes. ```scala // Histogram with custom buckets val histogramCustomBuckets = { for { pr <- PrometheusRegistry.build[IO] histogram <- Histogram.noLabelsBuckets( pr, Name("file_size_bytes"), "Uploaded file sizes", 1024, 10240, 102400, 1048576, 10485760 // 1KB, 10KB, 100KB, 1MB, 10MB ) _ <- histogram.observe(512) _ <- histogram.observe(5000) _ <- histogram.observe(500000) output <- pr.write004 } yield output }.unsafeRunSync() ``` -------------------------------- ### Accessing the global registry Source: https://github.com/davenverse/epimetheus/blob/main/docs/docs/04-CollectorRegistry.md Retrieves the singleton default registry for interoperability with Java libraries. ```scala PrometheusRegistry.defaultRegistry[IO] ``` -------------------------------- ### Create Counters Without Labels Source: https://context7.com/davenverse/epimetheus/llms.txt Illustrates creating and incrementing `Counter` metrics without labels. The `_total` suffix is automatically appended. Requires `cats.effect` and `io.chrisdavenport.epimetheus` imports. ```scala import io.chrisdavenport.epimetheus._ import cats.effect._ import cats.effect.unsafe.implicits.global // Counter without labels val counterNoLabels = { for { pr <- PrometheusRegistry.build[IO] successCounter <- Counter.noLabels(pr, Name("http_requests_success"), "Total successful HTTP requests") failureCounter <- Counter.noLabels(pr, Name("http_requests_failure"), "Total failed HTTP requests") _ <- successCounter.inc // Increment by 1 _ <- successCounter.incBy(5.0) // Increment by specific amount _ <- failureCounter.inc output <- pr.write004 } yield output }.unsafeRunSync() // Output: // # HELP http_requests_success_total Total successful HTTP requests // # TYPE http_requests_success_total counter // http_requests_success_total 6.0 // # HELP http_requests_failure_total Total failed HTTP requests // # TYPE http_requests_failure_total counter // http_requests_failure_total 1.0 ``` -------------------------------- ### Create and Use Gauge Without Labels Source: https://context7.com/davenverse/epimetheus/llms.txt Demonstrates creating a Gauge metric without labels and performing operations like incrementing, decrementing, and setting its value. Requires PrometheusRegistry and Gauge imports. ```scala import io.chrisdavenport.epimetheus._ import cats.effect._ import cats.effect.unsafe.implicits.global // Gauge without labels val gaugeNoLabels = { for { pr <- PrometheusRegistry.build[IO] gauge <- Gauge.noLabels(pr, Name("active_connections"), "Number of active connections") _ <- gauge.inc // Increment by 1 _ <- gauge.inc _ <- gauge.incBy(3.0) // Increment by specific amount _ <- gauge.dec // Decrement by 1 _ <- gauge.decBy(2.0) // Decrement by specific amount _ <- gauge.set(10.0) // Set to specific value output <- pr.write004 } yield output }.unsafeRunSync() // Output: // # HELP active_connections Number of active connections // # TYPE active_connections gauge // active_connections 10.0 ``` -------------------------------- ### Register All JVM Default Metrics Source: https://context7.com/davenverse/epimetheus/llms.txt Registers all default JVM metrics collectors, including memory, garbage collection, threads, and process metrics, with a Prometheus registry. Ensure PrometheusRegistry is built before calling. ```scala import io.chrisdavenport.epimetheus._ import cats.effect._ import cats.effect.unsafe.implicits.global // Register all JVM defaults val allDefaults = { for { pr <- PrometheusRegistry.build[IO] _ <- Collector.Defaults.registerDefaults(pr) output <- pr.write004 } yield output }.unsafeRunSync() // Includes: jvm_memory_*, jvm_gc_*, jvm_threads_*, process_*, etc. ``` -------------------------------- ### Registering default metrics manually Source: https://github.com/davenverse/epimetheus/blob/main/docs/docs/04-CollectorRegistry.md Manually registers default collectors into a custom-built registry. ```scala { for { pr <- PrometheusRegistry.build[IO] _ <- Collector.Defaults.registerDefaults(pr) } yield pr } ``` -------------------------------- ### Create Type-Safe HTTP Metrics Algebra Source: https://context7.com/davenverse/epimetheus/llms.txt Defines an algebra for HTTP metrics, including request counters and latency histograms, using type-safe labels for HTTP methods. This ensures correct label application at compile time. ```scala import io.chrisdavenport.epimetheus._ import cats.effect._ import cats.effect.unsafe.implicits.global // Define a sealed trait for type-safe labels sealed trait HttpMethod case object GET extends HttpMethod case object POST extends HttpMethod case object PUT extends HttpMethod case object DELETE extends HttpMethod // Label transformation function def methodToLabel(m: HttpMethod): Sized[IndexedSeq[String], _1] = m match { case GET => Sized("GET") case POST => Sized("POST") case PUT => Sized("PUT") case DELETE => Sized("DELETE") } // Define an algebra for HTTP metrics trait HttpMetrics[F[_]] { def recordRequest(method: HttpMethod): F[Unit] def recordLatency(method: HttpMethod, seconds: Double): F[Unit] } object HttpMetrics { def apply[F[_]: Sync](pr: PrometheusRegistry[F]): F[HttpMetrics[F]] = for { requestCounter <- Counter.labelled( pr, Name("http_requests"), "HTTP requests", Sized(Label("method")), methodToLabel ) latencyHistogram <- Histogram.labelled( pr, Name("http_request_duration_seconds"), "HTTP latency", Sized(Label("method")), methodToLabel ) } yield new HttpMetrics[F] { def recordRequest(method: HttpMethod): F[Unit] = requestCounter.label(method).inc def recordLatency(method: HttpMethod, seconds: Double): F[Unit] = latencyHistogram.label(method).observe(seconds) } } ``` -------------------------------- ### Runtime Name and Label Validation Source: https://context7.com/davenverse/epimetheus/llms.txt Construct Name and Label instances dynamically using 'impl' for runtime validation. This returns an Either, allowing for error handling if the provided string does not conform to Prometheus naming rules. ```scala // Runtime construction for dynamic values val dynamicName = Name.impl("my_metric") // Returns Either[IllegalArgumentException, Name] val dynamicLabel = Label.impl("my_label") // Returns Either[IllegalArgumentException, Label] // Example with dynamic name validation val result = Name.impl("valid_metric_name") match { case Right(name) => s"Valid name: ${name.getName}" case Left(err) => s"Invalid: ${err.getMessage}" } ``` -------------------------------- ### Automatic Timing with timed() Source: https://context7.com/davenverse/epimetheus/llms.txt Uses the `timed()` method to automatically record the duration of an IO operation. The duration is recorded in seconds by default. ```scala // Automatic timing with timed() val timedHistogram = { for { pr <- PrometheusRegistry.build[IO] histogram <- Histogram.noLabels(pr, Name("operation_duration_seconds"), "Operation timing") result <- histogram.timed(IO.sleep(100.millis) *> IO.pure("completed"), SECONDS) output <- pr.write004 } yield (result, output) }.unsafeRunSync() // Automatically records the duration of the IO operation ``` -------------------------------- ### Histogram with Labels Source: https://context7.com/davenverse/epimetheus/llms.txt Creates a labeled histogram, allowing observations to be categorized by specific labels like 'endpoint'. Requires defining labels and a function to map values to label sets. ```scala // Histogram with labels val histogramWithLabels = { for { pr <- PrometheusRegistry.build[IO] histogram <- Histogram.labelled( pr, Name("http_request_duration_seconds"), "HTTP request latency by endpoint", Sized(Label("endpoint")), { s: String => Sized(s) } ) _ <- histogram.label("/api/users").observe(0.05) _ <- histogram.label("/api/orders").observe(0.15) _ <- histogram.label("/api/users").observe(0.08) output <- pr.write004 } yield output }.unsafeRunSync() ``` -------------------------------- ### Add Epimetheus Dependency to build.sbt Source: https://github.com/davenverse/epimetheus/blob/main/README.md Include this dependency in your build.sbt file to use Epimetheus in your Scala project. Replace '' with the desired Epimetheus version. ```scala libraryDependencies ++= Seq( "io.chrisdavenport" %% "epimetheus" % "" ) ``` -------------------------------- ### Register Specific JVM Metrics Source: https://context7.com/davenverse/epimetheus/llms.txt Registers specific JVM metrics collectors individually, such as memory, garbage collection, threads, process, and runtime info. This allows for a more granular selection of metrics. ```scala import io.chrisdavenport.epimetheus._ import cats.effect._ import cats.effect.unsafe.implicits.global // Or register specific JVM metrics val specificMetrics = { for { pr <- PrometheusRegistry.build[IO] _ <- Collector.Defaults.registerJvmMemoryMetrics(pr) _ <- Collector.Defaults.registerJvmGarbageCollectorMetrics(pr) _ <- Collector.Defaults.registerJvmThreadsMetrics(pr) _ <- Collector.Defaults.registerProcessMetrics(pr) _ <- Collector.Defaults.registerJvmRuntimeInfoMetric(pr) output <- pr.write004 } yield output }.unsafeRunSync() ``` -------------------------------- ### Define Type-Safe HTTP Method Labels Source: https://context7.com/davenverse/epimetheus/llms.txt Defines a sealed trait for HTTP methods and a transformation function to create type-safe labels for metrics. This ensures compile-time safety for label values. ```scala import io.chrisdavenport.epimetheus._ import cats.effect._ import cats.effect.unsafe.implicits.global // Define a sealed trait for type-safe labels sealed trait HttpMethod case object GET extends HttpMethod case object POST extends HttpMethod case object PUT extends HttpMethod case object DELETE extends HttpMethod // Label transformation function def methodToLabel(m: HttpMethod): Sized[IndexedSeq[String], _1] = m match { case GET => Sized("GET") case POST => Sized("POST") case PUT => Sized("PUT") case DELETE => Sized("DELETE") } ``` -------------------------------- ### Compile-Time Name and Label Validation Source: https://context7.com/davenverse/epimetheus/llms.txt Use Name and Label with literal strings for compile-time validation of Prometheus metric identifiers. This ensures adherence to naming conventions before runtime. ```scala import io.chrisdavenport.epimetheus._ // Macro-based compile-time validation (literals only) val validName = Name("http_requests_total") // Compiles successfully val validLabel = Label("method") // Compiles successfully // These would fail at compile time: // val invalidName = Name("123invalid") // Compile error: starts with number // val invalidLabel = Label("invalid-label") // Compile error: contains hyphen ``` -------------------------------- ### Incorrectly sized labels for Counter Source: https://github.com/davenverse/epimetheus/blob/main/docs/docs/05-Counter.md This code snippet demonstrates a compile-time error that occurs when the size of the labels provided does not match the expected size, enforcing type safety. ```scala def incorrectlySized[F[_]: Sync](pr: PrometheusRegistry[F]) = { Counter.labelled(pr, Name("fail"), "Example Failure", Sized(Label("color"), Name("method")), {s: String => Sized(s)}) } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.