4
4
5
5
use Illuminate \Contracts \Config \Repository ;
6
6
use Illuminate \Contracts \Http \Kernel ;
7
+ use Illuminate \Database \Events \QueryExecuted ;
7
8
use Illuminate \Routing \Router ;
9
+ use Illuminate \Support \Facades \App ;
10
+ use Illuminate \Support \Facades \DB ;
11
+ use Illuminate \Support \Facades \Log ;
8
12
use Illuminate \Support \ServiceProvider ;
13
+ use Jobilla \CloudNative \Laravel \Exceptions \UnsupportedAdapterException ;
9
14
use Jobilla \CloudNative \Laravel \Http \Controllers \ServeMetrics ;
10
15
use Jobilla \CloudNative \Laravel \Http \Middleware \RecordPrometheusMetrics ;
11
16
use Prometheus \CollectorRegistry ;
12
17
use Prometheus \Storage \APC ;
18
+ use Prometheus \Storage \APCng ;
19
+ use Prometheus \Storage \InMemory ;
20
+ use Prometheus \Storage \Redis ;
13
21
14
22
class CloudNativeServiceProvider extends ServiceProvider
15
23
{
24
+ protected CollectorRegistry $ registry ;
25
+
16
26
public function register ()
17
27
{
18
28
$ this ->mergeConfigFrom (__DIR__ .'/../config/metrics.php ' , 'metrics ' );
19
-
20
- $ this ->app ->singleton (CollectorRegistry::class, function () {
21
- return new CollectorRegistry (new APC ());
22
- });
23
29
}
24
30
25
31
public function boot (Repository $ config , Kernel $ kernel )
26
32
{
27
- $ this ->publishes ([
28
- __DIR__ .'/../config/logging.php ' => config_path ('logging.php ' ),
29
- __DIR__ .'/../config/metrics.php ' => config_path ('metrics.php ' ),
30
- ], 'cloud-native-config ' );
31
-
32
- $ this ->publishes ([
33
- __DIR__ .'/../config/logging.php ' => config_path ('logging.php ' ),
34
- ], 'cloud-native-logging ' );
35
-
36
33
$ this ->publishes ([
37
34
__DIR__ .'/../config/metrics.php ' => config_path ('metrics.php ' ),
38
35
], 'cloud-native-metrics ' );
@@ -41,11 +38,55 @@ public function boot(Repository $config, Kernel $kernel)
41
38
__DIR__ .'/../assets/Dockerfile ' => base_path ('Dockerfile ' ),
42
39
], 'dockerfile ' );
43
40
44
- if ($ config ->get ('metrics.route.enabled ' )) {
41
+ $ this ->app ->singleton (CollectorRegistry::class, function () use ($ config ) {
42
+ $ adapter = $ config ->get ('metrics.adapter ' , 'memory ' );
43
+
44
+ switch ($ adapter ) {
45
+ case 'redis ' :
46
+ return new CollectorRegistry (new Redis );
47
+ break ;
48
+ case 'apc ' :
49
+ if (filter_var (ini_get ('apcu.enable_cli ' ), FILTER_VALIDATE_BOOLEAN ) === false && App::runningInConsole ()) {
50
+ Log::warning ('Metrics adapter temporarily turned to "memory" because apc is disabled in CLI. See: https://www.php.net/manual/en/apcu.configuration.php ' );
51
+ return new CollectorRegistry (new InMemory );
52
+ }
53
+
54
+ return new CollectorRegistry (new APC );
55
+ break ;
56
+ case 'apcng ' :
57
+ return new CollectorRegistry (new APCng );
58
+ break ;
59
+ case 'memory ' :
60
+ return new CollectorRegistry (new InMemory );
61
+ break ;
62
+ default :
63
+ throw new UnsupportedAdapterException ("Adapter ` {$ adapter }` is not supported. " );
64
+ break ;
65
+ }
66
+ });
67
+
68
+ $ this ->registry = $ this ->app ->make (CollectorRegistry::class);
69
+
70
+ if ($ this ->registry && $ config ->get ('metrics.handle.database ' )) {
71
+ DB ::listen (function (QueryExecuted $ query ) use ($ config ) {
72
+ $ query_labels = ['query ' => $ query ->sql , 'mode ' => strtok ($ query ->sql , ' ' )];
73
+
74
+ $ query_counter = $ this ->registry ->getOrRegisterCounter ('db ' , 'query_total ' , 'Counter of total queries ' , array_keys ($ query_labels ));
75
+ $ query_counter ->inc (array_values ($ query_labels ));
76
+
77
+ $ query_duration = $ this ->registry ->getOrRegisterHistogram ('db ' , 'query_duration_ms ' , 'Duration of query ' , array_keys ($ query_labels ), $ config ->get ('metrics.buckets ' ));
78
+ $ query_duration ->observe ($ query ->time , array_values ($ query_labels ));
79
+ });
80
+ }
81
+
82
+ if ($ this ->registry && $ config ->get ('metrics.handle.http ' )) {
83
+ $ kernel ->prependMiddleware (RecordPrometheusMetrics::class);
84
+ }
85
+
86
+ if ($ this ->registry && $ config ->get ('metrics.route.enabled ' )) {
45
87
/** @var Router $router */
46
88
$ router = $ this ->app ['router ' ];
47
89
$ router ->get ($ config ->get ('metrics.route.path ' ), ServeMetrics::class);
48
- $ kernel ->prependMiddleware (RecordPrometheusMetrics::class);
49
90
}
50
91
}
51
92
}
0 commit comments