Run clang-format after removing ssnprintf
[collectd.git] / src / varnish.c
1 /**
2  * collectd - src/varnish.c
3  * Copyright (C) 2010      Jérôme Renard
4  * Copyright (C) 2010      Marc Fournier
5  * Copyright (C) 2010-2012 Florian Forster
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by the
9  * Free Software Foundation; only version 2 of the License is applicable.
10  *
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
19  *
20  * Authors:
21  *   Jérôme Renard <jerome.renard at gmail.com>
22  *   Marc Fournier <marc.fournier at camptocamp.com>
23  *   Florian octo Forster <octo at collectd.org>
24  **/
25
26 #include "collectd.h"
27
28 #include "common.h"
29 #include "plugin.h"
30
31 #if HAVE_VARNISH_V4
32 #include <vapi/vsc.h>
33 #include <vapi/vsm.h>
34 typedef struct VSC_C_main c_varnish_stats_t;
35 #endif
36
37 #if HAVE_VARNISH_V3
38 #include <varnishapi.h>
39 #include <vsc.h>
40 typedef struct VSC_C_main c_varnish_stats_t;
41 #endif
42
43 #if HAVE_VARNISH_V2
44 #include <varnishapi.h>
45 typedef struct varnish_stats c_varnish_stats_t;
46 #endif
47
48 /* {{{ user_config_s */
49 struct user_config_s {
50   char *instance;
51
52   _Bool collect_cache;
53   _Bool collect_connections;
54   _Bool collect_esi;
55   _Bool collect_backend;
56 #ifdef HAVE_VARNISH_V3
57   _Bool collect_dirdns;
58 #endif
59   _Bool collect_fetch;
60   _Bool collect_hcb;
61   _Bool collect_objects;
62 #if HAVE_VARNISH_V2
63   _Bool collect_purge;
64 #else
65   _Bool collect_ban;
66 #endif
67   _Bool collect_session;
68   _Bool collect_shm;
69   _Bool collect_sms;
70 #if HAVE_VARNISH_V2
71   _Bool collect_sm;
72   _Bool collect_sma;
73 #endif
74   _Bool collect_struct;
75   _Bool collect_totals;
76 #if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
77   _Bool collect_uptime;
78 #endif
79   _Bool collect_vcl;
80   _Bool collect_workers;
81 #if HAVE_VARNISH_V4
82   _Bool collect_vsm;
83 #endif
84 };
85 typedef struct user_config_s user_config_t; /* }}} */
86
87 static _Bool have_instance = 0;
88
89 static int varnish_submit(const char *plugin_instance, /* {{{ */
90                           const char *category, const char *type,
91                           const char *type_instance, value_t value) {
92   value_list_t vl = VALUE_LIST_INIT;
93
94   vl.values = &value;
95   vl.values_len = 1;
96
97   sstrncpy(vl.plugin, "varnish", sizeof(vl.plugin));
98
99   if (plugin_instance == NULL)
100     plugin_instance = "default";
101   snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%s-%s",
102            plugin_instance, category);
103
104   sstrncpy(vl.type, type, sizeof(vl.type));
105
106   if (type_instance != NULL)
107     sstrncpy(vl.type_instance, type_instance, sizeof(vl.type_instance));
108
109   return plugin_dispatch_values(&vl);
110 } /* }}} int varnish_submit */
111
112 static int varnish_submit_gauge(const char *plugin_instance, /* {{{ */
113                                 const char *category, const char *type,
114                                 const char *type_instance,
115                                 uint64_t gauge_value) {
116   return varnish_submit(plugin_instance, category, type, type_instance,
117                         (value_t){
118                             .gauge = (gauge_t)gauge_value,
119                         });
120 } /* }}} int varnish_submit_gauge */
121
122 static int varnish_submit_derive(const char *plugin_instance, /* {{{ */
123                                  const char *category, const char *type,
124                                  const char *type_instance,
125                                  uint64_t derive_value) {
126   return varnish_submit(plugin_instance, category, type, type_instance,
127                         (value_t){
128                             .derive = (derive_t)derive_value,
129                         });
130 } /* }}} int varnish_submit_derive */
131
132 #if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
133 static int varnish_monitor(void *priv,
134                            const struct VSC_point *const pt) /* {{{ */
135 {
136   uint64_t val;
137   const user_config_t *conf;
138   const char *class;
139   const char *name;
140
141   if (pt == NULL)
142     return 0;
143
144   conf = priv;
145
146 #if HAVE_VARNISH_V4
147   class = pt->section->fantom->type;
148   name = pt->desc->name;
149
150   if (strcmp(class, "MAIN") != 0)
151     return 0;
152
153 #elif HAVE_VARNISH_V3
154   class = pt->class;
155   name = pt->name;
156
157   if (strcmp(class, "") != 0)
158     return 0;
159 #endif
160
161   val = *(const volatile uint64_t *)pt->ptr;
162
163   if (conf->collect_cache) {
164     if (strcmp(name, "cache_hit") == 0)
165       return varnish_submit_derive(conf->instance, "cache", "cache_result",
166                                    "hit", val);
167     else if (strcmp(name, "cache_miss") == 0)
168       return varnish_submit_derive(conf->instance, "cache", "cache_result",
169                                    "miss", val);
170     else if (strcmp(name, "cache_hitpass") == 0)
171       return varnish_submit_derive(conf->instance, "cache", "cache_result",
172                                    "hitpass", val);
173   }
174
175   if (conf->collect_connections) {
176     if (strcmp(name, "client_conn") == 0)
177       return varnish_submit_derive(conf->instance, "connections", "connections",
178                                    "accepted", val);
179     else if (strcmp(name, "client_drop") == 0)
180       return varnish_submit_derive(conf->instance, "connections", "connections",
181                                    "dropped", val);
182     else if (strcmp(name, "client_req") == 0)
183       return varnish_submit_derive(conf->instance, "connections", "connections",
184                                    "received", val);
185   }
186
187 #ifdef HAVE_VARNISH_V3
188   if (conf->collect_dirdns) {
189     if (strcmp(name, "dir_dns_lookups") == 0)
190       return varnish_submit_derive(conf->instance, "dirdns", "cache_operation",
191                                    "lookups", val);
192     else if (strcmp(name, "dir_dns_failed") == 0)
193       return varnish_submit_derive(conf->instance, "dirdns", "cache_result",
194                                    "failed", val);
195     else if (strcmp(name, "dir_dns_hit") == 0)
196       return varnish_submit_derive(conf->instance, "dirdns", "cache_result",
197                                    "hits", val);
198     else if (strcmp(name, "dir_dns_cache_full") == 0)
199       return varnish_submit_derive(conf->instance, "dirdns", "cache_result",
200                                    "cache_full", val);
201   }
202 #endif
203
204   if (conf->collect_esi) {
205     if (strcmp(name, "esi_errors") == 0)
206       return varnish_submit_derive(conf->instance, "esi", "total_operations",
207                                    "error", val);
208     else if (strcmp(name, "esi_parse") == 0)
209       return varnish_submit_derive(conf->instance, "esi", "total_operations",
210                                    "parsed", val);
211     else if (strcmp(name, "esi_warnings") == 0)
212       return varnish_submit_derive(conf->instance, "esi", "total_operations",
213                                    "warning", val);
214   }
215
216   if (conf->collect_backend) {
217     if (strcmp(name, "backend_conn") == 0)
218       return varnish_submit_derive(conf->instance, "backend", "connections",
219                                    "success", val);
220     else if (strcmp(name, "backend_unhealthy") == 0)
221       return varnish_submit_derive(conf->instance, "backend", "connections",
222                                    "not-attempted", val);
223     else if (strcmp(name, "backend_busy") == 0)
224       return varnish_submit_derive(conf->instance, "backend", "connections",
225                                    "too-many", val);
226     else if (strcmp(name, "backend_fail") == 0)
227       return varnish_submit_derive(conf->instance, "backend", "connections",
228                                    "failures", val);
229     else if (strcmp(name, "backend_reuse") == 0)
230       return varnish_submit_derive(conf->instance, "backend", "connections",
231                                    "reuses", val);
232     else if (strcmp(name, "backend_toolate") == 0)
233       return varnish_submit_derive(conf->instance, "backend", "connections",
234                                    "was-closed", val);
235     else if (strcmp(name, "backend_recycle") == 0)
236       return varnish_submit_derive(conf->instance, "backend", "connections",
237                                    "recycled", val);
238     else if (strcmp(name, "backend_unused") == 0)
239       return varnish_submit_derive(conf->instance, "backend", "connections",
240                                    "unused", val);
241     else if (strcmp(name, "backend_retry") == 0)
242       return varnish_submit_derive(conf->instance, "backend", "connections",
243                                    "retries", val);
244     else if (strcmp(name, "backend_req") == 0)
245       return varnish_submit_derive(conf->instance, "backend", "http_requests",
246                                    "requests", val);
247     else if (strcmp(name, "n_backend") == 0)
248       return varnish_submit_gauge(conf->instance, "backend", "backends",
249                                   "n_backends", val);
250   }
251
252   if (conf->collect_fetch) {
253     if (strcmp(name, "fetch_head") == 0)
254       return varnish_submit_derive(conf->instance, "fetch", "http_requests",
255                                    "head", val);
256     else if (strcmp(name, "fetch_length") == 0)
257       return varnish_submit_derive(conf->instance, "fetch", "http_requests",
258                                    "length", val);
259     else if (strcmp(name, "fetch_chunked") == 0)
260       return varnish_submit_derive(conf->instance, "fetch", "http_requests",
261                                    "chunked", val);
262     else if (strcmp(name, "fetch_eof") == 0)
263       return varnish_submit_derive(conf->instance, "fetch", "http_requests",
264                                    "eof", val);
265     else if (strcmp(name, "fetch_bad") == 0)
266       return varnish_submit_derive(conf->instance, "fetch", "http_requests",
267                                    "bad_headers", val);
268     else if (strcmp(name, "fetch_close") == 0)
269       return varnish_submit_derive(conf->instance, "fetch", "http_requests",
270                                    "close", val);
271     else if (strcmp(name, "fetch_oldhttp") == 0)
272       return varnish_submit_derive(conf->instance, "fetch", "http_requests",
273                                    "oldhttp", val);
274     else if (strcmp(name, "fetch_zero") == 0)
275       return varnish_submit_derive(conf->instance, "fetch", "http_requests",
276                                    "zero", val);
277     else if (strcmp(name, "fetch_failed") == 0)
278       return varnish_submit_derive(conf->instance, "fetch", "http_requests",
279                                    "failed", val);
280     else if (strcmp(name, "fetch_1xx") == 0)
281       return varnish_submit_derive(conf->instance, "fetch", "http_requests",
282                                    "no_body_1xx", val);
283     else if (strcmp(name, "fetch_204") == 0)
284       return varnish_submit_derive(conf->instance, "fetch", "http_requests",
285                                    "no_body_204", val);
286     else if (strcmp(name, "fetch_304") == 0)
287       return varnish_submit_derive(conf->instance, "fetch", "http_requests",
288                                    "no_body_304", val);
289   }
290
291   if (conf->collect_hcb) {
292     if (strcmp(name, "hcb_nolock") == 0)
293       return varnish_submit_derive(conf->instance, "hcb", "cache_operation",
294                                    "lookup_nolock", val);
295     else if (strcmp(name, "hcb_lock") == 0)
296       return varnish_submit_derive(conf->instance, "hcb", "cache_operation",
297                                    "lookup_lock", val);
298     else if (strcmp(name, "hcb_insert") == 0)
299       return varnish_submit_derive(conf->instance, "hcb", "cache_operation",
300                                    "insert", val);
301   }
302
303   if (conf->collect_objects) {
304     if (strcmp(name, "n_expired") == 0)
305       return varnish_submit_derive(conf->instance, "objects", "total_objects",
306                                    "expired", val);
307     else if (strcmp(name, "n_lru_nuked") == 0)
308       return varnish_submit_derive(conf->instance, "objects", "total_objects",
309                                    "lru_nuked", val);
310     else if (strcmp(name, "n_lru_saved") == 0)
311       return varnish_submit_derive(conf->instance, "objects", "total_objects",
312                                    "lru_saved", val);
313     else if (strcmp(name, "n_lru_moved") == 0)
314       return varnish_submit_derive(conf->instance, "objects", "total_objects",
315                                    "lru_moved", val);
316     else if (strcmp(name, "n_deathrow") == 0)
317       return varnish_submit_derive(conf->instance, "objects", "total_objects",
318                                    "deathrow", val);
319     else if (strcmp(name, "losthdr") == 0)
320       return varnish_submit_derive(conf->instance, "objects", "total_objects",
321                                    "header_overflow", val);
322     else if (strcmp(name, "n_obj_purged") == 0)
323       return varnish_submit_derive(conf->instance, "objects", "total_objects",
324                                    "purged", val);
325     else if (strcmp(name, "n_objsendfile") == 0)
326       return varnish_submit_derive(conf->instance, "objects", "total_objects",
327                                    "sent_sendfile", val);
328     else if (strcmp(name, "n_objwrite") == 0)
329       return varnish_submit_derive(conf->instance, "objects", "total_objects",
330                                    "sent_write", val);
331     else if (strcmp(name, "n_objoverflow") == 0)
332       return varnish_submit_derive(conf->instance, "objects", "total_objects",
333                                    "workspace_overflow", val);
334   }
335
336 #if HAVE_VARNISH_V3
337   if (conf->collect_ban) {
338     if (strcmp(name, "n_ban") == 0)
339       return varnish_submit_derive(conf->instance, "ban", "total_operations",
340                                    "total", val);
341     else if (strcmp(name, "n_ban_add") == 0)
342       return varnish_submit_derive(conf->instance, "ban", "total_operations",
343                                    "added", val);
344     else if (strcmp(name, "n_ban_retire") == 0)
345       return varnish_submit_derive(conf->instance, "ban", "total_operations",
346                                    "deleted", val);
347     else if (strcmp(name, "n_ban_obj_test") == 0)
348       return varnish_submit_derive(conf->instance, "ban", "total_operations",
349                                    "objects_tested", val);
350     else if (strcmp(name, "n_ban_re_test") == 0)
351       return varnish_submit_derive(conf->instance, "ban", "total_operations",
352                                    "regexps_tested", val);
353     else if (strcmp(name, "n_ban_dups") == 0)
354       return varnish_submit_derive(conf->instance, "ban", "total_operations",
355                                    "duplicate", val);
356   }
357 #endif
358 #if HAVE_VARNISH_V4
359   if (conf->collect_ban) {
360     if (strcmp(name, "bans") == 0)
361       return varnish_submit_derive(conf->instance, "ban", "total_operations",
362                                    "total", val);
363     else if (strcmp(name, "bans_added") == 0)
364       return varnish_submit_derive(conf->instance, "ban", "total_operations",
365                                    "added", val);
366     else if (strcmp(name, "bans_obj") == 0)
367       return varnish_submit_derive(conf->instance, "ban", "total_operations",
368                                    "obj", val);
369     else if (strcmp(name, "bans_req") == 0)
370       return varnish_submit_derive(conf->instance, "ban", "total_operations",
371                                    "req", val);
372     else if (strcmp(name, "bans_completed") == 0)
373       return varnish_submit_derive(conf->instance, "ban", "total_operations",
374                                    "completed", val);
375     else if (strcmp(name, "bans_deleted") == 0)
376       return varnish_submit_derive(conf->instance, "ban", "total_operations",
377                                    "deleted", val);
378     else if (strcmp(name, "bans_tested") == 0)
379       return varnish_submit_derive(conf->instance, "ban", "total_operations",
380                                    "tested", val);
381     else if (strcmp(name, "bans_dups") == 0)
382       return varnish_submit_derive(conf->instance, "ban", "total_operations",
383                                    "duplicate", val);
384   }
385 #endif
386
387   if (conf->collect_session) {
388     if (strcmp(name, "sess_closed") == 0)
389       return varnish_submit_derive(conf->instance, "session",
390                                    "total_operations", "closed", val);
391     else if (strcmp(name, "sess_pipeline") == 0)
392       return varnish_submit_derive(conf->instance, "session",
393                                    "total_operations", "pipeline", val);
394     else if (strcmp(name, "sess_readahead") == 0)
395       return varnish_submit_derive(conf->instance, "session",
396                                    "total_operations", "readahead", val);
397     else if (strcmp(name, "sess_conn") == 0)
398       return varnish_submit_derive(conf->instance, "session",
399                                    "total_operations", "accepted", val);
400     else if (strcmp(name, "sess_drop") == 0)
401       return varnish_submit_derive(conf->instance, "session",
402                                    "total_operations", "dropped", val);
403     else if (strcmp(name, "sess_fail") == 0)
404       return varnish_submit_derive(conf->instance, "session",
405                                    "total_operations", "failed", val);
406     else if (strcmp(name, "sess_pipe_overflow") == 0)
407       return varnish_submit_derive(conf->instance, "session",
408                                    "total_operations", "overflow", val);
409     else if (strcmp(name, "sess_queued") == 0)
410       return varnish_submit_derive(conf->instance, "session",
411                                    "total_operations", "queued", val);
412     else if (strcmp(name, "sess_linger") == 0)
413       return varnish_submit_derive(conf->instance, "session",
414                                    "total_operations", "linger", val);
415     else if (strcmp(name, "sess_herd") == 0)
416       return varnish_submit_derive(conf->instance, "session",
417                                    "total_operations", "herd", val);
418   }
419
420   if (conf->collect_shm) {
421     if (strcmp(name, "shm_records") == 0)
422       return varnish_submit_derive(conf->instance, "shm", "total_operations",
423                                    "records", val);
424     else if (strcmp(name, "shm_writes") == 0)
425       return varnish_submit_derive(conf->instance, "shm", "total_operations",
426                                    "writes", val);
427     else if (strcmp(name, "shm_flushes") == 0)
428       return varnish_submit_derive(conf->instance, "shm", "total_operations",
429                                    "flushes", val);
430     else if (strcmp(name, "shm_cont") == 0)
431       return varnish_submit_derive(conf->instance, "shm", "total_operations",
432                                    "contention", val);
433     else if (strcmp(name, "shm_cycles") == 0)
434       return varnish_submit_derive(conf->instance, "shm", "total_operations",
435                                    "cycles", val);
436   }
437
438   if (conf->collect_sms) {
439     if (strcmp(name, "sms_nreq") == 0)
440       return varnish_submit_derive(conf->instance, "sms", "total_requests",
441                                    "allocator", val);
442     else if (strcmp(name, "sms_nobj") == 0)
443       return varnish_submit_gauge(conf->instance, "sms", "requests",
444                                   "outstanding", val);
445     else if (strcmp(name, "sms_nbytes") == 0)
446       return varnish_submit_gauge(conf->instance, "sms", "bytes", "outstanding",
447                                   val);
448     else if (strcmp(name, "sms_balloc") == 0)
449       return varnish_submit_derive(conf->instance, "sms", "total_bytes",
450                                    "allocated", val);
451     else if (strcmp(name, "sms_bfree") == 0)
452       return varnish_submit_derive(conf->instance, "sms", "total_bytes", "free",
453                                    val);
454   }
455
456   if (conf->collect_struct) {
457     if (strcmp(name, "n_sess_mem") == 0)
458       return varnish_submit_gauge(conf->instance, "struct", "current_sessions",
459                                   "sess_mem", val);
460     else if (strcmp(name, "n_sess") == 0)
461       return varnish_submit_gauge(conf->instance, "struct", "current_sessions",
462                                   "sess", val);
463     else if (strcmp(name, "n_object") == 0)
464       return varnish_submit_gauge(conf->instance, "struct", "objects", "object",
465                                   val);
466     else if (strcmp(name, "n_vampireobject") == 0)
467       return varnish_submit_gauge(conf->instance, "struct", "objects",
468                                   "vampireobject", val);
469     else if (strcmp(name, "n_objectcore") == 0)
470       return varnish_submit_gauge(conf->instance, "struct", "objects",
471                                   "objectcore", val);
472     else if (strcmp(name, "n_waitinglist") == 0)
473       return varnish_submit_gauge(conf->instance, "struct", "objects",
474                                   "waitinglist", val);
475     else if (strcmp(name, "n_objecthead") == 0)
476       return varnish_submit_gauge(conf->instance, "struct", "objects",
477                                   "objecthead", val);
478     else if (strcmp(name, "n_smf") == 0)
479       return varnish_submit_gauge(conf->instance, "struct", "objects", "smf",
480                                   val);
481     else if (strcmp(name, "n_smf_frag") == 0)
482       return varnish_submit_gauge(conf->instance, "struct", "objects",
483                                   "smf_frag", val);
484     else if (strcmp(name, "n_smf_large") == 0)
485       return varnish_submit_gauge(conf->instance, "struct", "objects",
486                                   "smf_large", val);
487     else if (strcmp(name, "n_vbe_conn") == 0)
488       return varnish_submit_gauge(conf->instance, "struct", "objects",
489                                   "vbe_conn", val);
490   }
491
492   if (conf->collect_totals) {
493     if (strcmp(name, "s_sess") == 0)
494       return varnish_submit_derive(conf->instance, "totals", "total_sessions",
495                                    "sessions", val);
496     else if (strcmp(name, "s_req") == 0)
497       return varnish_submit_derive(conf->instance, "totals", "total_requests",
498                                    "requests", val);
499     else if (strcmp(name, "s_pipe") == 0)
500       return varnish_submit_derive(conf->instance, "totals", "total_operations",
501                                    "pipe", val);
502     else if (strcmp(name, "s_pass") == 0)
503       return varnish_submit_derive(conf->instance, "totals", "total_operations",
504                                    "pass", val);
505     else if (strcmp(name, "s_fetch") == 0)
506       return varnish_submit_derive(conf->instance, "totals", "total_operations",
507                                    "fetches", val);
508     else if (strcmp(name, "s_synth") == 0)
509       return varnish_submit_derive(conf->instance, "totals", "total_bytes",
510                                    "synth", val);
511     else if (strcmp(name, "s_req_hdrbytes") == 0)
512       return varnish_submit_derive(conf->instance, "totals", "total_bytes",
513                                    "req_header", val);
514     else if (strcmp(name, "s_req_bodybytes") == 0)
515       return varnish_submit_derive(conf->instance, "totals", "total_bytes",
516                                    "req_body", val);
517     else if (strcmp(name, "s_resp_hdrbytes") == 0)
518       return varnish_submit_derive(conf->instance, "totals", "total_bytes",
519                                    "resp_header", val);
520     else if (strcmp(name, "s_resp_bodybytes") == 0)
521       return varnish_submit_derive(conf->instance, "totals", "total_bytes",
522                                    "resp_body", val);
523     else if (strcmp(name, "s_pipe_hdrbytes") == 0)
524       return varnish_submit_derive(conf->instance, "totals", "total_bytes",
525                                    "pipe_header", val);
526     else if (strcmp(name, "s_pipe_in") == 0)
527       return varnish_submit_derive(conf->instance, "totals", "total_bytes",
528                                    "pipe_in", val);
529     else if (strcmp(name, "s_pipe_out") == 0)
530       return varnish_submit_derive(conf->instance, "totals", "total_bytes",
531                                    "pipe_out", val);
532     else if (strcmp(name, "n_purges") == 0)
533       return varnish_submit_derive(conf->instance, "totals", "total_operations",
534                                    "purges", val);
535     else if (strcmp(name, "s_hdrbytes") == 0)
536       return varnish_submit_derive(conf->instance, "totals", "total_bytes",
537                                    "header-bytes", val);
538     else if (strcmp(name, "s_bodybytes") == 0)
539       return varnish_submit_derive(conf->instance, "totals", "total_bytes",
540                                    "body-bytes", val);
541     else if (strcmp(name, "n_gzip") == 0)
542       return varnish_submit_derive(conf->instance, "totals", "total_operations",
543                                    "gzip", val);
544     else if (strcmp(name, "n_gunzip") == 0)
545       return varnish_submit_derive(conf->instance, "totals", "total_operations",
546                                    "gunzip", val);
547   }
548
549   if (conf->collect_uptime) {
550     if (strcmp(name, "uptime") == 0)
551       return varnish_submit_gauge(conf->instance, "uptime", "uptime",
552                                   "client_uptime", val);
553   }
554
555   if (conf->collect_vcl) {
556     if (strcmp(name, "n_vcl") == 0)
557       return varnish_submit_gauge(conf->instance, "vcl", "vcl", "total_vcl",
558                                   val);
559     else if (strcmp(name, "n_vcl_avail") == 0)
560       return varnish_submit_gauge(conf->instance, "vcl", "vcl", "avail_vcl",
561                                   val);
562     else if (strcmp(name, "n_vcl_discard") == 0)
563       return varnish_submit_gauge(conf->instance, "vcl", "vcl", "discarded_vcl",
564                                   val);
565     else if (strcmp(name, "vmods") == 0)
566       return varnish_submit_gauge(conf->instance, "vcl", "objects", "vmod",
567                                   val);
568   }
569
570   if (conf->collect_workers) {
571     if (strcmp(name, "threads") == 0)
572       return varnish_submit_gauge(conf->instance, "workers", "threads",
573                                   "worker", val);
574     else if (strcmp(name, "threads_created") == 0)
575       return varnish_submit_derive(conf->instance, "workers", "total_threads",
576                                    "created", val);
577     else if (strcmp(name, "threads_failed") == 0)
578       return varnish_submit_derive(conf->instance, "workers", "total_threads",
579                                    "failed", val);
580     else if (strcmp(name, "threads_limited") == 0)
581       return varnish_submit_derive(conf->instance, "workers", "total_threads",
582                                    "limited", val);
583     else if (strcmp(name, "threads_destroyed") == 0)
584       return varnish_submit_derive(conf->instance, "workers", "total_threads",
585                                    "dropped", val);
586     else if (strcmp(name, "thread_queue_len") == 0)
587       return varnish_submit_derive(conf->instance, "workers", "queue_length",
588                                    "threads", val);
589     else if (strcmp(name, "n_wrk") == 0)
590       return varnish_submit_gauge(conf->instance, "workers", "threads",
591                                   "worker", val);
592     else if (strcmp(name, "n_wrk_create") == 0)
593       return varnish_submit_derive(conf->instance, "workers", "total_threads",
594                                    "created", val);
595     else if (strcmp(name, "n_wrk_failed") == 0)
596       return varnish_submit_derive(conf->instance, "workers", "total_threads",
597                                    "failed", val);
598     else if (strcmp(name, "n_wrk_max") == 0)
599       return varnish_submit_derive(conf->instance, "workers", "total_threads",
600                                    "limited", val);
601     else if (strcmp(name, "n_wrk_drop") == 0)
602       return varnish_submit_derive(conf->instance, "workers", "total_threads",
603                                    "dropped", val);
604     else if (strcmp(name, "n_wrk_queue") == 0)
605       return varnish_submit_derive(conf->instance, "workers", "total_requests",
606                                    "queued", val);
607     else if (strcmp(name, "n_wrk_overflow") == 0)
608       return varnish_submit_derive(conf->instance, "workers", "total_requests",
609                                    "overflowed", val);
610     else if (strcmp(name, "n_wrk_queued") == 0)
611       return varnish_submit_derive(conf->instance, "workers", "total_requests",
612                                    "queued", val);
613     else if (strcmp(name, "n_wrk_lqueue") == 0)
614       return varnish_submit_derive(conf->instance, "workers", "total_requests",
615                                    "queue_length", val);
616   }
617
618 #if HAVE_VARNISH_V4
619   if (conf->collect_vsm) {
620     if (strcmp(name, "vsm_free") == 0)
621       return varnish_submit_gauge(conf->instance, "vsm", "bytes", "free", val);
622     else if (strcmp(name, "vsm_used") == 0)
623       return varnish_submit_gauge(conf->instance, "vsm", "bytes", "used", val);
624     else if (strcmp(name, "vsm_cooling") == 0)
625       return varnish_submit_gauge(conf->instance, "vsm", "bytes", "cooling",
626                                   val);
627     else if (strcmp(name, "vsm_overflow") == 0)
628       return varnish_submit_gauge(conf->instance, "vsm", "bytes", "overflow",
629                                   val);
630     else if (strcmp(name, "vsm_overflowed") == 0)
631       return varnish_submit_derive(conf->instance, "vsm", "total_bytes",
632                                    "overflowed", val);
633   }
634 #endif
635
636   return 0;
637
638 } /* }}} static int varnish_monitor */
639 #else /* if HAVE_VARNISH_V2 */
640 static void varnish_monitor(const user_config_t *conf, /* {{{ */
641                             const c_varnish_stats_t *stats) {
642   if (conf->collect_cache) {
643     /* Cache hits */
644     varnish_submit_derive(conf->instance, "cache", "cache_result", "hit",
645                           stats->cache_hit);
646     /* Cache misses */
647     varnish_submit_derive(conf->instance, "cache", "cache_result", "miss",
648                           stats->cache_miss);
649     /* Cache hits for pass */
650     varnish_submit_derive(conf->instance, "cache", "cache_result", "hitpass",
651                           stats->cache_hitpass);
652   }
653
654   if (conf->collect_connections) {
655     /* Client connections accepted */
656     varnish_submit_derive(conf->instance, "connections", "connections",
657                           "accepted", stats->client_conn);
658     /* Connection dropped, no sess */
659     varnish_submit_derive(conf->instance, "connections", "connections",
660                           "dropped", stats->client_drop);
661     /* Client requests received    */
662     varnish_submit_derive(conf->instance, "connections", "connections",
663                           "received", stats->client_req);
664   }
665
666   if (conf->collect_esi) {
667     /* ESI parse errors (unlock)   */
668     varnish_submit_derive(conf->instance, "esi", "total_operations", "error",
669                           stats->esi_errors);
670     /* Objects ESI parsed (unlock) */
671     varnish_submit_derive(conf->instance, "esi", "total_operations", "parsed",
672                           stats->esi_parse);
673   }
674
675   if (conf->collect_backend) {
676     /* Backend conn. success       */
677     varnish_submit_derive(conf->instance, "backend", "connections", "success",
678                           stats->backend_conn);
679     /* Backend conn. not attempted */
680     varnish_submit_derive(conf->instance, "backend", "connections",
681                           "not-attempted", stats->backend_unhealthy);
682     /* Backend conn. too many      */
683     varnish_submit_derive(conf->instance, "backend", "connections", "too-many",
684                           stats->backend_busy);
685     /* Backend conn. failures      */
686     varnish_submit_derive(conf->instance, "backend", "connections", "failures",
687                           stats->backend_fail);
688     /* Backend conn. reuses        */
689     varnish_submit_derive(conf->instance, "backend", "connections", "reuses",
690                           stats->backend_reuse);
691     /* Backend conn. was closed    */
692     varnish_submit_derive(conf->instance, "backend", "connections",
693                           "was-closed", stats->backend_toolate);
694     /* Backend conn. recycles      */
695     varnish_submit_derive(conf->instance, "backend", "connections", "recycled",
696                           stats->backend_recycle);
697     /* Backend conn. unused        */
698     varnish_submit_derive(conf->instance, "backend", "connections", "unused",
699                           stats->backend_unused);
700     /* Backend requests mades      */
701     varnish_submit_derive(conf->instance, "backend", "http_requests",
702                           "requests", stats->backend_req);
703     /* N backends                  */
704     varnish_submit_gauge(conf->instance, "backend", "backends", "n_backends",
705                          stats->n_backend);
706   }
707
708   if (conf->collect_fetch) {
709     /* Fetch head                */
710     varnish_submit_derive(conf->instance, "fetch", "http_requests", "head",
711                           stats->fetch_head);
712     /* Fetch with length         */
713     varnish_submit_derive(conf->instance, "fetch", "http_requests", "length",
714                           stats->fetch_length);
715     /* Fetch chunked             */
716     varnish_submit_derive(conf->instance, "fetch", "http_requests", "chunked",
717                           stats->fetch_chunked);
718     /* Fetch EOF                 */
719     varnish_submit_derive(conf->instance, "fetch", "http_requests", "eof",
720                           stats->fetch_eof);
721     /* Fetch bad headers         */
722     varnish_submit_derive(conf->instance, "fetch", "http_requests",
723                           "bad_headers", stats->fetch_bad);
724     /* Fetch wanted close        */
725     varnish_submit_derive(conf->instance, "fetch", "http_requests", "close",
726                           stats->fetch_close);
727     /* Fetch pre HTTP/1.1 closed */
728     varnish_submit_derive(conf->instance, "fetch", "http_requests", "oldhttp",
729                           stats->fetch_oldhttp);
730     /* Fetch zero len            */
731     varnish_submit_derive(conf->instance, "fetch", "http_requests", "zero",
732                           stats->fetch_zero);
733     /* Fetch failed              */
734     varnish_submit_derive(conf->instance, "fetch", "http_requests", "failed",
735                           stats->fetch_failed);
736   }
737
738   if (conf->collect_hcb) {
739     /* HCB Lookups without lock */
740     varnish_submit_derive(conf->instance, "hcb", "cache_operation",
741                           "lookup_nolock", stats->hcb_nolock);
742     /* HCB Lookups with lock    */
743     varnish_submit_derive(conf->instance, "hcb", "cache_operation",
744                           "lookup_lock", stats->hcb_lock);
745     /* HCB Inserts              */
746     varnish_submit_derive(conf->instance, "hcb", "cache_operation", "insert",
747                           stats->hcb_insert);
748   }
749
750   if (conf->collect_objects) {
751     /* N expired objects             */
752     varnish_submit_derive(conf->instance, "objects", "total_objects", "expired",
753                           stats->n_expired);
754     /* N LRU nuked objects           */
755     varnish_submit_derive(conf->instance, "objects", "total_objects",
756                           "lru_nuked", stats->n_lru_nuked);
757     /* N LRU saved objects           */
758     varnish_submit_derive(conf->instance, "objects", "total_objects",
759                           "lru_saved", stats->n_lru_saved);
760     /* N LRU moved objects           */
761     varnish_submit_derive(conf->instance, "objects", "total_objects",
762                           "lru_moved", stats->n_lru_moved);
763     /* N objects on deathrow         */
764     varnish_submit_derive(conf->instance, "objects", "total_objects",
765                           "deathrow", stats->n_deathrow);
766     /* HTTP header overflows         */
767     varnish_submit_derive(conf->instance, "objects", "total_objects",
768                           "header_overflow", stats->losthdr);
769     /* Objects sent with sendfile    */
770     varnish_submit_derive(conf->instance, "objects", "total_objects",
771                           "sent_sendfile", stats->n_objsendfile);
772     /* Objects sent with write       */
773     varnish_submit_derive(conf->instance, "objects", "total_objects",
774                           "sent_write", stats->n_objwrite);
775     /* Objects overflowing workspace */
776     varnish_submit_derive(conf->instance, "objects", "total_objects",
777                           "workspace_overflow", stats->n_objoverflow);
778   }
779
780   if (conf->collect_purge) {
781     /* N total active purges      */
782     varnish_submit_derive(conf->instance, "purge", "total_operations", "total",
783                           stats->n_purge);
784     /* N new purges added         */
785     varnish_submit_derive(conf->instance, "purge", "total_operations", "added",
786                           stats->n_purge_add);
787     /* N old purges deleted       */
788     varnish_submit_derive(conf->instance, "purge", "total_operations",
789                           "deleted", stats->n_purge_retire);
790     /* N objects tested           */
791     varnish_submit_derive(conf->instance, "purge", "total_operations",
792                           "objects_tested", stats->n_purge_obj_test);
793     /* N regexps tested against   */
794     varnish_submit_derive(conf->instance, "purge", "total_operations",
795                           "regexps_tested", stats->n_purge_re_test);
796     /* N duplicate purges removed */
797     varnish_submit_derive(conf->instance, "purge", "total_operations",
798                           "duplicate", stats->n_purge_dups);
799   }
800
801   if (conf->collect_session) {
802     /* Session Closed     */
803     varnish_submit_derive(conf->instance, "session", "total_operations",
804                           "closed", stats->sess_closed);
805     /* Session Pipeline   */
806     varnish_submit_derive(conf->instance, "session", "total_operations",
807                           "pipeline", stats->sess_pipeline);
808     /* Session Read Ahead */
809     varnish_submit_derive(conf->instance, "session", "total_operations",
810                           "readahead", stats->sess_readahead);
811     /* Session Linger     */
812     varnish_submit_derive(conf->instance, "session", "total_operations",
813                           "linger", stats->sess_linger);
814     /* Session herd       */
815     varnish_submit_derive(conf->instance, "session", "total_operations", "herd",
816                           stats->sess_herd);
817   }
818
819   if (conf->collect_shm) {
820     /* SHM records                 */
821     varnish_submit_derive(conf->instance, "shm", "total_operations", "records",
822                           stats->shm_records);
823     /* SHM writes                  */
824     varnish_submit_derive(conf->instance, "shm", "total_operations", "writes",
825                           stats->shm_writes);
826     /* SHM flushes due to overflow */
827     varnish_submit_derive(conf->instance, "shm", "total_operations", "flushes",
828                           stats->shm_flushes);
829     /* SHM MTX contention          */
830     varnish_submit_derive(conf->instance, "shm", "total_operations",
831                           "contention", stats->shm_cont);
832     /* SHM cycles through buffer   */
833     varnish_submit_derive(conf->instance, "shm", "total_operations", "cycles",
834                           stats->shm_cycles);
835   }
836
837   if (conf->collect_sm) {
838     /* allocator requests */
839     varnish_submit_derive(conf->instance, "sm", "total_requests", "nreq",
840                           stats->sm_nreq);
841     /* outstanding allocations */
842     varnish_submit_gauge(conf->instance, "sm", "requests", "outstanding",
843                          stats->sm_nobj);
844     /* bytes allocated */
845     varnish_submit_derive(conf->instance, "sm", "total_bytes", "allocated",
846                           stats->sm_balloc);
847     /* bytes free */
848     varnish_submit_derive(conf->instance, "sm", "total_bytes", "free",
849                           stats->sm_bfree);
850   }
851
852   if (conf->collect_sma) {
853     /* SMA allocator requests */
854     varnish_submit_derive(conf->instance, "sma", "total_requests", "nreq",
855                           stats->sma_nreq);
856     /* SMA outstanding allocations */
857     varnish_submit_gauge(conf->instance, "sma", "requests", "outstanding",
858                          stats->sma_nobj);
859     /* SMA outstanding bytes */
860     varnish_submit_gauge(conf->instance, "sma", "bytes", "outstanding",
861                          stats->sma_nbytes);
862     /* SMA bytes allocated */
863     varnish_submit_derive(conf->instance, "sma", "total_bytes", "allocated",
864                           stats->sma_balloc);
865     /* SMA bytes free */
866     varnish_submit_derive(conf->instance, "sma", "total_bytes", "free",
867                           stats->sma_bfree);
868   }
869
870   if (conf->collect_sms) {
871     /* SMS allocator requests */
872     varnish_submit_derive(conf->instance, "sms", "total_requests", "allocator",
873                           stats->sms_nreq);
874     /* SMS outstanding allocations */
875     varnish_submit_gauge(conf->instance, "sms", "requests", "outstanding",
876                          stats->sms_nobj);
877     /* SMS outstanding bytes */
878     varnish_submit_gauge(conf->instance, "sms", "bytes", "outstanding",
879                          stats->sms_nbytes);
880     /* SMS bytes allocated */
881     varnish_submit_derive(conf->instance, "sms", "total_bytes", "allocated",
882                           stats->sms_balloc);
883     /* SMS bytes freed */
884     varnish_submit_derive(conf->instance, "sms", "total_bytes", "free",
885                           stats->sms_bfree);
886   }
887
888   if (conf->collect_struct) {
889     /* N struct sess_mem       */
890     varnish_submit_gauge(conf->instance, "struct", "current_sessions",
891                          "sess_mem", stats->n_sess_mem);
892     /* N struct sess           */
893     varnish_submit_gauge(conf->instance, "struct", "current_sessions", "sess",
894                          stats->n_sess);
895     /* N struct object         */
896     varnish_submit_gauge(conf->instance, "struct", "objects", "object",
897                          stats->n_object);
898     /* N struct objecthead     */
899     varnish_submit_gauge(conf->instance, "struct", "objects", "objecthead",
900                          stats->n_objecthead);
901     /* N struct smf            */
902     varnish_submit_gauge(conf->instance, "struct", "objects", "smf",
903                          stats->n_smf);
904     /* N small free smf         */
905     varnish_submit_gauge(conf->instance, "struct", "objects", "smf_frag",
906                          stats->n_smf_frag);
907     /* N large free smf         */
908     varnish_submit_gauge(conf->instance, "struct", "objects", "smf_large",
909                          stats->n_smf_large);
910     /* N struct vbe_conn        */
911     varnish_submit_gauge(conf->instance, "struct", "objects", "vbe_conn",
912                          stats->n_vbe_conn);
913   }
914
915   if (conf->collect_totals) {
916     /* Total Sessions */
917     varnish_submit_derive(conf->instance, "totals", "total_sessions",
918                           "sessions", stats->s_sess);
919     /* Total Requests */
920     varnish_submit_derive(conf->instance, "totals", "total_requests",
921                           "requests", stats->s_req);
922     /* Total pipe */
923     varnish_submit_derive(conf->instance, "totals", "total_operations", "pipe",
924                           stats->s_pipe);
925     /* Total pass */
926     varnish_submit_derive(conf->instance, "totals", "total_operations", "pass",
927                           stats->s_pass);
928     /* Total fetch */
929     varnish_submit_derive(conf->instance, "totals", "total_operations",
930                           "fetches", stats->s_fetch);
931     /* Total header bytes */
932     varnish_submit_derive(conf->instance, "totals", "total_bytes",
933                           "header-bytes", stats->s_hdrbytes);
934     /* Total body byte */
935     varnish_submit_derive(conf->instance, "totals", "total_bytes", "body-bytes",
936                           stats->s_bodybytes);
937   }
938
939   if (conf->collect_vcl) {
940     /* N vcl total     */
941     varnish_submit_gauge(conf->instance, "vcl", "vcl", "total_vcl",
942                          stats->n_vcl);
943     /* N vcl available */
944     varnish_submit_gauge(conf->instance, "vcl", "vcl", "avail_vcl",
945                          stats->n_vcl_avail);
946     /* N vcl discarded */
947     varnish_submit_gauge(conf->instance, "vcl", "vcl", "discarded_vcl",
948                          stats->n_vcl_discard);
949   }
950
951   if (conf->collect_workers) {
952     /* worker threads */
953     varnish_submit_gauge(conf->instance, "workers", "threads", "worker",
954                          stats->n_wrk);
955     /* worker threads created */
956     varnish_submit_derive(conf->instance, "workers", "total_threads", "created",
957                           stats->n_wrk_create);
958     /* worker threads not created */
959     varnish_submit_derive(conf->instance, "workers", "total_threads", "failed",
960                           stats->n_wrk_failed);
961     /* worker threads limited */
962     varnish_submit_derive(conf->instance, "workers", "total_threads", "limited",
963                           stats->n_wrk_max);
964     /* dropped work requests */
965     varnish_submit_derive(conf->instance, "workers", "total_threads", "dropped",
966                           stats->n_wrk_drop);
967     /* queued work requests */
968     varnish_submit_derive(conf->instance, "workers", "total_requests", "queued",
969                           stats->n_wrk_queue);
970     /* overflowed work requests */
971     varnish_submit_derive(conf->instance, "workers", "total_requests",
972                           "overflowed", stats->n_wrk_overflow);
973   }
974
975 } /* }}} void varnish_monitor */
976 #endif
977
978 #if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
979 static int varnish_read(user_data_t *ud) /* {{{ */
980 {
981   struct VSM_data *vd;
982   const c_varnish_stats_t *stats;
983   _Bool ok;
984
985   user_config_t *conf;
986
987   if ((ud == NULL) || (ud->data == NULL))
988     return EINVAL;
989
990   conf = ud->data;
991
992   vd = VSM_New();
993 #if HAVE_VARNISH_V3
994   VSC_Setup(vd);
995 #endif
996
997   if (conf->instance != NULL) {
998     int status;
999
1000     status = VSM_n_Arg(vd, conf->instance);
1001     if (status < 0) {
1002       VSM_Delete(vd);
1003       ERROR("varnish plugin: VSM_n_Arg (\"%s\") failed "
1004             "with status %i.",
1005             conf->instance, status);
1006       return -1;
1007     }
1008   }
1009
1010 #if HAVE_VARNISH_V3
1011   ok = (VSC_Open(vd, /* diag = */ 1) == 0);
1012 #else /* if HAVE_VARNISH_V4 */
1013   ok = (VSM_Open(vd) == 0);
1014 #endif
1015   if (!ok) {
1016     VSM_Delete(vd);
1017     ERROR("varnish plugin: Unable to open connection.");
1018
1019     return -1;
1020   }
1021
1022 #if HAVE_VARNISH_V3
1023   stats = VSC_Main(vd);
1024 #else /* if HAVE_VARNISH_V4 */
1025   stats = VSC_Main(vd, NULL);
1026 #endif
1027   if (!stats) {
1028     VSM_Delete(vd);
1029     ERROR("varnish plugin: Unable to get statistics.");
1030
1031     return -1;
1032   }
1033
1034 #if HAVE_VARNISH_V3
1035   VSC_Iter(vd, varnish_monitor, conf);
1036 #else /* if HAVE_VARNISH_V4 */
1037   VSC_Iter(vd, NULL, varnish_monitor, conf);
1038 #endif
1039   VSM_Delete(vd);
1040
1041   return 0;
1042 } /* }}} */
1043 #else /* if HAVE_VARNISH_V2 */
1044 static int varnish_read(user_data_t *ud) /* {{{ */
1045 {
1046   const c_varnish_stats_t *stats;
1047
1048   user_config_t *conf;
1049
1050   if ((ud == NULL) || (ud->data == NULL))
1051     return EINVAL;
1052
1053   conf = ud->data;
1054
1055   stats = VSL_OpenStats(conf->instance);
1056   if (stats == NULL) {
1057     ERROR("Varnish plugin : unable to load statistics");
1058
1059     return -1;
1060   }
1061
1062   varnish_monitor(conf, stats);
1063
1064   return 0;
1065 } /* }}} */
1066 #endif
1067
1068 static void varnish_config_free(void *ptr) /* {{{ */
1069 {
1070   user_config_t *conf = ptr;
1071
1072   if (conf == NULL)
1073     return;
1074
1075   sfree(conf->instance);
1076   sfree(conf);
1077 } /* }}} */
1078
1079 static int varnish_config_apply_default(user_config_t *conf) /* {{{ */
1080 {
1081   if (conf == NULL)
1082     return EINVAL;
1083
1084   conf->collect_backend = 1;
1085   conf->collect_cache = 1;
1086   conf->collect_connections = 1;
1087 #ifdef HAVE_VARNISH_V3
1088   conf->collect_dirdns = 0;
1089 #endif
1090   conf->collect_esi = 0;
1091   conf->collect_fetch = 0;
1092   conf->collect_hcb = 0;
1093   conf->collect_objects = 0;
1094 #if HAVE_VARNISH_V2
1095   conf->collect_purge = 0;
1096 #else
1097   conf->collect_ban = 0;
1098 #endif
1099   conf->collect_session = 0;
1100   conf->collect_shm = 1;
1101 #if HAVE_VARNISH_V2
1102   conf->collect_sm = 0;
1103   conf->collect_sma = 0;
1104 #endif
1105   conf->collect_sms = 0;
1106   conf->collect_struct = 0;
1107   conf->collect_totals = 0;
1108 #if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
1109   conf->collect_uptime = 0;
1110 #endif
1111   conf->collect_vcl = 0;
1112   conf->collect_workers = 0;
1113 #if HAVE_VARNISH_V4
1114   conf->collect_vsm = 0;
1115 #endif
1116
1117   return 0;
1118 } /* }}} int varnish_config_apply_default */
1119
1120 static int varnish_init(void) /* {{{ */
1121 {
1122   user_config_t *conf;
1123
1124   if (have_instance)
1125     return 0;
1126
1127   conf = calloc(1, sizeof(*conf));
1128   if (conf == NULL)
1129     return ENOMEM;
1130
1131   /* Default settings: */
1132   conf->instance = NULL;
1133
1134   varnish_config_apply_default(conf);
1135
1136   plugin_register_complex_read(
1137       /* group = */ "varnish",
1138       /* name      = */ "varnish/localhost",
1139       /* callback  = */ varnish_read,
1140       /* interval  = */ 0,
1141       &(user_data_t){
1142           .data = conf, .free_func = varnish_config_free,
1143       });
1144
1145   return 0;
1146 } /* }}} int varnish_init */
1147
1148 static int varnish_config_instance(const oconfig_item_t *ci) /* {{{ */
1149 {
1150   user_config_t *conf;
1151   char callback_name[DATA_MAX_NAME_LEN];
1152
1153   conf = calloc(1, sizeof(*conf));
1154   if (conf == NULL)
1155     return ENOMEM;
1156   conf->instance = NULL;
1157
1158   varnish_config_apply_default(conf);
1159
1160   if (ci->values_num == 1) {
1161     int status;
1162
1163     status = cf_util_get_string(ci, &conf->instance);
1164     if (status != 0) {
1165       sfree(conf);
1166       return status;
1167     }
1168     assert(conf->instance != NULL);
1169
1170     if (strcmp("localhost", conf->instance) == 0) {
1171       sfree(conf->instance);
1172       conf->instance = NULL;
1173     }
1174   } else if (ci->values_num > 1) {
1175     WARNING("Varnish plugin: \"Instance\" blocks accept only "
1176             "one argument.");
1177     sfree(conf);
1178     return EINVAL;
1179   }
1180
1181   for (int i = 0; i < ci->children_num; i++) {
1182     oconfig_item_t *child = ci->children + i;
1183
1184     if (strcasecmp("CollectCache", child->key) == 0)
1185       cf_util_get_boolean(child, &conf->collect_cache);
1186     else if (strcasecmp("CollectConnections", child->key) == 0)
1187       cf_util_get_boolean(child, &conf->collect_connections);
1188     else if (strcasecmp("CollectESI", child->key) == 0)
1189       cf_util_get_boolean(child, &conf->collect_esi);
1190     else if (strcasecmp("CollectDirectorDNS", child->key) == 0)
1191 #ifdef HAVE_VARNISH_V3
1192       cf_util_get_boolean(child, &conf->collect_dirdns);
1193 #else
1194       WARNING("Varnish plugin: \"%s\" is available for Varnish %s only.",
1195               child->key, "v3");
1196 #endif
1197     else if (strcasecmp("CollectBackend", child->key) == 0)
1198       cf_util_get_boolean(child, &conf->collect_backend);
1199     else if (strcasecmp("CollectFetch", child->key) == 0)
1200       cf_util_get_boolean(child, &conf->collect_fetch);
1201     else if (strcasecmp("CollectHCB", child->key) == 0)
1202       cf_util_get_boolean(child, &conf->collect_hcb);
1203     else if (strcasecmp("CollectObjects", child->key) == 0)
1204       cf_util_get_boolean(child, &conf->collect_objects);
1205     else if (strcasecmp("CollectPurge", child->key) == 0)
1206 #if HAVE_VARNISH_V2
1207       cf_util_get_boolean(child, &conf->collect_purge);
1208 #else
1209       WARNING("Varnish plugin: \"%s\" is available for Varnish %s only.",
1210               child->key, "v2");
1211 #endif
1212     else if (strcasecmp("CollectBan", child->key) == 0)
1213 #if HAVE_VARNISH_V2
1214       WARNING("Varnish plugin: \"%s\" is not available for Varnish %s.",
1215               child->key, "v2");
1216 #else
1217       cf_util_get_boolean(child, &conf->collect_ban);
1218 #endif
1219     else if (strcasecmp("CollectSession", child->key) == 0)
1220       cf_util_get_boolean(child, &conf->collect_session);
1221     else if (strcasecmp("CollectSHM", child->key) == 0)
1222       cf_util_get_boolean(child, &conf->collect_shm);
1223     else if (strcasecmp("CollectSMS", child->key) == 0)
1224       cf_util_get_boolean(child, &conf->collect_sms);
1225     else if (strcasecmp("CollectSMA", child->key) == 0)
1226 #if HAVE_VARNISH_V2
1227       cf_util_get_boolean(child, &conf->collect_sma);
1228 #else
1229       WARNING("Varnish plugin: \"%s\" is available for Varnish %s only.",
1230               child->key, "v2");
1231 #endif
1232     else if (strcasecmp("CollectSM", child->key) == 0)
1233 #if HAVE_VARNISH_V2
1234       cf_util_get_boolean(child, &conf->collect_sm);
1235 #else
1236       WARNING("Varnish plugin: \"%s\" is available for Varnish %s only.",
1237               child->key, "v2");
1238 #endif
1239     else if (strcasecmp("CollectStruct", child->key) == 0)
1240       cf_util_get_boolean(child, &conf->collect_struct);
1241     else if (strcasecmp("CollectTotals", child->key) == 0)
1242       cf_util_get_boolean(child, &conf->collect_totals);
1243     else if (strcasecmp("CollectUptime", child->key) == 0)
1244 #if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
1245       cf_util_get_boolean(child, &conf->collect_uptime);
1246 #else
1247       WARNING("Varnish plugin: \"%s\" is available for Varnish %s only.",
1248               child->key, "v3 and v4");
1249 #endif
1250     else if (strcasecmp("CollectVCL", child->key) == 0)
1251       cf_util_get_boolean(child, &conf->collect_vcl);
1252     else if (strcasecmp("CollectWorkers", child->key) == 0)
1253       cf_util_get_boolean(child, &conf->collect_workers);
1254     else if (strcasecmp("CollectVSM", child->key) == 0)
1255 #if HAVE_VARNISH_V4
1256       cf_util_get_boolean(child, &conf->collect_vsm);
1257 #else
1258       WARNING("Varnish plugin: \"%s\" is available for Varnish %s only.",
1259               child->key, "v4");
1260 #endif
1261     else {
1262       WARNING("Varnish plugin: Ignoring unknown "
1263               "configuration option: \"%s\". Did "
1264               "you forget to add an <Instance /> "
1265               "block around the configuration?",
1266               child->key);
1267     }
1268   }
1269
1270   if (!conf->collect_cache && !conf->collect_connections &&
1271       !conf->collect_esi && !conf->collect_backend
1272 #ifdef HAVE_VARNISH_V3
1273       && !conf->collect_dirdns
1274 #endif
1275       && !conf->collect_fetch && !conf->collect_hcb && !conf->collect_objects
1276 #if HAVE_VARNISH_V2
1277       && !conf->collect_purge
1278 #else
1279       && !conf->collect_ban
1280 #endif
1281       && !conf->collect_session && !conf->collect_shm && !conf->collect_sms
1282 #if HAVE_VARNISH_V2
1283       && !conf->collect_sma && !conf->collect_sm
1284 #endif
1285       && !conf->collect_struct && !conf->collect_totals
1286 #if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
1287       && !conf->collect_uptime
1288 #endif
1289       && !conf->collect_vcl && !conf->collect_workers
1290 #if HAVE_VARNISH_V4
1291       && !conf->collect_vsm
1292 #endif
1293       ) {
1294     WARNING("Varnish plugin: No metric has been configured for "
1295             "instance \"%s\". Disabling this instance.",
1296             (conf->instance == NULL) ? "localhost" : conf->instance);
1297     sfree(conf);
1298     return EINVAL;
1299   }
1300
1301   snprintf(callback_name, sizeof(callback_name), "varnish/%s",
1302            (conf->instance == NULL) ? "localhost" : conf->instance);
1303
1304   plugin_register_complex_read(
1305       /* group = */ "varnish",
1306       /* name      = */ callback_name,
1307       /* callback  = */ varnish_read,
1308       /* interval  = */ 0,
1309       &(user_data_t){
1310           .data = conf, .free_func = varnish_config_free,
1311       });
1312
1313   have_instance = 1;
1314
1315   return 0;
1316 } /* }}} int varnish_config_instance */
1317
1318 static int varnish_config(oconfig_item_t *ci) /* {{{ */
1319 {
1320   for (int i = 0; i < ci->children_num; i++) {
1321     oconfig_item_t *child = ci->children + i;
1322
1323     if (strcasecmp("Instance", child->key) == 0)
1324       varnish_config_instance(child);
1325     else {
1326       WARNING("Varnish plugin: Ignoring unknown "
1327               "configuration option: \"%s\"",
1328               child->key);
1329     }
1330   }
1331
1332   return 0;
1333 } /* }}} int varnish_config */
1334
1335 void module_register(void) /* {{{ */
1336 {
1337   plugin_register_complex_config("varnish", varnish_config);
1338   plugin_register_init("varnish", varnish_init);
1339 } /* }}} */