Writing Prometheus exporter using Crystal language - Part 2

Nov 3, 2020
3 minutes read.
amber crystal prometheus crometheus

In the last blog post, we discussed instrumenting Amber apps using the Crometheus library. In this blog, we will see how to monitor an external application or a log file.

One main difference here is defining various metric types like Counter, Guage, etc.. are not required. But export the sample values when requested.

I created a demo app using the HTTP server example available on the Crystal language home page. In this blog, we will instrument this web app by collecting a few metrics externally.

# file:
require "http/server"

server = do |context|
  context.response.content_type = "text/plain"
  context.response.print "Hello world, got #{context.request.path}!"

puts "Listening on"

Build and run the application,

$ crystal build
$ ./myapp

Now let’s create an app that collects the CPU, Memory, and uptime details about the app we created initially(or any other app). Create and install the project dependencies using,

$ mkdir myapp_exporter
$ cd myapp_exporter
$ shards init
$ mkdir src
$ touch src/
$ shards install
# file: shard.yml
name: myapp_exporter
version: 0.1.0

    github: darwinnn/crometheus
    branch: master

    main: src/

The below command provides the CPU, memory, and uptime information about the application.

$ ps --no-header -ww -o pcpu,pmem,rsz,vsz,etimes,comm -C myapp
# file: src/
require "crometheus"

class MyappMetrics < Crometheus::Metric
  def self.type

  def samples : Nil
    cmdout = `ps --no-header -ww -o pcpu,pmem,rsz,vsz,etimes,comm -C myapp`
    return if cmdout == ""

    parts = cmdout.split
    pcpu = parts[0].strip.to_f
    pmem = parts[1].strip.to_f
    rsz = parts[2].strip.to_f * 1024
    vsz = parts[3].strip.to_f * 1024
    uptime = parts[4].strip.to_f
    labels = {:server => ""}
    yield, labels: labels, suffix: "cpu_percentage")
    yield, labels: labels, suffix: "memory_percentage")
    yield, labels: labels, suffix: "resident_memory_bytes")
    yield, labels: labels, suffix: "virtual_memory_bytes")
    yield, labels: labels, suffix: "uptime_seconds")
end, "CPU, Memory and Uptime metrics")

Crometheus.default_registry.path = "/metrics"

Build and run,

$ shards build
$ ./bin/myapp_exporter

Now browse http://localhost:5000/metrics to see the metrics related to myapp

# HELP myapp CPU, Memory and Uptime metrics
# TYPE myapp gauge
myapp_cpu_percentage{server=""} 0.0
myapp_memory_percentage{server=""} 0.3
myapp_resident_memory_bytes{server=""} 6664192.0
myapp_virtual_memory_bytes{server=""} 48365568.0
myapp_uptime_seconds{server=""} 1656.0

Add multiple classes to collect more meaningful data. For example, connect to the database and query the table to see the number of users or any other entities.

About Aravinda Vishwanathapura

Co-Founder & CTO at Kadalu Technologies, Creator of Sanka, Creator of Chitra, GlusterFS core team member, Maintainer of Kadalu Storage
Contact: Linkedin | Twitter | Facebook | Github |