1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* This file is part of graze/dog-statsd |
4
|
|
|
* |
5
|
|
|
* Copyright (c) 2016 Nature Delivered Ltd. <https://www.graze.com> |
6
|
|
|
* |
7
|
|
|
* For the full copyright and license information, please view the LICENSE |
8
|
|
|
* file that was distributed with this source code. |
9
|
|
|
* |
10
|
|
|
* @license https://github.com/graze/dog-statsd/blob/master/LICENSE.md |
11
|
|
|
* @link https://github.com/graze/dog-statsd |
12
|
|
|
*/ |
13
|
|
|
|
14
|
|
|
namespace Graze\DogStatsD; |
15
|
|
|
|
16
|
|
|
use Graze\DogStatsD\Exception\ConfigurationException; |
17
|
|
|
use Graze\DogStatsD\Exception\ConnectionException; |
18
|
|
|
|
19
|
|
|
/** |
20
|
|
|
* StatsD Client Class - Modified to support DataDogs statsd server |
21
|
|
|
*/ |
22
|
|
|
class Client |
23
|
|
|
{ |
24
|
|
|
const STATUS_OK = 0; |
25
|
|
|
const STATUS_WARNING = 1; |
26
|
|
|
const STATUS_CRITICAL = 2; |
27
|
|
|
const STATUS_UNKNOWN = 3; |
28
|
|
|
|
29
|
|
|
const PRIORITY_LOW = 'low'; |
30
|
|
|
const PRIORITY_NORMAL = 'normal'; |
31
|
|
|
|
32
|
|
|
const ALERT_ERROR = 'error'; |
33
|
|
|
const ALERT_WARNING = 'warning'; |
34
|
|
|
const ALERT_INFO = 'info'; |
35
|
|
|
const ALERT_SUCCESS = 'success'; |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* Instance instances array |
39
|
|
|
* |
40
|
|
|
* @var array |
41
|
|
|
*/ |
42
|
|
|
protected static $instances = []; |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* Instance ID |
46
|
|
|
* |
47
|
|
|
* @var string |
48
|
|
|
*/ |
49
|
|
|
protected $instanceId; |
50
|
|
|
|
51
|
|
|
/** |
52
|
|
|
* Server Host |
53
|
|
|
* |
54
|
|
|
* @var string |
55
|
|
|
*/ |
56
|
|
|
protected $host = '127.0.0.1'; |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* Server Port |
60
|
|
|
* |
61
|
|
|
* @var integer |
62
|
|
|
*/ |
63
|
|
|
protected $port = 8125; |
64
|
|
|
|
65
|
|
|
/** |
66
|
|
|
* Last message sent to the server |
67
|
|
|
* |
68
|
|
|
* @var string |
69
|
|
|
*/ |
70
|
|
|
protected $message = ''; |
71
|
|
|
|
72
|
|
|
/** |
73
|
|
|
* Class namespace |
74
|
|
|
* |
75
|
|
|
* @var string |
76
|
|
|
*/ |
77
|
|
|
protected $namespace = ''; |
78
|
|
|
|
79
|
|
|
/** |
80
|
|
|
* Timeout for creating the socket connection |
81
|
|
|
* |
82
|
|
|
* @var null|int |
83
|
|
|
*/ |
84
|
|
|
protected $timeout; |
85
|
|
|
|
86
|
|
|
/** |
87
|
|
|
* Whether or not an exception should be thrown on failed connections |
88
|
|
|
* |
89
|
|
|
* @var bool |
90
|
|
|
*/ |
91
|
|
|
protected $throwExceptions = true; |
92
|
|
|
|
93
|
|
|
/** |
94
|
|
|
* Socket connection |
95
|
|
|
* |
96
|
|
|
* @var resource|null |
97
|
|
|
*/ |
98
|
|
|
protected $socket = null; |
99
|
|
|
|
100
|
|
|
/** |
101
|
|
|
* Metadata for the DataDog event message |
102
|
|
|
* |
103
|
|
|
* @var array - time - Assign a timestamp to the event. |
104
|
|
|
* - hostname - Assign a hostname to the event |
105
|
|
|
* - key - Assign an aggregation key to th event, to group it with some others |
106
|
|
|
* - priority - Can be 'normal' or 'low' |
107
|
|
|
* - source - Assign a source type to the event |
108
|
|
|
* - alert - Can be 'error', 'warning', 'info' or 'success' |
109
|
|
|
*/ |
110
|
|
|
protected $eventMetaData = [ |
111
|
|
|
'time' => 'd', |
112
|
|
|
'hostname' => 'h', |
113
|
|
|
'key' => 'k', |
114
|
|
|
'priority' => 'p', |
115
|
|
|
'source' => 's', |
116
|
|
|
'alert' => 't', |
117
|
|
|
]; |
118
|
|
|
|
119
|
|
|
/** |
120
|
|
|
* @var array - time - Assign a timestamp to the service check |
121
|
|
|
* - hostname - Assign a hostname to the service check |
122
|
|
|
*/ |
123
|
|
|
protected $serviceCheckMetaData = [ |
124
|
|
|
'time' => 'd', |
125
|
|
|
'hostname' => 'h', |
126
|
|
|
]; |
127
|
|
|
|
128
|
|
|
/** |
129
|
|
|
* @var array - message - Assign a message to the service check |
130
|
|
|
*/ |
131
|
|
|
protected $serviceCheckMessage = [ |
132
|
|
|
'message' => 'm', |
133
|
|
|
]; |
134
|
|
|
|
135
|
|
|
/** |
136
|
|
|
* Is the server type DataDog implementation |
137
|
|
|
* |
138
|
1 |
|
* @var bool |
139
|
|
|
*/ |
140
|
1 |
|
protected $dataDog = true; |
141
|
1 |
|
|
142
|
1 |
|
/** |
143
|
1 |
|
* Set of default tags to send to every request |
144
|
|
|
* |
145
|
|
|
* @var array |
146
|
|
|
*/ |
147
|
|
|
protected $tags = []; |
148
|
|
|
|
149
|
|
|
/** |
150
|
|
|
* Singleton Reference |
151
|
45 |
|
* |
152
|
|
|
* @param string $name Instance name |
153
|
45 |
|
* |
154
|
|
|
* @return Client Client instance |
155
|
45 |
|
*/ |
156
|
45 |
|
public static function instance($name = 'default') |
157
|
45 |
|
{ |
158
|
45 |
|
if (!isset(static::$instances[$name])) { |
159
|
|
|
static::$instances[$name] = new static($name); |
160
|
|
|
} |
161
|
|
|
return static::$instances[$name]; |
162
|
|
|
} |
163
|
|
|
|
164
|
|
|
/** |
165
|
2 |
|
* Create a new instance |
166
|
|
|
* |
167
|
2 |
|
* @param string|null $instanceId |
168
|
|
|
*/ |
169
|
|
|
public function __construct($instanceId = null) |
170
|
|
|
{ |
171
|
|
|
$this->instanceId = $instanceId ?: uniqid(); |
172
|
|
|
|
173
|
|
|
if (empty($this->timeout)) { |
174
|
|
|
$this->timeout = (int) ini_get('default_socket_timeout'); |
175
|
|
|
} |
176
|
|
|
} |
177
|
|
|
|
178
|
|
|
/** |
179
|
|
|
* Get string value of instance |
180
|
|
|
* |
181
|
|
|
* @return string String representation of this instance |
182
|
|
|
*/ |
183
|
|
|
public function __toString() |
184
|
|
|
{ |
185
|
45 |
|
return 'DogStatsD\Client::[' . $this->instanceId . ']'; |
186
|
|
|
} |
187
|
|
|
|
188
|
45 |
|
/** |
189
|
15 |
|
* Initialize Connection Details |
190
|
15 |
|
* |
191
|
45 |
|
* @param array $options Configuration options |
192
|
|
|
* :host <string|ip> - host to talk to |
193
|
45 |
|
* :port <int> - Port to communicate with |
194
|
45 |
|
* :namespace <string> - Default namespace |
195
|
45 |
|
* :timeout <int> - Timeout in seconds |
196
|
45 |
|
* :throwExceptions <bool> - Throw an exception on connection error |
197
|
45 |
|
* :dataDog <bool> - Use DataDog's version of statsd (Default: true) |
198
|
45 |
|
* :tags <array> - List of tags to add to each message |
199
|
45 |
|
* |
200
|
|
|
* @return Client This instance |
201
|
45 |
|
* @throws ConfigurationException If port is invalid |
202
|
2 |
|
*/ |
203
|
|
|
public function configure(array $options = []) |
204
|
|
|
{ |
205
|
45 |
|
$setOption = function ($name, $type = null) use ($options) { |
206
|
|
|
if (isset($options[$name])) { |
207
|
|
|
if (!is_null($type) && (gettype($options[$name]) != $type)) { |
208
|
|
|
throw new ConfigurationException($this, sprintf( |
209
|
|
|
"Option: %s is expected to be: '%s', was: '%s'", |
210
|
|
|
$name, |
211
|
|
|
$type, |
212
|
|
|
gettype($options[$name]) |
213
|
1 |
|
)); |
214
|
|
|
} |
215
|
1 |
|
$this->{$name} = $options[$name]; |
216
|
|
|
} |
217
|
|
|
}; |
218
|
|
|
|
219
|
|
|
$setOption('host', 'string'); |
220
|
|
|
$setOption('port', 'integer'); |
221
|
|
|
$setOption('namespace', 'string'); |
222
|
|
|
$setOption('timeout'); |
223
|
2 |
|
$setOption('throwExceptions', 'boolean'); |
224
|
|
|
$setOption('dataDog', 'boolean'); |
225
|
2 |
|
$setOption('tags', 'array'); |
226
|
|
|
|
227
|
|
|
if (!$this->port || !is_numeric($this->port) || $this->port > 65535) { |
228
|
|
|
throw new ConfigurationException($this, 'Option: Port is out of range'); |
229
|
|
|
} |
230
|
|
|
|
231
|
|
|
return $this; |
232
|
|
|
} |
233
|
1 |
|
|
234
|
|
|
/** |
235
|
1 |
|
* Get Host |
236
|
|
|
* |
237
|
|
|
* @return string Host |
238
|
|
|
*/ |
239
|
|
|
public function getHost() |
240
|
|
|
{ |
241
|
|
|
return $this->host; |
242
|
|
|
} |
243
|
31 |
|
|
244
|
|
|
/** |
245
|
31 |
|
* Get Port |
246
|
|
|
* |
247
|
|
|
* @return int Port |
248
|
|
|
*/ |
249
|
|
|
public function getPort() |
250
|
|
|
{ |
251
|
|
|
return $this->port; |
252
|
|
|
} |
253
|
|
|
|
254
|
|
|
/** |
255
|
|
|
* Get Namespace |
256
|
|
|
* |
257
|
|
|
* @return string Namespace |
258
|
14 |
|
*/ |
259
|
|
|
public function getNamespace() |
260
|
14 |
|
{ |
261
|
|
|
return $this->namespace; |
262
|
14 |
|
} |
263
|
14 |
|
|
264
|
1 |
|
/** |
265
|
1 |
|
* Get Last Message |
266
|
1 |
|
* |
267
|
1 |
|
* @return string Last message sent to server |
268
|
1 |
|
*/ |
269
|
1 |
|
public function getLastMessage() |
270
|
13 |
|
{ |
271
|
13 |
|
return $this->message; |
272
|
13 |
|
} |
273
|
|
|
|
274
|
14 |
|
/** |
275
|
|
|
* Increment a metric |
276
|
|
|
* |
277
|
|
|
* @param string|string[] $metrics Metric(s) to increment |
278
|
|
|
* @param int $delta Value to decrement the metric by |
279
|
|
|
* @param float $sampleRate Sample rate of metric |
280
|
|
|
* @param string[] $tags List of tags for this metric |
281
|
|
|
* |
282
|
|
|
* @return Client This instance |
283
|
|
|
*/ |
284
|
|
|
public function increment($metrics, $delta = 1, $sampleRate = 1.0, array $tags = []) |
285
|
|
|
{ |
286
|
|
|
$metrics = is_array($metrics) ? $metrics : [$metrics]; |
287
|
2 |
|
|
288
|
|
|
$data = []; |
289
|
2 |
|
if ($sampleRate < 1.0) { |
290
|
|
|
foreach ($metrics as $metric) { |
291
|
|
View Code Duplication |
if ((mt_rand() / mt_getrandmax()) <= $sampleRate) { |
|
|
|
|
292
|
|
|
$data[$metric] = $delta . '|c|@' . $sampleRate; |
293
|
|
|
} |
294
|
|
|
} |
295
|
|
|
} else { |
296
|
|
|
foreach ($metrics as $metric) { |
297
|
|
|
$data[$metric] = $delta . '|c'; |
298
|
|
|
} |
299
|
|
|
} |
300
|
|
|
return $this->send($data, $tags); |
301
|
3 |
|
} |
302
|
|
|
|
303
|
3 |
|
/** |
304
|
|
|
* Decrement a metric |
305
|
3 |
|
* |
306
|
3 |
|
* @param string|string[] $metrics Metric(s) to decrement |
307
|
|
|
* @param int $delta Value to increment the metric by |
308
|
3 |
|
* @param int $sampleRate Sample rate of metric |
309
|
|
|
* @param string[] $tags List of tags for this metric |
310
|
|
|
* |
311
|
|
|
* @return Client This instance |
312
|
|
|
*/ |
313
|
|
|
public function decrement($metrics, $delta = 1, $sampleRate = 1, array $tags = []) |
314
|
|
|
{ |
315
|
|
|
return $this->increment($metrics, 0 - $delta, $sampleRate, $tags); |
316
|
|
|
} |
317
|
|
|
|
318
|
|
|
/** |
319
|
|
|
* Timing |
320
|
1 |
|
* |
321
|
|
|
* @param string $metric Metric to track |
322
|
1 |
|
* @param float $time Time in milliseconds |
323
|
1 |
|
* @param string[] $tags List of tags for this metric |
324
|
1 |
|
* |
325
|
1 |
|
* @return Client This instance |
326
|
1 |
|
*/ |
327
|
|
|
public function timing($metric, $time, array $tags = []) |
328
|
|
|
{ |
329
|
|
|
return $this->send( |
330
|
|
|
[ |
331
|
|
|
$metric => $time . '|ms', |
332
|
|
|
], |
333
|
|
|
$tags |
334
|
|
|
); |
335
|
|
|
} |
336
|
|
|
|
337
|
|
|
/** |
338
|
|
|
* Time a function |
339
|
2 |
|
* |
340
|
|
|
* @param string $metric Metric to time |
341
|
2 |
|
* @param callable $func Function to record |
342
|
|
|
* @param string[] $tags List of tags for this metric |
343
|
2 |
|
* |
344
|
2 |
|
* @return Client This instance |
345
|
|
|
*/ |
346
|
2 |
|
public function time($metric, callable $func, array $tags = []) |
347
|
|
|
{ |
348
|
|
|
$timerStart = microtime(true); |
349
|
|
|
$func(); |
350
|
|
|
$timerEnd = microtime(true); |
351
|
|
|
$time = round(($timerEnd - $timerStart) * 1000, 4); |
352
|
|
|
return $this->timing($metric, $time, $tags); |
353
|
|
|
} |
354
|
|
|
|
355
|
|
|
/** |
356
|
|
|
* Gauges |
357
|
|
|
* |
358
|
2 |
|
* @param string $metric Metric to gauge |
359
|
|
|
* @param int $value Set the value of the gauge |
360
|
2 |
|
* @param string[] $tags List of tags for this metric |
361
|
|
|
* |
362
|
2 |
|
* @return Client This instance |
363
|
2 |
|
*/ |
364
|
|
|
public function gauge($metric, $value, array $tags = []) |
365
|
2 |
|
{ |
366
|
|
|
return $this->send( |
367
|
|
|
[ |
368
|
|
|
$metric => $value . '|g', |
369
|
|
|
], |
370
|
|
|
$tags |
371
|
|
|
); |
372
|
|
|
} |
373
|
|
|
|
374
|
|
|
/** |
375
|
|
|
* Histogram |
376
|
|
|
* |
377
|
|
|
* @param string $metric Metric to send |
378
|
|
|
* @param float $value Value to send |
379
|
|
|
* @param float $sampleRate Sample rate of metric |
380
|
|
|
* @param string[] $tags List of tags for this metric |
381
|
|
|
* |
382
|
|
|
* @return Client This instance |
383
|
|
|
*/ |
384
|
|
|
public function histogram($metric, $value, $sampleRate = 1.0, array $tags = []) |
385
|
|
|
{ |
386
|
|
|
$data = []; |
387
|
6 |
|
if ($sampleRate < 1.0) { |
388
|
|
View Code Duplication |
if ((mt_rand() / mt_getrandmax()) <= $sampleRate) { |
|
|
|
|
389
|
6 |
|
$data[$metric] = $value . '|h|@' . $sampleRate; |
390
|
1 |
|
} |
391
|
|
|
} else { |
392
|
|
|
$data[$metric] = $value . '|h'; |
393
|
5 |
|
} |
394
|
5 |
|
|
395
|
5 |
|
return $this->send($data, $tags); |
396
|
5 |
|
} |
397
|
|
|
|
398
|
5 |
|
/** |
399
|
2 |
|
* Sets - count the number of unique elements for a group |
400
|
2 |
|
* |
401
|
2 |
|
* @param string $metric |
402
|
5 |
|
* @param int $value |
403
|
|
|
* @param string[] $tags List of tags for this metric |
404
|
5 |
|
* |
405
|
|
|
* @return Client This instance |
406
|
5 |
|
*/ |
407
|
5 |
|
public function set($metric, $value, array $tags = []) |
408
|
5 |
|
{ |
409
|
|
|
return $this->send( |
410
|
|
|
[ |
411
|
|
|
$metric => $value . '|s', |
412
|
|
|
], |
413
|
|
|
$tags |
414
|
|
|
); |
415
|
|
|
} |
416
|
|
|
|
417
|
|
|
/** |
418
|
|
|
* Send a event notification |
419
|
|
|
* |
420
|
|
|
* @link http://docs.datadoghq.com/guides/dogstatsd/#events |
421
|
|
|
* |
422
|
|
|
* @param string $title Event Title |
423
|
|
|
* @param string $text Event Text |
424
|
|
|
* @param array $metadata Set of metadata for this event: |
425
|
|
|
* - time - Assign a timestamp to the event. |
426
|
6 |
|
* - hostname - Assign a hostname to the event |
427
|
|
|
* - key - Assign an aggregation key to th event, to group it with some others |
428
|
6 |
|
* - priority - Can be 'normal' or 'low' |
429
|
1 |
|
* - source - Assign a source type to the event |
430
|
|
|
* - alert - Can be 'error', 'warning', 'info' or 'success' |
431
|
|
|
* @param string[] $tags List of tags for this event |
432
|
5 |
|
* |
433
|
5 |
|
* @return Client This instance |
434
|
|
|
* @throws ConnectionException If there is a connection problem with the host |
435
|
5 |
|
*/ |
436
|
5 |
|
public function event($title, $text, array $metadata = [], array $tags = []) |
437
|
3 |
|
{ |
438
|
3 |
|
if (!$this->dataDog) { |
439
|
3 |
|
return $this; |
440
|
5 |
|
} |
441
|
5 |
|
|
442
|
|
|
$text = str_replace(["\r", "\n"], ['', "\\n"], $text); |
443
|
5 |
|
$metric = sprintf('_e{%d,%d}', strlen($title), strlen($text)); |
444
|
5 |
|
$prefix = $this->namespace ? $this->namespace . '.' : ''; |
445
|
5 |
|
$value = sprintf('%s|%s', $prefix . $title, $text); |
446
|
|
|
|
447
|
5 |
|
foreach ($metadata as $key => $data) { |
448
|
5 |
|
if (isset($this->eventMetaData[$key])) { |
449
|
5 |
|
$value .= sprintf('|%s:%s', $this->eventMetaData[$key], $data); |
450
|
|
|
} |
451
|
|
|
} |
452
|
|
|
|
453
|
|
|
$value .= $this->formatTags($tags); |
454
|
|
|
|
455
|
|
|
return $this->sendMessages([ |
456
|
|
|
sprintf('%s:%s', $metric, $value), |
457
|
31 |
|
]); |
458
|
|
|
} |
459
|
31 |
|
|
460
|
20 |
|
/** |
461
|
|
|
* Service Checks |
462
|
|
|
* |
463
|
11 |
|
* @link http://docs.datadoghq.com/guides/dogstatsd/#service-checks |
464
|
11 |
|
* |
465
|
11 |
|
* @param string $name Name of the service |
466
|
10 |
|
* @param int $status digit corresponding to the status you’re reporting (OK = 0, WARNING = 1, CRITICAL = 2, |
467
|
10 |
|
* UNKNOWN = 3) |
468
|
2 |
|
* @param array $metadata - time - Assign a timestamp to the service check |
469
|
|
|
* - hostname - Assign a hostname to the service check |
470
|
11 |
|
* @param string[] $tags List of tags for this event |
471
|
|
|
* |
472
|
11 |
|
* @return Client This instance |
473
|
|
|
* @throws ConnectionException If there is a connection problem with the host |
474
|
|
|
*/ |
475
|
|
|
public function serviceCheck($name, $status, array $metadata = [], array $tags = []) |
476
|
|
|
{ |
477
|
|
|
if (!$this->dataDog) { |
478
|
|
|
return $this; |
479
|
|
|
} |
480
|
|
|
|
481
|
|
|
$prefix = $this->namespace ? $this->namespace . '.' : ''; |
482
|
|
|
$value = sprintf('_sc|%s|%d', $prefix . $name, $status); |
483
|
|
|
|
484
|
21 |
|
$applyMetadata = function ($metadata, $definition) use (&$value) { |
485
|
|
|
foreach ($metadata as $key => $data) { |
486
|
21 |
|
if (isset($definition[$key])) { |
487
|
21 |
|
$value .= sprintf('|%s:%s', $definition[$key], $data); |
488
|
21 |
|
} |
489
|
21 |
|
} |
490
|
21 |
|
}; |
491
|
21 |
|
|
492
|
21 |
|
$applyMetadata($metadata, $this->serviceCheckMetaData); |
493
|
|
|
$value .= $this->formatTags($tags); |
494
|
|
|
$applyMetadata($metadata, $this->serviceCheckMessage); |
495
|
|
|
|
496
|
|
|
return $this->sendMessages([ |
497
|
|
|
$value, |
498
|
|
|
]); |
499
|
|
|
} |
500
|
|
|
|
501
|
31 |
|
/** |
502
|
|
|
* @param string[] $tags A list of tags to apply to each message |
503
|
31 |
|
* |
504
|
31 |
|
* @return string |
505
|
2 |
|
*/ |
506
|
1 |
|
private function formatTags(array $tags = []) |
507
|
|
|
{ |
508
|
1 |
|
if (!$this->dataDog || count($tags) === 0) { |
509
|
1 |
|
return ''; |
510
|
|
|
} |
511
|
1 |
|
|
512
|
1 |
|
$result = []; |
513
|
|
|
foreach ($tags as $key => $value) { |
514
|
|
|
if (is_numeric($key)) { |
515
|
29 |
|
$result[] = $value; |
516
|
29 |
|
} else { |
517
|
29 |
|
$result[] = sprintf('%s:%s', $key, $value); |
518
|
29 |
|
} |
519
|
|
|
} |
520
|
|
|
|
521
|
|
|
return sprintf('|#%s', implode(',', $result)); |
522
|
|
|
} |
523
|
|
|
|
524
|
|
|
/** |
525
|
|
|
* Send Data to StatsD Server |
526
|
|
|
* |
527
|
|
|
* @param string[] $data A list of messages to send to the server |
528
|
|
|
* @param string[] $tags A list of tags to apply to each message |
529
|
|
|
* |
530
|
|
|
* @return Client This instance |
531
|
|
|
* @throws ConnectionException If there is a connection problem with the host |
532
|
|
|
*/ |
533
|
|
|
protected function send(array $data, array $tags = []) |
534
|
|
|
{ |
535
|
|
|
$messages = []; |
536
|
|
|
$prefix = $this->namespace ? $this->namespace . '.' : ''; |
537
|
|
|
$formattedTags = $this->formatTags(array_merge($this->tags, $tags)); |
538
|
|
|
foreach ($data as $key => $value) { |
539
|
|
|
$messages[] = $prefix . $key . ':' . $value . $formattedTags; |
540
|
|
|
} |
541
|
|
|
return $this->sendMessages($messages); |
542
|
|
|
} |
543
|
|
|
|
544
|
|
|
/** |
545
|
|
|
* @param string[] $messages |
546
|
|
|
* |
547
|
|
|
* @return Client This instance |
548
|
|
|
* @throws ConnectionException If there is a connection problem with the host |
549
|
|
|
*/ |
550
|
|
|
protected function sendMessages(array $messages) |
551
|
|
|
{ |
552
|
|
|
if (is_null($this->socket)) { |
553
|
|
|
$this->socket = $this->connect(); |
554
|
|
|
} |
555
|
|
|
if ($this->socket) { |
556
|
|
|
$this->message = implode("\n", $messages); |
557
|
|
|
if (@fwrite($this->socket, $this->message) === false) { |
558
|
|
|
// attempt to re-send on socket resource failure |
559
|
|
|
$this->socket = $this->connect(); |
560
|
|
|
@fwrite($this->socket, $this->message); |
|
|
|
|
561
|
|
|
} |
562
|
|
|
} |
563
|
|
|
|
564
|
|
|
return $this; |
565
|
|
|
} |
566
|
|
|
|
567
|
|
|
/** |
568
|
|
|
* Creates a persistent connection to the udp host:port |
569
|
|
|
* |
570
|
|
|
* @return resource |
571
|
|
|
*/ |
572
|
|
|
protected function connect() |
573
|
|
|
{ |
574
|
|
|
$socket = @fsockopen('udp://' . $this->host, $this->port, $errno, $errstr, $this->timeout); |
575
|
|
|
if ($socket === false) { |
576
|
|
|
if ($this->throwExceptions) { |
577
|
|
|
throw new ConnectionException($this, '(' . $errno . ') ' . $errstr); |
578
|
|
|
} else { |
579
|
|
|
trigger_error( |
580
|
|
|
sprintf('StatsD server connection failed (udp://%s:%d)', $this->host, $this->port), |
581
|
|
|
E_USER_WARNING |
582
|
|
|
); |
583
|
|
|
} |
584
|
|
|
} |
585
|
|
|
stream_set_timeout($socket, $this->timeout); |
586
|
|
|
return $socket; |
587
|
|
|
} |
588
|
|
|
|
589
|
|
|
public function __destruct() |
590
|
|
|
{ |
591
|
|
|
if ($this->socket) { |
592
|
|
|
fclose($this->socket); |
593
|
|
|
} |
594
|
|
|
} |
595
|
|
|
} |
596
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.