Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reporter #68

Open
wants to merge 34 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
a93cced
add prometheus reporter
ArtARTs36 Sep 26, 2023
8e82e4c
add category to metric subjct
ArtARTs36 Sep 27, 2023
198c8e1
add samples
ArtARTs36 Sep 27, 2023
524895f
move storage
ArtARTs36 Sep 27, 2023
5dc448b
refactor
ArtARTs36 Sep 27, 2023
33ddb7a
refactor
ArtARTs36 Sep 27, 2023
4e800a7
move flusher
ArtARTs36 Sep 27, 2023
48a3502
rename provider
ArtARTs36 Sep 27, 2023
e33bd6c
add report config
ArtARTs36 Sep 27, 2023
3e388ba
add metric storage factory
ArtARTs36 Sep 27, 2023
ee82e2d
add metric registerer
ArtARTs36 Sep 27, 2023
06f4522
refactor metrics
ArtARTs36 Sep 28, 2023
adcb011
add metric handler for rule events
ArtARTs36 Sep 28, 2023
72cfb7f
fix stat-analyse issues
ArtARTs36 Sep 28, 2023
f1413ff
print metrics
ArtARTs36 Sep 28, 2023
714222e
fix stat analyse
ArtARTs36 Sep 28, 2023
42cc3f6
fix test part
ArtARTs36 Sep 28, 2023
45c8619
rename manager to registry
ArtARTs36 Sep 28, 2023
9b82088
test
ArtARTs36 Sep 28, 2023
1659de3
fix test namespace
ArtARTs36 Sep 28, 2023
d43fdc9
fix test
ArtARTs36 Sep 28, 2023
3ca3ae9
fix lint
ArtARTs36 Sep 28, 2023
836d836
add test
ArtARTs36 Sep 28, 2023
391bb5f
add test
ArtARTs36 Sep 28, 2023
0757788
rename var
ArtARTs36 Sep 28, 2023
eeb2296
add test
ArtARTs36 Sep 28, 2023
93cacbc
add test for abstract vector
ArtARTs36 Sep 28, 2023
f53bd64
add test for renderer
ArtARTs36 Sep 28, 2023
46e6966
add cov
ArtARTs36 Sep 28, 2023
598682e
add test for pushgateway client
ArtARTs36 Sep 28, 2023
776eaf2
move tests
ArtARTs36 Sep 28, 2023
c4d9c4e
remove metrics from config
ArtARTs36 Sep 28, 2023
ff5842a
fix stat analyse
ArtARTs36 Sep 28, 2023
d184487
fix lint
ArtARTs36 Sep 28, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
add prometheus reporter
  • Loading branch information
ArtARTs36 committed Sep 26, 2023
commit a93cced8e6b947a3d1cbb08f0a177aa8b43ab709
16 changes: 16 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
services:
prometheus:
restart: always
image: bitnami/prometheus:latest
links:
- pushgateway
volumes:
- ./prom.yml:/opt/bitnami/prometheus/conf/prometheus.yml
ports:
- 9092:9090

pushgateway:
restart: always
image: bitnami/pushgateway:latest
ports:
- 9091:9091
11 changes: 11 additions & 0 deletions prom.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
global:
scrape_interval: 5s
scrape_timeout: 2s
evaluation_interval: 15s

scrape_configs:
- job_name: pushgateway
honor_labels: true
static_configs:
- targets:
- 'pushgateway:9091'
41 changes: 41 additions & 0 deletions src/Application/Report/Reporter/PrometheusPushGatewayReporter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

namespace ArtARTs36\MergeRequestLinter\Application\Report\Reporter;

use ArtARTs36\MergeRequestLinter\Domain\Linter\LintResult;
use ArtARTs36\MergeRequestLinter\Domain\Request\MergeRequest;
use ArtARTs36\MergeRequestLinter\Infrastructure\Prometheus\PushGateway\Metric;
use ArtARTs36\MergeRequestLinter\Infrastructure\Prometheus\PushGateway\PushGateway;
use ArtARTs36\MergeRequestLinter\Shared\Metrics\Value\MetricManager;

class PrometheusPushGatewayReporter implements Reporter
{
public function __construct(
private readonly MetricManager $metrics,
private readonly PushGateway $client,
) {
}

public function report(MergeRequest $request, LintResult $result): void
{
$jobId = sprintf('%s-%s', $request->uri, time());
$jobIdHash = md5($jobId);

$this->client->push($jobIdHash, $this->collectMetrics($request, $result));
}

/**
* @return array<Metric>
*/
private function collectMetrics(MergeRequest $request, LintResult $result): array
{
$labels = ['repo' => (string) $request->uri, 'request_id' => $request->id];
$metrics = [];

$metrics[] = Metric::gauge('mr_linter_lint_state', 'MR Linter: lint state', $labels, $result->state->value);
$metrics[] = Metric::gauge('mr_linter_lint_duration', 'MR Linter: lint duration', $labels, $result->duration->seconds);
$metrics[] = Metric::gauge('mr_linter_lint_notes', 'MR Linter: lint duration', $labels, $result->notes->count());

return $metrics;
}
}
11 changes: 11 additions & 0 deletions src/Application/Report/Reporter/Reporter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace ArtARTs36\MergeRequestLinter\Application\Report\Reporter;

