Completed
Push — master ( 1af786...fa8c29 )
by Petrică
03:05
created

NotifyCommand::closeStatsd()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 6
ccs 5
cts 5
cp 1
rs 9.4285
cc 2
eloc 3
nc 2
nop 0
crap 2
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: Petrica
5
 * Date: 3/22/2016
6
 * Time: 22:45
7
 */
8
namespace Petrica\StatsdSystem\Command;
9
10
use Domnikl\Statsd\Client;
11
use Petrica\StatsdSystem\Config\ConfigLoader;
12
use Petrica\StatsdSystem\Gauge\GaugeInterface;
13
use Petrica\StatsdSystem\Statsd\Connection\UdpSocket;
14
use Symfony\Component\Console\Command\Command;
15
use Symfony\Component\Console\Input\InputArgument;
16
use Symfony\Component\Console\Input\InputInterface;
17
use Symfony\Component\Console\Input\InputOption;
18
use Symfony\Component\Console\Output\OutputInterface;
19
20
class NotifyCommand extends Command
21
{
22
    /**
23
     * @var UdpSocket
24
     */
25
    protected $statsdConnection = null;
26
27
    /**
28
     * @var Client
29
     */
30
    protected $statsd = null;
31
32
    /**
33
     * Instantiated gauges
34
     *
35
     * @var array
36
     */
37
    protected $gauges = null;
38
39 1
    /**
40
     * @var null
41
     */
42
    protected $config = null;
43
44
    protected function configure()
45
    {
46 1
        $this
47 1
            ->setName('statsd:notify')
48
            ->setDescription('Collect and send defined gauges to statsd server')
49
            ->addArgument(
50
                'config',
51
                InputArgument::REQUIRED,
52
                'Path to yaml configuration file.'
53
            )
54
            ->addOption(
55
                'statsd-host',
56
                null,
57
                InputOption::VALUE_OPTIONAL,
58
                'Statsd server hostname',
59
                'localhost'
60
            )
61
            ->addOption(
62
                'statsd-port',
63
                null,
64
                InputOption::VALUE_OPTIONAL,
65
                'Statsd server port',
66
                '8125'
67
            )
68
            ->addOption(
69
                'statsd-namespace',
70
                null,
71
                InputOption::VALUE_OPTIONAL,
72
                'Gauge namespace sent to statsd',
73
                'system'
74
            )
75
            ->addOption(
76
                'iterations',
77
                null,
78
                InputOption::VALUE_OPTIONAL,
79
                'The number of times the job collects stats and sends them to statsd server before exiting.',
80
                3600
81
            );
82
    }
83
84
    /**
85
     * @param InputInterface $input
86
     * @param OutputInterface $output
87
     */
88
    protected function execute(InputInterface $input, OutputInterface $output)
89
    {
90
        $config = $this->getConfiguration($input);
91
        $gauges = $this->getGauges($config);
92
        $statsd = $this->getStatsd($input);
93
94
        $iterations = $input->getOption('iterations');
95
        $count = 0;
96
        while($count < $iterations)
97
        {
98
            foreach($gauges as $path => $gauge) {
99
                // Sampling period attained for current gauge?
100
                if (fmod($count, $gauge->getSamplingPeriod()) == 0) {
101
102
                    $values = $gauge->getCollection();
103
104
                    $statsd->startBatch();
105
106
                    foreach ($values as $key => $value) {
107
                        $composed = $path . '.' . $key;
108
109
                        if (null !== $value) {
110
                            $statsd->gauge($composed, $value);
111
                        }
112
113
                        if ($input->getOption('verbose')) {
114
                            $output->writeln(sprintf('%s: %s', $composed, $value));
115
                        }
116
                    }
117
118
                    $statsd->endBatch();
119
                    $this->closeStatsd();
120
                }
121
            }
122
123
            sleep(1);
124
            $count ++;
125
        }
126
    }
127
128 1
    /**
129
     * Statically cache statsd client and return a statsd client
130 1
     *
131 1
     * @param InputInterface $input
132 1
     * @return Client
133 1
     */
134 1
    protected function getStatsd(InputInterface $input)
135 1
    {
136 1
        if (null === $this->statsd) {
137 1
            $this->statsdConnection = new UdpSocket(
138 1
                $input->getOption('statsd-host'),
139 1
                $input->getOption('statsd-port')
140
            );
141 1
            $this->statsd = new Client(
142
                $this->statsdConnection,
143
                $input->getOption('statsd-namespace')
144
            );
145
        }
146
147
        return $this->statsd;
148
    }
149
150 1
    /**
151
     * Close statsd opened connection
152 1
     */
153 1
    protected function closeStatsd()
154
    {
155 1
        if (null != $this->statsdConnection) {
156 1
            $this->statsdConnection->close();
157 1
        }
158 1
    }
159
160 1
    /**
161
     * Instantiate selected gauges
162
     *
163
     * @param array $config
164
     * @return GaugeInterface[] array
165 1
     */
166
    protected function getGauges($config)
167 1
    {
168
        if (null === $this->gauges) {
169
            $this->gauges = array();
170
171
            foreach ($config as $path => $details) {
172
                $className = $details['class'];
173 1
                if (class_exists($className)) {
174
                    $reflection = new \ReflectionClass($className);
175 1
176
                    if ($reflection->getConstructor()) {
177
                        $this->gauges[$path] = $reflection->newInstanceArgs(
178
                            $details['arguments'] ? $details['arguments'] : array());
179
                    }
180 1
                    else {
181
                        $this->gauges[$path] = $reflection->newInstance();
182 1
                    }
183
                }
184
                else {
185
                    throw new \RuntimeException(sprintf(
186
                        'Class does not exists %s'
187
                    ), $className);
188
                }
189
            }
190
191
            if (empty($this->gauges)) {
192 1
                throw new \RuntimeException(
193
                    sprintf('No gauges found for provided string %s', $input->getArgument('gauges-class'))
194 1
                );
195
            }
196 1
        }
197
198
        return $this->gauges;
199
    }
200
201
    /**
202
     * Read Yaml configuration file
203
     * and returns array map
204
     *
205
     * @param InputInterface $input
206
     * @return array
207
     */
208
    protected function getConfiguration(InputInterface $input)
209
    {
210
        $loader = new ConfigLoader($input->getArgument('config'));
211
212
        return $loader->load();
213
    }
214
}
215