TrafficMonitor::inbound()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 2
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Traffic monitor
4
 * User: moyo
5
 * Date: 2018/6/6
6
 * Time: 11:38 AM
7
 */
8
9
namespace Carno\Web\Handlers;
10
11
use Carno\Chain\Layered;
12
use Carno\Coroutine\Context;
13
use Carno\HTTP\Standard\Response;
14
use Carno\Monitor\Metrics;
15
use Throwable;
16
17
class TrafficMonitor implements Layered
18
{
19
    /**
20
     * @var Metrics\Counter
21
     */
22
    private $ttRequests = null;
23
24
    /**
25
     * @var Metrics\Histogram
26
     */
27
    private $ttResponses = null;
28
29
    /**
30
     * @var Metrics\Counter
31
     */
32
    private $ttExceptions = null;
33
34
    /**
35
     * @var Metrics\Gauge
36
     */
37
    private $ttProcessing = null;
38
39
    /**
40
     * @var array
41
     */
42
    private $ttStatusCodes = [];
43
44
    /**
45
     * TrafficMonitor constructor.
46
     */
47
    public function __construct()
48
    {
49
        $this->ttRequests = Metrics::counter()->named('http.requests.all');
50
        $this->ttResponses = Metrics::histogram()->named('http.responses.time')->fixed(5, 20, 50, 200, 500, 1000);
51
        $this->ttExceptions = Metrics::counter()->named('http.exceptions.all');
52
        $this->ttProcessing = Metrics::gauge()->named('http.processing.now');
53
    }
54
55
    /**
56
     * @param int $status
57
     * @return Metrics\Counter
58
     */
59
    private function cc(int $status) : Metrics\Counter
60
    {
61
        return $this->ttStatusCodes[$status] ?? $this->ttStatusCodes[$status] =
62
            Metrics::counter()
63
                ->named('http.responses.code')
64
                ->labels(['code' => $status])
65
        ;
66
    }
67
68
    /**
69
     * @param mixed $message
70
     * @param Context $ctx
71
     * @return mixed
72
     */
73
    public function inbound($message, Context $ctx)
74
    {
75
        $this->requestBegin($ctx);
76
        $this->ttRequests->inc();
77
        $this->ttProcessing->inc();
78
        return $message;
79
    }
80
81
    /**
82
     * @param mixed $message
83
     * @param Context $ctx
84
     * @return mixed
85
     */
86
    public function outbound($message, Context $ctx)
87
    {
88
        $this->ttProcessing->dec();
89
        $this->requestEnd($ctx);
90
        return $message;
91
    }
92
93
    /**
94
     * @param Throwable $e
95
     * @param Context $ctx
96
     * @throws Throwable
97
     */
98
    public function exception(Throwable $e, Context $ctx)
99
    {
100
        $this->ttProcessing->dec();
101
        $this->ttExceptions->inc();
102
        $this->requestEnd($ctx);
103
        throw $e;
104
    }
105
106
    /**
107
     * @param Context $ctx
108
     */
109
    private function requestBegin(Context $ctx) : void
110
    {
111
        $ctx->set('tm-r-begin', microtime(true));
112
    }
113
114
    /**
115
     * @param Context $ctx
116
     */
117
    private function requestEnd(Context $ctx) : void
118
    {
119
        /**
120
         * @var Response $response
121
         */
122
123
        if ($response = $ctx->get(IngressWrapper::RESPONDING)) {
124
            $this->cc($response->getStatusCode())->inc();
125
        }
126
127
        $this->ttResponses->observe((microtime(true) - $ctx->get('tm-r-begin') ?? 0) * 1000);
128
    }
129
}
130