robertogallea/laravel-metrics

There is no license information available for the latest version (0.5.1) of this package.

Instrument your Laravel application with smart metrics

0.5.1 2021-06-14 12:40 UTC

This package is auto-updated.

Last update: 2024-11-10 14:58:25 UTC


README

Packagist Version GitHub Workflow Status

Introduction

This package allows to record metrics in your laravel application and performing statistics.

It also provides tools for implementing simple alerting mechanisms.

Installation

In order to install the package run

composer require robertogallea/laravel-metrics

Laravel auto-discovery will register package ServiceProvider and Aliases.

Configuration

If you wish to edit the package configuration run

php artisan vendor:publish --provider=robertogallea\\LaravelMetrics\\MetricsServiceProvider --tag=config

Usage

The package relies on the concept of Metric. A metric is a measure of some type inside the application.

Currently, two types of measures are supported:

  • Markers
  • Timers

Markers are just their name. These could be used to determine how many times an event occurred in your application.

Timers tracks events duration. These could be useful to determine how long events took to complete.

Save metrics

This is the simplest way of using metrics. In any part of your code you can save metrics as follows:

  • Markers:
$registry = resolve(MetricRegistry::class);
$marker = $registry->meter('metric-name');

$marker->mark();


// or you can use facade
$marker = \Metrics::meter('metric-name');

$marker->mark();
  • Timers
$registry = resolve(MetricRegistry::class);
$timer = $registry->meter('metric-name', MeterType::TIMER);

$timerId = $timer->start();

// or you can use facade
$timer = \Metrics::meter('metric-name', MeterType::TIMER);

$timerId = $timer->start();

doSomething();

$timer->stop($timerId);

By default, timers are stored using seconds resolution. However, desired resolution can be changed before stopping the timer:

$timer->inMicrosceconds()->stop($timerId);
$timer->inMilliseconds()->stop($timerId);
$timer->inSeconds()->stop($timerId);
$timer->inMinutes()->stop($timerId);
$timer->inHours()->stop($timerId);
$timer->inDays()->stop($timerId);
$timer->inWeeks()->stop($timerId);
$timer->inMonths()->stop($timerId);
$timer->inYears()->stop($timerId);

Storing metadata

If needed, you can also store additional metadata in your metrics, by passing a data array to the mark() or start()/stop() methods:

Marker

$data = ['key' => 'value'];
$marker->mark($data);

Timer

$data = ['key' => 'value'];
$timerId = $timer->start($data);

doSomething();

$timer->stop($timerId);

or

$timerId = $timer->start();

$data = doSomething();

$timer->stop($timerId, $data);

Measuring events

You could automatically save marker metrics during event dispatch by doing three steps:

  • Implementing the PerformsMetrics interface;
  • Using the Measurable trait;
  • Defining the $meter field with the name you want to use for your metric.
class TestEvent implements PerformsMetrics
{
    use Dispatchable;
    use Measurable;

    protected $meter = 'test';
}

Now, whenever you dispatch an event, the marker is automatically saved:

event(new TestEvent());

Creating measurable events

For your convenience a command is registered for creating measurable events:

php artisan make:measurable-event MyMeterEvent

Measuring requests

You can also instrument your requests by using two middlewares provided:

Route::get('/', 'HomeController@index')->middleware('mark:home-visits');

A Marker is saved with the home-visits name;

Route::get('/page/{page}', 'PagesController@show')->middleware('measure-time:page-visits-duration');

A Timer containing the request duration is saved with the page-visit-duration name.

Route::get('/details', 'DetailsController@index')->middleware('measure-time:details-duration,milliseconds');

Timer could be set to a specific resolution using a second parameter.

Retrieving metrics

There are two options for retrieving metrics:

  • Using MetricRegistry:
$registry = resolve(MetricRegistry::class);
$meter = $registry->meter('meter-name');
$meter->get(); // gets the entire dataset for the meter

$from = Carbon::yesterday();
$meter->after($from)->get(); // gets the dataset for meters recorded after $from

$to = Carbon::tomorrow();
$meter->before($from)->get(); // gets the dataset for meters recorded before $to

$meter->between($from, $to)->get(); // gets the dataset for meters recorded between $from and $to
  • Directly querying the Metric Eloquent model.

Time series

One of the most important aspect of using metrics is extracting time series from them with convenient statistics.

Currently supported statistics are count, average, max and min.

$registry = resolve(MetricRegistry::class);

$timer = $registry->meter('meter-name', MeterType::TIMER);

$from = Carbon::now()->subYears(2);
$to = Carbon::today();

$timeSeries = $this->timer->bySecond($from, $to, TimeSeriesStatistics::COUNT);
$timeSeries = $this->timer->byMinute($from, $to, TimeSeriesStatistics::AVERAGE);
$timeSeries = $this->timer->byHour($from, $to, TimeSeriesStatistics::MAX);
$timeSeries = $this->timer->byMonth($from, $to, TimeSeriesStatistics::MIN);
$timeSeries = $this->timer->byYear($from, $to, TimeSeriesStatistics::MIN);

Time series are generated as custom collection of type MetricCollection.

Statistics on time series

Once a time series is extracted, you can perform statistics on it. In addition to standard Collection methods, like mean(), max(), min(), avg(), etc., the MetricCollection class adds methods for performing other operations. Actually the following are supported:

  • stDev() - computes values standard deviation
  • variance() - computes values variance
  • cumulative() - computes discrete probability density function (i.e. cumulative sum)
  • histogram($nbins) - computes the histogram for the values using nbins bins.
  • kolmSmirn($collection) - computes Kolmogorov-Smirnov distance for comparing two time series.

Treeware

You're free to use this package, but if it makes it to your production environment you are required to buy the world a tree.

It’s now common knowledge that one of the best tools to tackle the climate crisis and keep our temperatures from rising above 1.5C is to plant trees. If you support this package and contribute to the Treeware forest you’ll be creating employment for local families and restoring wildlife habitats.

You can buy trees here offset.earth/treeware

Read more about Treeware at treeware.earth

Issues, Questions and Pull Requests

You can report issues and ask questions in the issues section. Please start your issue with ISSUE: and your question with QUESTION:

If you have a question, check the closed issues first. Over time, I've been able to answer quite a few.

To submit a Pull Request, please fork this repository, create a new branch and commit your new/updated code in there. Then open a Pull Request from your new branch. Refer to this guide for more info.