SilexSetup::setupAndGetMetricsRoute()   A
last analyzed

Complexity

Conditions 2
Paths 1

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 5
Bugs 0 Features 0
Metric Value
c 5
b 0
f 0
dl 0
loc 14
rs 9.4285
cc 2
eloc 9
nc 1
nop 2
1
<?php
2
3
/*
4
 * This file is part of the PHPProm package.
5
 *
6
 * (c) Philip Lehmann-Böhm <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace PHPProm\Integration;
13
14
use PHPProm\PrometheusExport;
15
use PHPProm\StopWatch;
16
use PHPProm\Storage\AbstractStorage;
17
use Silex\Application;
18
use Silex\Route;
19
use Symfony\Component\HttpFoundation\Request;
20
use Symfony\Component\HttpFoundation\Response;
21
22
/**
23
 * Class SilexSetup
24
 * Setups Silex applications to measure:
25
 * - the time of each route
26
 * - the used memory of each route
27
 * - the amount of requests of each route
28
 * It also offers an function to be used for a Prometheus scrapable endpoint.
29
 * @package PHPProm\Integration
30
 */
31
class SilexSetup {
32
33
    /**
34
     * Sets up the Silex middlewares where the actual measurements happen.
35
     *
36
     * @param Application $app
37
     * the Silex application
38
     * @param AbstractStorage $storage
39
     * the storage for the measurements
40
     */
41
    protected function setupMiddleware(Application $app, AbstractStorage $storage) {
42
43
        $storage->addAvailableMetric('route_time', 'name', 'request times per route in seconds', 'gauge', 'Nan');
44
        $storage->addAvailableMetric('route_memory', 'name', 'request memory per route in bytes', 'gauge', 'Nan');
45
        $storage->addAvailableMetric('route_requests_total', 'name', 'total requests per route', 'counter', 0);
46
47
        $routeTime = new StopWatch($storage);
48
49
        $app->before(function() use ($routeTime) {
50
            $routeTime->start();
51
        }, Application::EARLY_EVENT);
52
53
        $app->finish(function(Request $request) use ($routeTime, $storage) {
54
            $route = $request->get('_route');
55
            $routeTime->stop('route_time', $route);
56
            $storage->storeMeasurement('route_memory', $route, memory_get_peak_usage(true));
57
            $storage->incrementMeasurement('route_requests_total', $route);
58
        });
59
60
    }
61
62
    /**
63
     * Gets the path with all methods from a route.
64
     *
65
     * @param Route $route
66
     * the route to get the path and methods from
67
     * @return array
68
     * the pathes with methods
69
     */
70
    protected function getPathWithMethods(Route $route) {
71
        $supportedMethods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'];
72
        $path             = str_replace('/', '_', $route->getPath());
73
        $foundMethod      = false;
74
        $routes           = [];
75
        foreach ($route->getMethods() as $method) {
76
            $routes[]    = $method.$path;
77
            $foundMethod = true;
78
        }
79
        if (!$foundMethod) {
80
            foreach ($supportedMethods as $supportedMethod) {
81
                $routes[] = $supportedMethod.$path;
82
            }
83
        }
84
        return $routes;
85
    }
86
87
    /**
88
     * Sets up the Silex middlewares where the actual measurements happen
89
     * and returns a function to be used for a Prometheus scrapable endpoint.
90
     *
91
     * @param Application $app
92
     * the Silex application
93
     * @param AbstractStorage $storage
94
     * the storage for the measurements
95
     *
96
     * @return \Closure
97
     * the function to be used for a Prometheus scrapable endpoint
98
     */
99
    public function setupAndGetMetricsRoute(Application $app, AbstractStorage $storage) {
100
101
        $this->setupMiddleware($app, $storage);
102
103
        return function() use ($app, $storage) {
104
            $routes = [];
105
            foreach ($app['routes']->all() as $route) {
106
                $routes = array_merge($routes, $this->getPathWithMethods($route));
107
            }
108
            $export   = new PrometheusExport();
109
            $response = $export->getExport($storage, $routes);
110
            return new Response($response, 200, ['Content-Type' => 'text/plain; version=0.0.4']);
111
        };
112
    }
113
114
}
115