Completed
Push — master ( 52a46f...98e19a )
by Petrică
02:29
created

NotifyCommand::getGauges()   C

Complexity

Conditions 7
Paths 4

Size

Total Lines 34
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 9.3554

Importance

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