StatsD.php 4.8 KB

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