StatisticClient.php 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. <?php
  2. /**
  3. *
  4. * 上报接口调用统计信息的客户端 UDP协议
  5. * 用来统计调用量、成功率、耗时、错误码等信息
  6. *
  7. * @author liangl
  8. */
  9. class StatisticClient
  10. {
  11. // udp最大包长 linux:65507 mac:9216
  12. const MAX_UDP_PACKGE_SIZE = 65507;
  13. // char类型能保存的最大数值
  14. const MAX_CHAR_VALUE = 255;
  15. // usigned short 能保存的最大数值
  16. const MAX_UNSIGNED_SHORT_VALUE = 65535;
  17. // 固定包长
  18. const PACKEGE_FIXED_LENGTH = 25;
  19. /**
  20. * [module=>[interface=>time_start, interface=>time_start ...], module=>[interface=>time_start..],..]
  21. * @var array
  22. */
  23. protected static $timeMap = array();
  24. /**
  25. * 模块接口上报消耗时间记时
  26. * @param string $module
  27. * @param string $interface
  28. * @return void
  29. */
  30. public static function tick($module = '', $interface = '')
  31. {
  32. self::$timeMap[$module][$interface] = microtime(true);
  33. }
  34. /**
  35. * 模块接口上报统计
  36. * 格式:
  37. * struct{
  38. * int code, // 返回码
  39. * unsigned int time, // 时间
  40. * float cost_time, // 消耗时间 单位秒 例如1.xxx
  41. * unsigned int source_ip, // 来源ip
  42. * unsigned int target_ip, // 目标ip
  43. * unsigned char success, // 是否成功
  44. * unsigned char module_name_length, // 模块名字长度
  45. * unsigned char interface_name_length,// 接口名字长度
  46. * unsigned short msg_length, // 日志信息长度
  47. * unsigned char[module_name_length] module, // 模块名字
  48. * unsigned char[interface_name_length] interface, // 接口名字
  49. * char[msg_length] msg // 日志内容
  50. * }
  51. * @param string $module 模块名/类名
  52. * @param string $interface 接口名/方法名
  53. * @param int $code 返回码
  54. * @param string $msg 日志内容
  55. * @param bool $success 是否成功
  56. * @param string $ip ip1
  57. * @param string $source_ip ip2
  58. * @return true/false
  59. */
  60. public static function report($module, $interface, $code = 0, $msg = '', $success = true, $source_ip = '', $target_ip = '')
  61. {
  62. if(isset(self::$timeMap[$module][$interface]) && self::$timeMap[$module][$interface] > 0)
  63. {
  64. $time_start = self::$timeMap[$module][$interface];
  65. self::$timeMap[$module][$interface] = 0;
  66. }
  67. else if(isset(self::$timeMap['']['']) && self::$timeMap[''][''] > 0)
  68. {
  69. $time_start = self::$timeMap[''][''];
  70. self::$timeMap[''][''] = 0;
  71. }
  72. else
  73. {
  74. $time_start = microtime(true);
  75. }
  76. if(strlen($module) > self::MAX_CHAR_VALUE)
  77. {
  78. $module = substr($module, 0, self::MAX_CHAR_VALUE);
  79. }
  80. if(strlen($interface) > self::MAX_CHAR_VALUE)
  81. {
  82. $interface = substr($interface, 0, self::MAX_CHAR_VALUE);
  83. }
  84. $module_name_length = strlen($module);
  85. $interface_name_length = strlen($interface);
  86. //花费的时间
  87. $cost_time = microtime(true) - $time_start;
  88. $avalible_size = self::MAX_UDP_PACKGE_SIZE - self::PACKEGE_FIXED_LENGTH - $module_name_length - $interface_name_length;
  89. if(strlen($msg) > $avalible_size)
  90. {
  91. $msg = substr($msg, 0, $avalible_size);
  92. }
  93. $data = pack("iIfIICCCS",
  94. $code,
  95. time(),
  96. $cost_time,
  97. $source_ip ? ip2long($source_ip) : ip2long('127.0.0.1'),
  98. $target_ip ? ip2long($target_ip) : ip2long('127.0.0.1'),
  99. $success ? 1 : 0,
  100. $module_name_length,
  101. $interface_name_length,
  102. strlen($msg)
  103. );
  104. return self::sendData($data.$module.$interface.$msg);
  105. }
  106. /**
  107. * 发送统计数据到监控进程
  108. *
  109. * @param string $bin_data
  110. * @param string $ip
  111. * @param int $port
  112. * @param string $protocol upd/tcp
  113. * @return bool
  114. */
  115. private static function sendData($bin_data, $ip = '127.0.0.1', $port = 2207, $protocol = 'udp')
  116. {
  117. $socket = stream_socket_client("{$protocol}://$ip:{$port}");
  118. if(!$socket)
  119. {
  120. return false;
  121. }
  122. $len = stream_socket_sendto($socket, $bin_data);
  123. return $len == strlen($bin_data);
  124. }
  125. }