munin_api.module 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. <?php
  2. // $Id$
  3. /**
  4. * @file
  5. * Munin API for Drupal.
  6. *
  7. * @author Frederic G. MARAND
  8. *
  9. * @copyright (c) 2011 Ouest Systèmes Informatiques
  10. *
  11. * Licensed under the General Public License version 2 or later.
  12. */
  13. define('MUNIN_API_COUNTER', 'COUNTER');
  14. define('MUNIN_API_DERIVE', 'DERIVE');
  15. define('MUNIN_API_GAUGE', 'GAUGE');
  16. define('MUNIN_API_ABSOLUTE', 'ABSOLUTE'); // Counters reset upon reading (uncommon)
  17. define('MUNIN_API_DRAW_AREA', 'AREA');
  18. define('MUNIN_API_DRAW_LINE0', 'LINE0'); // Invisible line, but triggers graphs scaling
  19. define('MUNIN_API_DRAW_LINE1', 'LINE1'); // Default on Munin 2.0
  20. define('MUNIN_API_DRAW_LINE2', 'LINE2'); // Default on Munin < 2.0
  21. define('MUNIN_API_DRAW_LINE3', 'LINE3');
  22. define('MUNIN_API_DRAW_STACK', 'STACK');
  23. // Styles below are only supported on Munin >= 1.3.3
  24. define('MUNIN_API_DRAW_LINESTACK1', 'LINESTACK1');
  25. define('MUNIN_API_DRAW_LINESTACK2', 'LINESTACK2');
  26. define('MUNIN_API_DRAW_LINESTACK3', 'LINESTACK3');
  27. define('MUNIN_API_DRAW_AREASTACK', 'AREASTACK');
  28. /**
  29. * Finalize result pages for Munin interactions.
  30. *
  31. * - text content, not HTML
  32. * - non cacheable, even for anonymous users
  33. */
  34. function _munin_api_page_closure($ret) {
  35. drupal_set_header('Content-type: text/plain');
  36. $GLOBALS['conf']['cache'] = CACHE_DISABLED; // prevent page_set_cache() in drupal_page_footer().
  37. print $ret;
  38. drupal_page_footer();
  39. exit();
  40. }
  41. /**
  42. * Display and log an incorrect hook implementation.
  43. *
  44. * @param string $hook
  45. * @param string $module
  46. *
  47. * @return string
  48. */
  49. function _munin_report_hook_error($hook, $module) {
  50. $message = t('Incorrect implementation of hook_!hook() in module @module.');
  51. $params = array(
  52. '!hook' => $hook,
  53. '@module' => $module,
  54. );
  55. drupal_set_message(strtr($message, $params), 'error');
  56. watchdog('munin_api', $message, $params, WATCHDOG_ERROR);
  57. return '<p>'. l(t('Back'), 'admin/reports/munin_api/'. $module) .'</p>';
  58. }
  59. /**
  60. * Menu access callback for Munin config fetches.
  61. *
  62. * TODO: define rules, then code
  63. */
  64. function munin_api_access_config($module) {
  65. return TRUE; // For now, protect at the web server level
  66. }
  67. /**
  68. * Menu access callback for Munin data fetches.
  69. *
  70. * TODO: define rules, then code
  71. */
  72. function munin_api_access_fetch($module) {
  73. return TRUE; // For now, protect at the web server level
  74. }
  75. function munin_api_menu() {
  76. $items = array();
  77. $items['admin/reports/munin_api'] = array(
  78. 'title' => 'Munin',
  79. 'description' => 'Reports about Munin data collectors and their probes',
  80. 'page callback' => 'munin_api_page_report_global',
  81. 'access arguments' => array('access site reports'),
  82. );
  83. $items['admin/reports/munin_api/list'] = array(
  84. 'type' => MENU_DEFAULT_LOCAL_TASK,
  85. 'title' => 'General',
  86. 'weight' => -1,
  87. );
  88. foreach (module_implements('munin_api_info') as $module_name) {
  89. $module = module_invoke($module_name, 'munin_api_info');
  90. $graphs = element_children($module);
  91. $items['admin/reports/munin_api/'. $module_name] = array(
  92. 'type' => MENU_LOCAL_TASK,
  93. 'title' => $module['#title'],
  94. 'description' => $module['#description'],
  95. 'page callback' => 'munin_api_page_report_instance',
  96. 'page arguments' => array($module_name, $module),
  97. 'access arguments' => array('access site reports'),
  98. );
  99. foreach ($graphs as $graph_name) {
  100. $items['munin_api/'. $graph_name] = array(
  101. 'type' => MENU_CALLBACK,
  102. 'page callback' => 'munin_api_page_fetch',
  103. 'page arguments' => array($module_name, $module, $graph_name),
  104. 'access callback' => 'munin_api_access_fetch',
  105. 'access arguments' => array($module_name, $graph_name),
  106. );
  107. $items['munin_api/'. $graph_name .'/config'] = array(
  108. 'type' => MENU_CALLBACK,
  109. 'page callback' => 'munin_api_page_config',
  110. 'page arguments' => array($module_name, $graph_name),
  111. 'access callback' => 'munin_api_access_config',
  112. 'access arguments' => array($module_name, $graph_name),
  113. );
  114. }
  115. }
  116. ksort($items);
  117. return $items;
  118. }
  119. /**
  120. * Page callback for munin config fetches.
  121. */
  122. function munin_api_page_config($module_name, $graph_name) {
  123. $module_info = module_invoke($module_name, 'munin_api_info');
  124. if (!is_array($module_info)) {
  125. return _munin_report_hook_error('munin_api_info', $module);
  126. }
  127. $info = $module_info[$graph_name];
  128. $config = array(
  129. 'graph_title' => $info['#title'],
  130. 'graph_info' => $info['#info'],
  131. 'graph_category' => 'Drupal',
  132. );
  133. foreach (element_properties($info) as $property_name) {
  134. if (!in_array($property_name, array('#title', '#info'))) {
  135. $config[drupal_substr($property_name, 1)] = $info[$property_name];
  136. }
  137. }
  138. foreach (element_children($info) as $field_name) {
  139. foreach (element_properties($info[$field_name]) as $property_name) {
  140. $config[$field_name .'.'. drupal_substr($property_name, 1)] = $info[$field_name][$property_name];
  141. }
  142. }
  143. $ret = '';
  144. foreach ($config as $k => $v) {
  145. $ret .= $k .' '. $v . PHP_EOL;
  146. }
  147. _munin_api_page_closure($ret);
  148. }
  149. /**
  150. * Page callback for munin data fetches.
  151. */
  152. function munin_api_page_fetch($module_name, $module, $graph_name) {
  153. $data = module_invoke($module_name, 'munin_api_fetch', $graph_name);
  154. if (!is_array($data)) {
  155. return _munin_report_hook_error('munin_api_fetch', $module_name);
  156. }
  157. $ret = '';
  158. foreach ($data as $field => $value) {
  159. $ret .= $field .'.value '. $value . PHP_EOL;
  160. }
  161. _munin_api_page_closure($ret);
  162. }
  163. /**
  164. * Page callback for Munin global report.
  165. *
  166. * @return string
  167. */
  168. function munin_api_page_report_global() {
  169. $header = array(
  170. t('Module'),
  171. t('Graph'),
  172. t('Description'),
  173. t('Fields'),
  174. );
  175. $rows = array();
  176. foreach (module_implements('munin_api_info') as $module_name) {
  177. $info = module_invoke($module_name, 'munin_api_info');
  178. $rows[] = array(
  179. array(
  180. 'data' => l($info['#title'], 'admin/reports/munin_api/'. $module_name),
  181. 'colspan' => 2,
  182. ),
  183. array(
  184. 'colspan' => 2,
  185. 'data' => $info['#description'],
  186. ),
  187. );
  188. foreach (element_children($info) as $name) {
  189. $title = $info[$name]['#title'] ? $info[$name]['#title'] : $name;
  190. $rows[] = array(
  191. '&nbsp;',
  192. $title,
  193. isset($info[$name]['#info']) ? $info[$name]['#info'] : t('&lt;missing&gt;'),
  194. count(element_children($info[$name])),
  195. );
  196. }
  197. }
  198. $ret = theme('table', $header, $rows);
  199. return $ret;
  200. }
  201. /**
  202. * Page callback for Munin instance report.
  203. *
  204. * @return string
  205. */
  206. function munin_api_page_report_instance($module_name, $module_info) {
  207. if (!is_array($module_info)) {
  208. return _munin_report_hook_error('munin_api_info', $module_name);
  209. }
  210. $header = array(
  211. t('Name'),
  212. t('Title / Description'),
  213. t('Type'),
  214. t('Debug'),
  215. );
  216. $error = array('class' => 'error');
  217. $rows = array();
  218. foreach (element_children($module_info) as $graph_name) {
  219. $data = module_invoke($module_name, 'munin_api_fetch', $graph_name);
  220. if (!is_array($data)) {
  221. return _munin_report_hook_error('munin_api_fetch', $module_name);
  222. }
  223. $rows[] = array(
  224. array(
  225. 'data' => $module_info[$graph_name]['#title'] ? $module_info[$graph_name]['#title'] : $graph_name,
  226. 'colspan' => 3,
  227. ),
  228. l(t('config'), 'munin_api/'. $graph_name .'/config'),
  229. );
  230. foreach (element_children($module_info[$graph_name]) as $field_name) {
  231. $rows[] = array(
  232. '&nbsp;',
  233. isset($module_info[$graph_name][$field_name]['#label']) ? $module_info[$graph_name][$field_name]['#label'] : t('&lt;missing&gt;'),
  234. $module_info[$graph_name][$field_name]['#type'],
  235. $data[$field_name],
  236. );
  237. unset($data[$field_name]);
  238. }
  239. foreach ($data as $field_name => $field_value) {
  240. $rows[] = array(
  241. '&nbsp;',
  242. $error + array('data' => $field_name),
  243. $error + array('data' => check_plain('<unconfigured>')),
  244. $error + array('data' => $field_value),
  245. );
  246. }
  247. }
  248. $ret = theme('table', $header, $rows);
  249. return $ret;
  250. }