StatsD.php 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. <?php
  2. namespace StatsDBundle\Services;
  3. /**
  4. * Sends statistics to the stats daemon over UDP
  5. */
  6. class StatsD
  7. {
  8. public function __construct($config = false){
  9. $this->config = array();
  10. $this->config["enabled"] = true;
  11. $this->config["host"] = "127.0.0.1";
  12. $this->config["port"] = 8125;
  13. if(is_array($config)){
  14. $this->config = $config;
  15. $this->config["enabled"] = true;
  16. }
  17. }
  18. /**
  19. * Sets one or more timing values
  20. *
  21. * @param string|array $stats The metric(s) to set.
  22. * @param float $time The elapsed time (ms) to log
  23. */
  24. public function timing($stats, $time)
  25. {
  26. return $this->updateStats($stats, $time, 1, 'ms');
  27. }
  28. /**
  29. * Sets one or more gauges to a value
  30. *
  31. * @param string|array $stats The metric(s) to set.
  32. * @param float $value The value for the stats.
  33. */
  34. public function gauge($stats, $value)
  35. {
  36. return $this->updateStats($stats, $value, 1, 'g');
  37. }
  38. /**
  39. * A "Set" is a count of unique events.
  40. * This data type acts like a counter, but supports counting
  41. * of unique occurences of values between flushes. The backend
  42. * receives the number of unique events that happened since
  43. * the last flush.
  44. *
  45. * The reference use case involved tracking the number of active
  46. * and logged in users by sending the current userId of a user
  47. * with each request with a key of "uniques" (or similar).
  48. *
  49. * @param string|array $stats The metric(s) to set.
  50. * @param float $value The value for the stats.
  51. */
  52. public function set($stats, $value)
  53. {
  54. return $this->updateStats($stats, $value, 1, 's');
  55. }
  56. /**
  57. * Increments one or more stats counters
  58. *
  59. * @param string|array $stats The metric(s) to increment.
  60. * @param float|1 $sampleRate the rate (0-1) for sampling.
  61. *
  62. * @return boolean
  63. */
  64. public function increment($stats, $sampleRate = 1)
  65. {
  66. return $this->updateStats($stats, 1, $sampleRate, 'c');
  67. }
  68. /**
  69. * Decrements one or more stats counters.
  70. *
  71. * @param string|array $stats The metric(s) to decrement.
  72. * @param float|1 $sampleRate the rate (0-1) for sampling.
  73. *
  74. * @return boolean
  75. */
  76. public function decrement($stats, $sampleRate = 1)
  77. {
  78. $this->updateStats($stats, -1, $sampleRate, 'c');
  79. }
  80. /**
  81. * Updates one or more stats.
  82. *
  83. * @param string|array $stats The metric(s) to update. Should be either a string or array of metrics.
  84. * @param int|1 $delta The amount to increment/decrement each metric by.
  85. * @param float|1 $sampleRate the rate (0-1) for sampling.
  86. * @param string|c $metric The metric type ("c" for count, "ms" for timing, "g" for gauge, "s" for set)
  87. *
  88. * @return boolean
  89. */
  90. public function updateStats($stats, $delta = 1, $sampleRate = 1, $metric = 'c')
  91. {
  92. if (!is_array($stats)) {
  93. $stats = array($stats);
  94. }
  95. $data = array();
  96. foreach ($stats as $stat) {
  97. $data[$stat] = "$delta|$metric";
  98. }
  99. $this->send($data, $sampleRate);
  100. }
  101. /**
  102. * Squirt the metrics over UDP
  103. *
  104. * @param array $data
  105. * @param int $sampleRate
  106. *
  107. * @return void
  108. */
  109. public function send($data, $sampleRate = 1)
  110. {
  111. $config = $this->config;
  112. if (!$config["enabled"]){
  113. return;
  114. }
  115. // sampling
  116. $sampledData = array();
  117. if ($sampleRate < 1) {
  118. foreach ($data as $stat => $value) {
  119. if ((mt_rand() / mt_getrandmax()) <= $sampleRate) {
  120. $sampledData[$stat] = "$value|@$sampleRate";
  121. }
  122. }
  123. } else {
  124. $sampledData = $data;
  125. }
  126. $sampledData = $data;
  127. if (empty($sampledData)) {
  128. return;
  129. }
  130. // Wrap this in a try/catch - failures in any of this should be silently ignored
  131. $count = 1;
  132. // print_r("Total: ".count($sampledData).PHP_EOL);
  133. try {
  134. $host = $config["host"];
  135. $port = $config["port"];
  136. $fp = fsockopen("udp://$host", $port, $errno, $errstr);
  137. if (!$fp) {
  138. return;
  139. }
  140. $count_send = 0;
  141. foreach ($sampledData as $stat => $value) {
  142. // print_r("$count - $stat:$value".PHP_EOL);
  143. $count++;
  144. fwrite($fp, "$stat:$value");
  145. $count_send++;
  146. if($count_send > 250) {
  147. sleep(2);
  148. $count_send = 0;
  149. }
  150. }
  151. fclose($fp);
  152. } catch (Exception $e) {
  153. // print_r($e->getMessage());
  154. }
  155. }
  156. }