use ArtARTs36\MergeRequestLinter\Domain\Linter\LintResult;
use ArtARTs36\MergeRequestLinter\Domain\Request\MergeRequest;

interface Reporter
{
public function report(MergeRequest $request, LintResult $result): void;
}
30 changes: 30 additions & 0 deletions src/Application/Report/Reporter/ReporterFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace ArtARTs36\MergeRequestLinter\Application\Report\Reporter;

use ArtARTs36\MergeRequestLinter\Infrastructure\Http\Client\ClientGuzzleWrapper;
use ArtARTs36\MergeRequestLinter\Infrastructure\Prometheus\PushGateway\PushGateway;
use ArtARTs36\MergeRequestLinter\Infrastructure\Prometheus\PushGateway\PushGatewayClient;
use ArtARTs36\MergeRequestLinter\Infrastructure\Prometheus\PushGateway\Renderer;
use ArtARTs36\MergeRequestLinter\Shared\Metrics\Value\MetricManager;
use GuzzleHttp\Client;
use Psr\Log\LoggerInterface;

class ReporterFactory
{
public function __construct(
private readonly MetricManager $metrics,
private readonly LoggerInterface $logger,
) {
}

public function create(string $type, array $params): Reporter
{
if ($type === 'prometheusPushGateway') {
return new PrometheusPushGatewayReporter(
$this->metrics,
new PushGateway(new PushGatewayClient(new ClientGuzzleWrapper(new Client(), $this->logger)), new Renderer()),
);
}
}
}
28 changes: 28 additions & 0 deletions src/Application/Report/ReporterHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace ArtARTs36\MergeRequestLinter\Application\Report;

use ArtARTs36\MergeRequestLinter\Application\Report\Reporter\Reporter;
use ArtARTs36\MergeRequestLinter\Domain\Linter\LintFinishedEvent;
use ArtARTs36\MergeRequestLinter\Infrastructure\NotificationEvent\Listener;

class ReporterHandler implements Listener
{
public function __construct(
private readonly Reporter $reporter,
) {
}

public function handle(object $event): void
{
if (! $event instanceof LintFinishedEvent) {
throw new \LogicException(sprintf(
'ReporterHandler expects event of %s, actual: %s',
LintFinishedEvent::class,
$event::class,
));
}

$this->reporter->report($event->request, $event->result);
}
}
7 changes: 6 additions & 1 deletion src/Infrastructure/Http/Exceptions/HttpRequestException.php
Original file line number Diff line number Diff line change
@@ -24,7 +24,12 @@ public static function create(RequestInterface $request, ResponseInterface $resp
return new static(
$request,
$response,
sprintf('%s returns response with status %d', $request->getUri()->getHost(), $response->getStatusCode()),
sprintf(
'%s returns response with status %d: %s',
$request->getUri()->getHost(),
$response->getStatusCode(),
$response->getBody()->getContents(),
),
);
}

29 changes: 29 additions & 0 deletions src/Infrastructure/Prometheus/PushGateway/Metric.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace ArtARTs36\MergeRequestLinter\Infrastructure\Prometheus\PushGateway;

/**
* @codeCoverageIgnore
*/
readonly class Metric
{
/**
* @param array<string, int|string> $labels
*/
public function __construct(
public string $type,
public string $key,
public string $help,
public array $labels,
public int|string|float $value,
) {
}

/**
* @param array<string, int|string> $labels
*/
public static function gauge(string $key, string $help, array $labels, int|string|float $value): self
{
return new self('gauge', $key, $help, $labels, $value);
}
}
22 changes: 22 additions & 0 deletions src/Infrastructure/Prometheus/PushGateway/PushGateway.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

namespace ArtARTs36\MergeRequestLinter\Infrastructure\Prometheus\PushGateway;

class PushGateway
{
public function __construct(
private readonly PushGatewayClient $client,
private readonly Renderer $renderer,
) {
}

/**
* @param iterable<Metric> $records
*/
public function push(string $job, iterable $records): void
{
$data = $this->renderer->render($records);

$this->client->replace($job, $data);
}
}
21 changes: 21 additions & 0 deletions src/Infrastructure/Prometheus/PushGateway/PushGatewayClient.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace ArtARTs36\MergeRequestLinter\Infrastructure\Prometheus\PushGateway;

