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.
 
 
 

224 lines
5.8 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 "linebuffer.h"
  28. #include "list.h"
  29. #include "logging.h"
  30. #include "plugins.h"
  31. #include "probe.h"
  32. #define BUFSIZE 8192
  33. struct sammler_plugin plugin;
  34. struct server_entry {
  35. struct list_head list;
  36. CURL *handle;
  37. char *name;
  38. };
  39. static LIST_HEAD(server_list);
  40. static const char *ds_def = {
  41. "DS:total_accesses:COUNTER:90:0:U "
  42. "DS:total_kbytes:COUNTER:90:0:U "
  43. "DS:busy_workers:GAUGE:90:0:U "
  44. "DS:idle_workers:GAUGE:90:0:U "
  45. };
  46. struct stats {
  47. uint64_t total_accesses;
  48. uint64_t total_kbytes;
  49. uint64_t busy_workers;
  50. uint64_t idle_workers;
  51. };
  52. static struct lbuf * rxbuf;
  53. static const char * get_ds(int ds_id)
  54. {
  55. return ds_def;
  56. }
  57. static size_t curl_callback(void *buffer, size_t size, size_t nmemb, void *userp)
  58. {
  59. size_t realsize = size * nmemb;
  60. lbuf_append(rxbuf, buffer, realsize);
  61. return realsize;
  62. }
  63. static int probe(void)
  64. {
  65. struct server_entry *entry;
  66. list_for_each_entry(entry, &server_list, list) {
  67. lbuf_clear(rxbuf);
  68. int ret = curl_easy_perform(entry->handle);
  69. if (ret != 0) {
  70. log_print(LOG_ERROR, "p_apache: %s", curl_easy_strerror(ret));
  71. continue;
  72. }
  73. struct stats stats;
  74. memset(&stats, 0, sizeof(stats));
  75. char *line;
  76. while ((line = lbuf_gettok(rxbuf, "\r\n")) != NULL) {
  77. char *part[2];
  78. strsplit(line, ":", part, 2);
  79. if (!strcmp(part[0], "Total Accesses"))
  80. stats.total_accesses = atoll(part[1]);
  81. else if (!strcmp(part[0], "Total kBytes"))
  82. stats.total_kbytes = atoll(part[1]);
  83. else if (!strcmp(part[0], "BusyWorkers") || !strcmp(part[0], "BusyServers"))
  84. stats.busy_workers = atoll(part[1]);
  85. else if (!strcmp(part[0], "IdleWorkers") || !strcmp(part[0], "IdleServers"))
  86. stats.idle_workers = atoll(part[1]);
  87. lbuf_freetok(rxbuf);
  88. }
  89. char filename[32];
  90. int len = snprintf(filename, sizeof(filename), "apache-%s.rrd", entry->name);
  91. if (len < 0 || len >= sizeof(filename))
  92. continue;
  93. probe_submit(&plugin, filename, 0, "%llu:%llu:%llu:%llu",
  94. stats.total_accesses, stats.total_kbytes,
  95. stats.busy_workers, stats.idle_workers);
  96. }
  97. return 0;
  98. }
  99. static int init_cb(struct strtoken *tokens, void *privdata)
  100. {
  101. if (tokens->count < 2) {
  102. log_print(LOG_ERROR, "p_apache: parse error");
  103. return -1;
  104. }
  105. struct server_entry *entry = malloc(sizeof(struct server_entry));
  106. if (entry == NULL) {
  107. log_print(LOG_ERROR, "p_apache: out of memory");
  108. return -1;
  109. }
  110. entry->name = strdup(tokens->field[0]);
  111. entry->handle = curl_easy_init();
  112. if (entry->handle == NULL) {
  113. free(entry);
  114. return -1;
  115. }
  116. /* set URL */
  117. int ret = curl_easy_setopt(entry->handle, CURLOPT_URL, tokens->field[1]);
  118. if (ret != 0) {
  119. log_print(LOG_ERROR, "p_apache: %s", curl_easy_strerror(ret));
  120. curl_easy_cleanup(entry->handle);
  121. free(entry);
  122. return -1;
  123. }
  124. if (tokens->field[2] != NULL && tokens->field[3] != NULL) {
  125. *(tokens->field[3] -1) = ':';
  126. log_print(LOG_INFO, "p_apache: auth: '%s'", tokens->field[2]);
  127. /* set username:password */
  128. ret = curl_easy_setopt(entry->handle, CURLOPT_USERPWD, tokens->field[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. rxbuf = lbuf_create(BUFSIZE);
  157. if (rxbuf == NULL) {
  158. log_print(LOG_ERROR, "p_apache: out of memory");
  159. return -1;
  160. }
  161. config_get_strtokens("p_apache", "server", ",", 4, 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->name);
  170. free(entry);
  171. }
  172. lbuf_free(rxbuf);
  173. return 0;
  174. }
  175. struct sammler_plugin plugin = {
  176. .name = "apache",
  177. .interval = 60,
  178. .init = &init,
  179. .fini = &fini,
  180. .probe = &probe,
  181. .get_ds = &get_ds,
  182. };