Giter VIP home page Giter VIP logo

alchemetrics's Introduction

Alchemetrics

Alchemetrics

Metrics collection and reporting for Elixir applications.

Travis Coverage Status Hex

About

Alchemetrics makes life easier for anyone who wants to report and distribute metrics from an Elixir application. The metrics can help you to measure performance, detect errors or track information about your application.

Alchemetrics makes use of GenStage to ensure that collecting and submitting metrics will not impact application performance.

Each metric report creates a new event that follows the GenStage flow. With the help of the ConsumerSupervisor, your metrics are distributed with little impact to the application performance.

Documentation is available at HexDocs

Installation

Alchemetrics is available on Hex. All you have to do is to add it to mix.exs as a test dependency.

def deps do
  [{:alchemetrics, "~> 0.5.2"}]
end

Reports

Reports are made via calls to Alchemetrics functions. It is through reports that Alchemetrics stores a value to be measured and sent to the backends. Further details about reports can be found in the documentation available in HexDocs.

Backends

Collected metrics are typically stored in some type of datastore, such as Logstash and Influxdb. Alchemetrics uses the concept of backends to distribute the metrics to these data stores. More details can be found in the documentation about custom backends.

When a dataset is created, it subscribes to all backends enabled on the application. Datasets created before a backend is enabled will not subscribe to the new backend. Also, when a backend is disabled, all datasets will unsubscribe from it.

ConsoleBackend

Alchemetrics comes with a built-in backend called Alchemetrics.ConsoleBackend. This backend sends yor metrics to the console and is very useful when debugging.

You can enable Alchemetrics.ConsoleBackend when your application boot by adding it to yor backend list:

# config/config.exs

config :alchemetrics,
  backends: [
    {Alchemetrics.ConsoleBackend, []}
  ]

You can also enable it on the console:

# iex -S mix

iex(1)> Alchemetrics.ConsoleBackend.enable
Starting Elixir.Alchemetrics.ConsoleBackend with following options: []
:ok
iex(2)> Alchemetrics.report(100, :test)
:ok
iex(3)> %{datapoint: :avg, name: :test, options: [], value: 100}
%{datapoint: :max, name: :test, options: [], value: 100}
%{datapoint: :min, name: :test, options: [], value: 100}
%{datapoint: :p95, name: :test, options: [], value: 100}
%{datapoint: :p99, name: :test, options: [], value: 100}
%{datapoint: :last_interval, name: :test, options: [], value: 100}
%{datapoint: :total, name: :test, options: [], value: 100}

Erlang VM metrics

Alchemetrics automatically collects some information about Erlang's VM, like memory and run queue. This is disabled by default, but you can enable it on the configs:

# config/config.exs
config :alchemetrics, instrument_beam: true

This will enable the report of some data from Erlang's VM:

%{datapoint: :memory_atom, options: [], type: :memory, value: 621465}
%{datapoint: :memory_binary, options: [], type: :memory, value: 392504}
%{datapoint: :memory_ets, options: [], type: :memory, value: 1365728}
%{datapoint: :memory_processes, options: [], type: :memory, value: 10513080}
%{datapoint: :memory_total, options: [], type: :memory, value: 38397232}
%{datapoint: :system_runqueue, options: [], type: :system, value: 1}

Getting Started: Instrumenting requests on a Phoenix application

Let's show an example of how Alchemetrics could be used to instrument a Phoenix application with the help of Plug:

In this example application we will measure:

  • The number of requests for each route of the application grouped by the status of the response;
  • The response times (average, percentiles, max and min) of each route;

The collected metrics will be printed to the console by Alchemetrics.ConsoleBackend. To do this, we need to enable it in the settings:

# config/config.exs

config :alchemetrics,
  backends: [
    [module: Alchemetrics.ConsoleBackend, []]
  ]

Let's create the RequestInstrumentor plug:

# lib/my_app_web/plugs/request_count.ex

defmodule RequestInstrumentor do
  @behaviour Plug

  def init(opts \\ []), do: opts
  def call(conn, opts), do: count_request(conn)

  defp count_request(conn) do
    start = System.monotonic_time()
    Plug.Conn.register_before_send(conn, fn conn ->
      stop = System.monotonic_time()
      diff = System.convert_time_unit(stop - start, :native, :micro_seconds)
      # report throughput
      Alchemetrics.increment(request_count: %{method: conn.method, path: conn.request_path, status: conn.status})
      # report request time
      Alchemetrics.report(diff, request_time: %{method: conn.method, path: conn.request_path})
      conn
    end)
  end
end

Plug it on Phoenix Endpoint:

defmodule MyAppWeb.Endpoint do
  use Phoenix.Endpoint, otp_app: :my_app

  plug RequestInstrumentor
  ...
end

Request your application:

$ mix phx.server
$ curl localhost:4000/

Information about the request will show on application console:

%{datapoint: :last_interval, options: [], requests_for: %{method: "GET", path: "/", status: 200}, value: 1}
%{datapoint: :total, options: [], requests_for: %{method: "GET", path: "/", status: 200}, value: 1}
%{datapoint: :avg, options: [], request_time: %{method: "GET", path: "/", status: 200}, value: 44069}
%{datapoint: :max, options: [], request_time: %{method: "GET", path: "/", status: 200}, value: 44069}
%{datapoint: :min, options: [], request_time: %{method: "GET", path: "/", status: 200}, value: 44069}
%{datapoint: :p95, options: [], request_time: %{method: "GET", path: "/", status: 200}, value: 44069}
%{datapoint: :p99, options: [], request_time: %{method: "GET", path: "/", status: 200}, value: 44069}
%{datapoint: :last_interval, options: [], request_time: %{method: "GET", path: "/", status: 200}, value: 44069}
%{datapoint: :total, options: [], request_time: %{method: "GET", path: "/", status: 200}, value: 44069}

If you request an inexistent route, the reports will show 404 status code:

%{datapoint: :last_interval, options: [], requests_for: %{method: "GET", path: "/invalid_route", status: 404}, value: 1}
%{datapoint: :total, options: [], requests_for: %{method: "GET", path: "/invalid_route", status: 404}, value: 1}
%{datapoint: :avg, options: [], request_time: %{method: "GET", path: "/invalid_route", status: 404}, value: 39558}
%{datapoint: :max, options: [], request_time: %{method: "GET", path: "/invalid_route", status: 404}, value: 39558}
%{datapoint: :min, options: [], request_time: %{method: "GET", path: "/invalid_route", status: 404}, value: 39558}
%{datapoint: :p95, options: [], request_time: %{method: "GET", path: "/invalid_route", status: 404}, value: 39558}
%{datapoint: :p99, options: [], request_time: %{method: "GET", path: "/invalid_route", status: 404}, value: 39558}
%{datapoint: :last_interval, options: [], request_time: %{method: "GET", path: "/invalid_route", status: 404}, value: 39558}
%{datapoint: :total, options: [], request_time: %{method: "GET", path: "/invalid_route", status: 404}, value: 39558}

For more details about reports, metrics, datasets, backends and all Alchemetrics concepts, take a look at the docs.

alchemetrics's People

Contributors

bernardolins avatar luty81 avatar hugolnx avatar raphamorim avatar vsouza avatar

Watchers

James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.