use ArtARTs36\MergeRequestLinter\Infrastructure\Contracts\Http\Client;
use GuzzleHttp\Psr7\Request;

class PushGatewayClient
{
public function __construct(
private readonly Client $http,
) {
}

public function replace(string $job, string $data): void
{
$url = "http://host.docker.internal:9091/metrics/job/{$job}";

$this->http->sendRequest(new Request('POST', $url, body: $data));
}
}
54 changes: 54 additions & 0 deletions src/Infrastructure/Prometheus/PushGateway/Renderer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

namespace ArtARTs36\MergeRequestLinter\Infrastructure\Prometheus\PushGateway;

class Renderer
{
/**
* @param iterable<Metric> $records
*/
public function render(iterable $records): string
{
$content = '';

foreach ($records as $metric) {
$value = $metric->value;

$labelsString = $this->collectLabels($metric);

$content .= <<<HTML
# HELP {$metric->key} The number of items in the queue.
# TYPE {$metric->key} {$metric->type}

{$metric->key}{$labelsString} $value

HTML;
}

return $content;
}

private function collectLabels(Metric $metric): string
{
if (count($metric->labels) === 0) {
return '';
}

$labelsString = '{';
$labels = $metric->labels;

foreach ($labels as $labelKey => $labelValue) {
$labelsString .= sprintf(
'%s=%s',
$labelKey,
is_string($labelValue) ? ('"'. $labelValue .'"') : $labelValue,
);

if (next($labels) !== false) {
$labelsString .= ',';
}
}

return $labelsString . '}';
}
}
2 changes: 2 additions & 0 deletions src/Presentation/Console/Application/ApplicationFactory.php
Original file line number Diff line number Diff line change
@@ -41,6 +41,7 @@
use ArtARTs36\MergeRequestLinter\Providers\CommentProvider;
use ArtARTs36\MergeRequestLinter\Providers\EventDispatcherProvider;
use ArtARTs36\MergeRequestLinter\Providers\NotificationsProvider;
use ArtARTs36\MergeRequestLinter\Providers\ReportProvider;
use ArtARTs36\MergeRequestLinter\Providers\RuleProvider;
use ArtARTs36\MergeRequestLinter\Providers\ServiceProvider;
use ArtARTs36\MergeRequestLinter\Shared\Events\EventManager;
@@ -61,6 +62,7 @@ class ApplicationFactory
NotificationsProvider::class,
RuleProvider::class,
CommentProvider::class,
ReportProvider::class,
];

public function __construct(
2 changes: 1 addition & 1 deletion src/Presentation/Console/Command/LintCommand.php
Original file line number Diff line number Diff line change
@@ -117,7 +117,7 @@ private function printMetrics(StyleInterface $style, LintResult $result, bool $f
if ($fullMetrics) {
$metrics = $metrics->merge(
$this->metrics->describe()->mapToArray(
static fn (Record $record) => new Metric($record->subject->name, $record->getValue()),
static fn (Record $record) => new Metric($record->subject->name, $record->value->getMetricValue()),
)
);
}
35 changes: 35 additions & 0 deletions src/Providers/ReportProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

namespace ArtARTs36\MergeRequestLinter\Providers;

use ArtARTs36\MergeRequestLinter\Application\Report\Reporter\ReporterFactory;
use ArtARTs36\MergeRequestLinter\Domain\Linter\LintFinishedEvent;
use ArtARTs36\MergeRequestLinter\Shared\Events\CallbackListener;
use ArtARTs36\MergeRequestLinter\Shared\Events\EventManager;
use ArtARTs36\MergeRequestLinter\Shared\Metrics\Value\MetricManager;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;

final class ReportProvider extends Provider
{
public function provide(): void
{
$this
->container
->bind(ReporterFactory::class, static function (ContainerInterface $container) {
return new ReporterFactory(
$container->get(MetricManager::class),
$container->get(LoggerInterface::class),
);
});

$this
->container
->get(EventManager::class)
->listen(LintFinishedEvent::class, new CallbackListener('reporter', function (LintFinishedEvent $event) {
$factory = $this->container->get(ReporterFactory::class);

$factory->create('prometheusPushGateway', [])->report($event->request, $event->result);
}));
}
}
7 changes: 1 addition & 6 deletions src/Shared/Metrics/Value/Record.php
Original file line number Diff line number Diff line change
@@ -6,13 +6,8 @@
{
public function __construct(
public MetricSubject $subject,
private Metric $value,
public Metric $value,
public \DateTimeInterface $date,
) {
}

public function getValue(): string
{
return $this->value->getMetricValue();
}
}
31 changes: 0 additions & 31 deletions tests/Unit/Shared/Metrics/Value/RecordTest.php

This file was deleted.