StatsD.php 4.1 KB

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