rrd based system stats
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

223 lines
5.7 KiB

  1. /***************************************************************************
  2. * Copyright (C) 10/2006 by Olaf Rempel *
  3. * razzor@kopf-tisch.de *
  4. * *
  5. * This program is free software; you can redistribute it and/or modify *
  6. * it under the terms of the GNU General Public License as published by *
  7. * the Free Software Foundation; either version 2 of the License, or *
  8. * (at your option) any later version. *
  9. * *
  10. * This program is distributed in the hope that it will be useful, *
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  13. * GNU General Public License for more details. *
  14. * *
  15. * You should have received a copy of the GNU General Public License *
  16. * along with this program; if not, write to the *
  17. * Free Software Foundation, Inc., *
  18. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
  19. ***************************************************************************/
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <stdint.h>
  24. #include <curl/curl.h>
  25. #include "configfile.h"
  26. #include "helper.h"
  27. #include "list.h"
  28. #include "plugins.h"
  29. #include "probe.h"
  30. #define BUFSIZE 8192
  31. struct sammler_plugin plugin;
  32. struct server_entry {
  33. struct list_head list;
  34. CURL *handle;
  35. char *name;
  36. };
  37. static LIST_HEAD(server_list);
  38. static const char *ds_def = {
  39. "DS:total_accesses:COUNTER:90:0:U "
  40. "DS:total_kbytes:COUNTER:90:0:U "
  41. "DS:busy_workers:GAUGE:90:0:U "
  42. "DS:idle_workers:GAUGE:90:0:U "
  43. };
  44. struct stats {
  45. uint64_t total_accesses;
  46. uint64_t total_kbytes;
  47. uint64_t busy_workers;
  48. uint64_t idle_workers;
  49. };
  50. static char *rx_buf;
  51. static int rx_pos;
  52. static const char * get_ds(int ds_id)
  53. {
  54. return ds_def;
  55. }
  56. static size_t curl_callback(void *buffer, size_t size, size_t nmemb, void *userp)
  57. {
  58. size_t realsize = size * nmemb;
  59. // discard data
  60. if (rx_pos + realsize >= BUFSIZE)
  61. return realsize;
  62. memcpy(rx_buf + rx_pos, buffer, realsize);
  63. rx_pos += realsize;
  64. return realsize;
  65. }
  66. static int probe(void)
  67. {
  68. struct server_entry *entry;
  69. list_for_each_entry(entry, &server_list, list) {
  70. rx_pos = 0;
  71. curl_easy_perform(entry->handle);
  72. struct stats stats;
  73. memset(&stats, 0, sizeof(stats));
  74. char *line, *tmp = rx_buf, *tmp2;
  75. while ((line = strtok_r(tmp, "\r\n", &tmp2))) {
  76. char *part[2];
  77. strsplit(line, ":", part, 2);
  78. if (!strcmp(part[0], "Total Accesses"))
  79. stats.total_accesses = atoll(part[1]);
  80. else if (!strcmp(part[0], "Total kBytes"))
  81. stats.total_kbytes = atoll(part[1]);
  82. else if (!strcmp(part[0], "BusyWorkers") || !strcmp(part[0], "BusyServers"))
  83. stats.busy_workers = atoll(part[1]);
  84. else if (!strcmp(part[0], "IdleWorkers") || !strcmp(part[0], "IdleServers"))
  85. stats.idle_workers = atoll(part[1]);
  86. tmp = NULL;
  87. }
  88. char filename[32];
  89. int len = snprintf(filename, sizeof(filename), "apache-%s.rrd", entry->name);
  90. if (len < 0 || len >= sizeof(filename))
  91. continue;
  92. probe_submit(&plugin, filename, 0, "%llu:%llu:%llu:%llu",
  93. stats.total_accesses, stats.total_kbytes,
  94. stats.busy_workers, stats.idle_workers);
  95. }
  96. return 0;
  97. }
  98. static int init_cb(const char *parameter, void *privdata)
  99. {
  100. char *part[4];
  101. int ret = strsplit(parameter, ",", part, 4);
  102. if (ret < 2) {
  103. log_print(LOG_ERROR, "p_apache: parse error (1)");
  104. return -1;
  105. }
  106. struct server_entry *entry = malloc(sizeof(struct server_entry));
  107. if (entry == NULL) {
  108. log_print(LOG_ERROR, "p_apache: out of memory");
  109. return -1;
  110. }
  111. // reference config mem
  112. entry->name = part[0];
  113. entry->handle = curl_easy_init();
  114. if (entry->handle == NULL) {
  115. free(entry);
  116. return -1;
  117. }
  118. ret = curl_easy_setopt(entry->handle, CURLOPT_URL, part[1]);
  119. if (ret != 0) {
  120. log_print(LOG_ERROR, "p_apache: %s", curl_easy_strerror(ret));
  121. curl_easy_cleanup(entry->handle);
  122. free(entry);
  123. return -1;
  124. }
  125. if (part[2] != NULL && part[3] != NULL) {
  126. *(part[3] -1) = ':';
  127. log_print(LOG_INFO, "p_apache: auth: '%s'", part[2]);
  128. ret = curl_easy_setopt(entry->handle, CURLOPT_USERPWD, part[2]);
  129. if (ret != 0) {
  130. log_print(LOG_ERROR, "p_apache: %s", curl_easy_strerror(ret));
  131. curl_easy_cleanup(entry->handle);
  132. free(entry);
  133. return -1;
  134. }
  135. }
  136. ret = curl_easy_setopt(entry->handle, CURLOPT_WRITEFUNCTION, &curl_callback);
  137. if (ret != 0) {
  138. log_print(LOG_ERROR, "p_apache: %s", curl_easy_strerror(ret));
  139. curl_easy_cleanup(entry->handle);
  140. free(entry);
  141. return -1;
  142. }
  143. ret = curl_easy_setopt(entry->handle, CURLOPT_WRITEDATA, entry);
  144. if (ret != 0) {
  145. log_print(LOG_ERROR, "p_apache: %s", curl_easy_strerror(ret));
  146. curl_easy_cleanup(entry->handle);
  147. free(entry);
  148. return -1;
  149. }
  150. log_print(LOG_INFO, "p_apache: added server '%s'", entry->name);
  151. list_add_tail(&entry->list, &server_list);
  152. return 0;
  153. }
  154. static int init(void)
  155. {
  156. rx_buf = malloc(BUFSIZE);
  157. if (rx_buf == NULL) {
  158. log_print(LOG_ERROR, "p_apache: out of memory");
  159. return -1;
  160. }
  161. config_get_strings("p_apache", "server", init_cb, NULL);
  162. return 0;
  163. }
  164. static int fini(void)
  165. {
  166. struct server_entry *entry, *tmp;
  167. list_for_each_entry_safe(entry, tmp, &server_list, list) {
  168. curl_easy_cleanup(entry->handle);
  169. free(entry);
  170. }
  171. free(rx_buf);
  172. return 0;
  173. }
  174. struct sammler_plugin plugin = {
  175. .name = "apache",
  176. .interval = 60,
  177. .init = &init,
  178. .fini = &fini,
  179. .probe = &probe,
  180. .get_ds = &get_ds,
  181. };