hellofresh/stats-php

2.0.0 2019-12-02 17:12 UTC

README

codecov

PHP编写的通用统计库

这是一个通用的统计库,我们HelloFresh在项目中使用它来收集服务的统计数据,然后创建监控仪表板以跟踪活动和问题。

支持的PHP版本

stats-php 版本 1.x 支持以下PHP版本: 7.07.17.2。如果您打算使用较新的PHP版本,请考虑使用版本 2.x+

从版本 2.x 开始,此库开始使用内置的 intl PHP扩展,而不是 behat/transliterator

主要特性

  • 多个统计后端
    • log 用于开发环境
    • statsd 用于生产
    • memory 用于测试目的,跟踪单元测试中的统计操作
    • noop 用于不需要收集任何统计信息的环境
  • 对所有指标使用固定的指标部分计数,以便在 grafana 中轻松设置监控/警报
  • 易于构建HTTP请求指标 - 时间和计数
  • 泛化或修改HTTP请求指标 - 例如,跳过ID部分

依赖项

版本 1.x

  • php: >= 7.0
  • behat/transliterator: ^1.2

版本 2.x

  • php: >= 7.3
  • ext-intl: >= 2.0

安装

composer require hellofresh/stats-php

使用

实例创建

连接DSN具有以下格式: <type>://<connection params>/<connection path>?<connection options>

  • <type> - 支持的后端之一:logstatsdmemorynoop
  • <connection params> - 仅用于 statsd 后端,用于定义主机和端口
  • <connection path> - 仅用于 statsd 后端,用于定义前缀/命名空间
  • <connection options> - 仅用于 statsd 后端
    • timeout - statsd请求超时(秒),如果未设置,则使用 ini_get('default_socket_timeout')
    • error - 抛出连接错误异常,默认值为 true
<?php

use HelloFresh\Stats\Factory;

$statsdClient = Factory::build('statsd://statsd-host:8125/prefix?timeout=2.5&error=1', $logger);

// php parse_url does not support url with only schema part set
$logClient = Factory::build('log://log', $logger);

// php parse_url does not support url with only schema part set
$noopClient = Factory::build('noop://noop', $logger);

// php parse_url does not support url with only schema part set
$memoryClient = Factory::build('memory://memory', $logger);

// php parse_url does not support url with only schema part set
$statsClient = Factory::build(getenv('STATS_DSN'), $logger);

手动计数指标

<?php

use HelloFresh\Stats\Bucket\MetricOperation;
use HelloFresh\Stats\Factory;

$statsClient = Factory::build(getenv('STATS_DSN'), $logger);

$section = 'ordering';
$timer = $statsClient->buildTimer()->start();
$operation = new MetricOperation(['orders', 'order', 'create']);

try {
    OrdersService::create(...);
    $statsClient->trackOperation($section, $operation, true, $timer);
} catch (\Exception $e) {
    $statsClient->trackOperation($section, $operation, false, $timer);
}

$statsClient->trackMetric('requests', $operation);

$ordersInTheLast24Hours = OrdersService::count(60 * 60 * 24);
$statsClient->trackState($section, $operation, $ordersInTheLast24Hours);

通过类型泛化资源并删除资源ID

在某些情况下,您不需要收集所有唯一请求的指标,但需要一个类似类型的请求的单一指标,例如,具体用户页面的访问时间并不重要,但平均访问时间很重要。hellofresh/stats-php 允许修改HTTP请求指标并支持开箱即用的ID过滤,因此您可以得到泛化指标 get.users.-id- 而不是成千上万的指标,如 get.users.1get.users.13get.users.42 等,这可能导致您的 graphite 过载。

要使用第二级路径ID的泛化指标,可以将 HelloFresh\Stats\HTTPMetricAlterCallback\HasIDAtSecondLevel 实例传递给 HelloFresh\Stats\Client::setHTTPMetricAlterCallback()。此外,还有一个构建方法 HelloFresh\Stats\HTTPMetricAlterCallback\HasIDAtSecondLevel::createFromStringMap(),可以从字符串映射构建回调实例,因此您可以从配置中获取这些值。它接受以下格式的测试回调的列表:<section>:<test-callback-name>。您可以使用双冒号或换行符作为部分-回调对的分隔符,因此以下所有形式都是正确的

  • <section-0>:<test-callback-name-0>:<section-1>:<test-callback-name-1>:<section-2>:<test-callback-name-2>
  • <section-0>:<test-callback-name-0>\n<section-1>:<test-callback-name-1>\n<section-2>:<test-callback-name-2>
  • <section-0>:<test-callback-name-0>:<section-1>:<test-callback-name-1>\n<section-2>:<test-callback-name-2>

目前实现了以下测试回调函数:

  • true - 第二层路径总是被处理为ID,例如 /users/13 -> users.-id-/users/search -> users.-id-/users -> users.-id-
  • numeric - 只有数字形式的第二层路径被解释为ID,例如 /users/13 -> users.-id-/users/search -> users.search
  • not_empty - 只有非空的第二层路径被解释为ID,例如 /users/13 -> users.-id-/users -> users.-

您可以使用 HelloFresh\Stats\HTTPMetricAlterCallback\HasIDAtSecondLevel::registerSectionTest() 实例方法或构建方法的第二个参数注册您自己的测试回调函数 - 构建方法会验证测试回调函数是否与已注册的列表匹配。

<?php

use HelloFresh\Stats\Factory;
use HelloFresh\Stats\HTTPMetricAlterCallback\HasIDAtSecondLevel;

$statsClient = Factory::build(getenv('STATS_DSN'), $logger);
// STATS_IDS=users:numeric:search:not_empty
$callback = HasIDAtSecondLevel::createFromStringMap(getenv('STATS_IDS'));
$statsClient->setHTTPMetricAlterCallback($callback);

$timer = $statsClient->buildTimer()->start();

// GET /users/42 -> get.users.-id-
// GET /users/edit -> get.users.edit
// POST /users -> post.users.-
// GET /search -> get.search.-
// GET /search/friday%20beer -> get.search.-id-
$statsClient->trackRequest($request, $timer, true);