igaster/laravel-metrics

dev-master 2020-04-01 05:46 UTC

This package is auto-updated.

Last update: 2024-08-29 05:29:22 UTC


README

Laravel License Downloads Build Status Codecov

介绍

配置

示例提供者

这是一个负责配置指标并提供样本的类。

use Carbon\Carbon;
use Igaster\LaravelMetrics\Models\Metric;
use Igaster\LaravelMetrics\Services\Metrics\MetricsInterface;
use Igaster\LaravelMetrics\Services\Metrics\Sample;
use Igaster\LaravelMetrics\Services\Metrics\Segments\SegmentLevel;

class ExampleSamplesProvider implements MetricsInterface
{
    /**
     * Register a list of Metrics that this class will provide.
     * Returns an array of Metric
     */
    public function registerMetrics(): array 
    {
        // ...
    }

    /**
     * Return an array of Samples that have a timestamp >= $from (inclusive) and < $until (exclusive)
     * It will be called once for each $metric, every time that it's shortest sampling period has been completed (ie  every minute/day etc)
     */
    public function sample(Metric $metric, Carbon $from): array
    {
        // ...
    }

示例

registerMetrics():

此方法配置任意数量的指标

public function registerMetrics(): array 
{
    return [
        Metric::factory('metric-slug', [
            SegmentLevel::HOUR,             // Aggregation levels
            SegmentLevel::DAY,
            SegmentLevel::MONTH,
        ], [
            'size',                         // Partition names (keys)
            'color',
        ]),
    ];
}

sample():

此方法将在每个指标最低采样段的末尾执行(例如,每小时/每天等)。它应该返回一个数组,包含在此期间创建的每个事件生成的样本。

public function sample(Metric $metric, Carbon $from, Carbon $until): array
{
    return [
        new Sample(4, [ // Each sample may have a value
            'size' => 'large',
            'color' => 'blue',
        ]),
        new Sample(5, [
            'size' => 'large',
            // a partition can be skipped. Means "any value"
        ]),
        new Sample(6, [
            'size' => 'large',
            'color' => null, // Null is a normal value. it is not the same with skipping it (=any value) 
        ]),
        // ...
    ];
}

来自 Eloquent 模型的样本

您可以在想要采样的模型中使用 HasMetricsTrait。这个特质自动化了 Eloquent 查询,并提供了一个方便的接口将您的模型转换为样本。

注意:此步骤是 可选的。您可以直接在模型中实现 MetricsInterface,如前所述。

这是一个示例

use Igaster\LaravelMetrics\Models\Metric;
use Igaster\LaravelMetrics\Services\Metrics\HasMetricsTrait;
use Igaster\LaravelMetrics\Services\Metrics\MetricsInterface;
use Igaster\LaravelMetrics\Services\Metrics\Sample;
use Igaster\LaravelMetrics\Services\Metrics\Segments\SegmentLevel;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;

class ExampleSamplesModel extends Model implements MetricsInterface
{
    use HasMetricsTrait;

    /** @var string $samplesTimestampColumn Sets column that will be treated as a timestamp */
    private $samplesTimestampColumn = 'created_at'; // This is the default. Declaration can be omitted

    /**
     * Register a list of Metrics that this class will provide.
     * Returns an array of Metric
     */
    public function registerMetrics(): array
    {
        return [
            Metric::factory('metric-slug', [
                SegmentLevel::HOUR,
                SegmentLevel::DAY,
            ], [
                'color'
            ]),
        ];
    }

    /**
     * You can customize the query that will get the sampled items.
     * You don't have filter items based on their timestamp for current time slot.
     * These will be automatically selected based on the "created_at" value
     */
    public function getSamplesQuery(Metric $metric): Builder
    {
        return self::query()
            ->where('status','=','published') // Add your business logic...
            ->select([
                'quantity', // It is a good practice to get only the columns that are required in makeSample()
                'color' 
            ]);
    }

    /**
     * Transforms current eloquent model to a Sample
     */
    public function makeSample(): Sample
    {
        return new Sample(
            $this->quantity,
            [
                'color' => $this->color,
            ]
        );
    }
}

获取样本

采样是一个两步过程

1) 创建一个 "Sampler" 对象

  • 每个采样器都附属于一个 "样本提供者",该提供者将以常规的时间间隔进行检查。
  • 您可以通过以下方式创建采样器:a) 从对象实例创建,或 b) 从模型类名创建。
// a) Create a sampler from an object instance:

$samplesProvider = new ExampleSamplesProvider(); // ExampleSamplesProvider implements MetricsInterface.

$sampler = new MetricSampler($samplesProvider);

// b) Create a sampler from a Model:

$sampler = new MetricSampler(SomeModel::class); // SomeModel implements MetricsInterface.

2) 获取并处理某些时间段的样本。

必须满足以下要求

  • 必须完成时间槽才能获取有效结果(例如,您可以从上一小时获取样本,但不能从当前小时获取)
  • 时间是线性的:时间槽必须按顺序处理。时间槽内的样本可以按任何顺序获取,因为它们作为一批处理。
// Sample a single timeslot that starts at a timestamp.
// If a metric doesn't have a time-slot that starts at current timestamp, it will be skipped.
$sampler->sample($timestamp);

// Sample for a period of time
$sampler->samplePeriod($from, $until);

// Continue sampling since last sample was taken, and stop at some timestamp.
// If this is the 1st time that a metric is processed then current timestamp is initialized as starting time
// Only metrics that have a whole time-slot completed since last execution will be executed.
// $until doesn't have to match with the end of a time-slot. The end of the latest time-slot for each metric will be calculated and used. 
// You should design your system to call this method in regular intervals
$sampler->sampleUntil($until);

查询指标

计数 & 求和

获取一段时间内的样本的计数/求和。可以可选地指定分区

// Get count of events that occurred between two timestamps
// and have size=small, and color=red
Metric::get('metric-slug')->count(
    Carbon::parse('2020-01-01 00:00:00'),
    Carbon::parse('2020-01-01 02:00:00'),
    [
        'size' => 'small',
        'color' => 'red'
    ]
));

// Get total (sum) of events values that occurred between two timestamps
// and have size=small, and color=ANY (includes all color values)
Metric::get('metric-slug')->value(
    Carbon::parse('2020-01-01 00:00:00'),
    Carbon::parse('2020-01-01 02:00:00'),
    [
        'size' => 'small',
    ]
));

// Get count of events that occurred between two timestamps
// and belong to any partition
Metric::get('metric-slug')->count(
    Carbon::parse('2020-01-01 00:00:00'),
    Carbon::parse('2020-01-01 02:00:00')
));

按小时/天/月等获取

以下方法在 Metric 类中可用

$metric = Metric::get('metric-slug');

$metric->getByMinute($from, $until, $partitions);
$metric->getByHour($from, $until, $partitions);
$metric->getByDay($from, $until, $partitions);
$metric->getByMonth($from, $until, $partitions);
$metric->getByYear($from, $until, $partitions);

示例

Metric::get('metric-slug')->getByDay(
    Carbon::parse('2020-01-01 00:00:00'),
    Carbon::parse('2020-01-02 10:00:00'), [
        'color' => 'red',
    ]
);

//  Result is a collection for every day:
//  [
//      [
//          "from" => "2020-01-01 00:00:00",
//          "until" => "2020-01-02 00:00:00",
//          "count" => 72,
//          "value" => 144.0,
//      ],
//      [
//          "from" => "2020-01-02 00:00:00",
//          "until" => "2020-01-03 00:00:00",
//          "count" => 72,
//          "value" => 144.0,
//      ],
//     ...
//  ];