varnish-cache/bin/varnishstat/varnishstat.c
1
/*-
2
 * Copyright (c) 2006 Verdens Gang AS
3
 * Copyright (c) 2006-2015 Varnish Software AS
4
 * All rights reserved.
5
 *
6
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
7
 * Author: Dag-Erling Smørgrav <des@des.no>
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 * 2. Redistributions in binary form must reproduce the above copyright
15
 *    notice, this list of conditions and the following disclaimer in the
16
 *    documentation and/or other materials provided with the distribution.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
22
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
 * SUCH DAMAGE.
29
 *
30
 * Statistics output program
31
 */
32
33
#include "config.h"
34
35
#include <stdarg.h>
36
#include <stdio.h>
37
#include <stdlib.h>
38
#include <signal.h>
39
#include <string.h>
40
#include <time.h>
41
#include <unistd.h>
42
#include <math.h>
43
44
#define VOPT_DEFINITION
45
#define VOPT_INC "varnishstat_options.h"
46
47
#include "vapi/voptget.h"
48
#include "vapi/vsl.h"
49
#include "vdef.h"
50
#include "vut.h"
51
52
#include "varnishstat.h"
53
54
static struct VUT *vut;
55
56
/*--------------------------------------------------------------------*/
57
58
static int v_matchproto_(VSC_iter_f)
59 289
do_xml_cb(void *priv, const struct VSC_point * const pt)
60
{
61
        uint64_t val;
62
63
        (void)priv;
64 289
        if (pt == NULL)
65 0
                return (0);
66 289
        AZ(strcmp(pt->ctype, "uint64_t"));
67 289
        val = *(const volatile uint64_t*)pt->ptr;
68
69 289
        printf("\t<stat>\n");
70 289
        printf("\t\t<name>%s</name>\n", pt->name);
71 289
        printf("\t\t<value>%ju</value>\n", (uintmax_t)val);
72 289
        printf("\t\t<flag>%c</flag>\n", pt->semantics);
73 289
        printf("\t\t<format>%c</format>\n", pt->format);
74 289
        printf("\t\t<description>%s</description>\n", pt->sdesc);
75 289
        printf("\t</stat>\n");
76 289
        return (0);
77
}
78
79
static void
80 1
do_xml(struct vsm *vsm, struct vsc *vsc)
81
{
82
        char time_stamp[20];
83
        time_t now;
84
85 1
        printf("<?xml version=\"1.0\"?>\n");
86 1
        now = time(NULL);
87 1
        (void)strftime(time_stamp, 20, "%Y-%m-%dT%H:%M:%S", localtime(&now));
88 1
        printf("<varnishstat timestamp=\"%s\">\n", time_stamp);
89 1
        (void)VSC_Iter(vsc, vsm, do_xml_cb, NULL);
90 1
        printf("</varnishstat>\n");
91 1
}
92
93
94
/*--------------------------------------------------------------------*/
95
96
static int v_matchproto_(VSC_iter_f)
97 289
do_json_cb(void *priv, const struct VSC_point * const pt)
98
{
99
        uint64_t val;
100
        int *jp;
101
102 289
        if (pt == NULL)
103 0
                return (0);
104
105 289
        jp = priv;
106 289
        AZ(strcmp(pt->ctype, "uint64_t"));
107 289
        val = *(const volatile uint64_t*)pt->ptr;
108
109 289
        if (*jp)
110 1
                *jp = 0;
111
        else
112 288
                printf(",\n");
113
114 289
        printf("  \"");
115
        /* build the JSON key name.  */
116 289
        printf("%s\": {\n", pt->name);
117 289
        printf("    \"description\": \"%s\",\n", pt->sdesc);
118
119 289
        printf("    \"flag\": \"%c\", ", pt->semantics);
120 289
        printf("\"format\": \"%c\",\n", pt->format);
121 289
        printf("    \"value\": %ju", (uintmax_t)val);
122 289
        printf("\n  }");
123
124 289
        if (*jp)
125 0
                printf("\n");
126 289
        return (0);
127
}
128
129
static void
130 1
do_json(struct vsm *vsm, struct vsc *vsc)
131
{
132
        char time_stamp[20];
133
        time_t now;
134
        int jp;
135
136 1
        jp = 1;
137
138 1
        printf("{\n");
139 1
        now = time(NULL);
140
141 1
        (void)strftime(time_stamp, 20, "%Y-%m-%dT%H:%M:%S", localtime(&now));
142 1
        printf("  \"timestamp\": \"%s\",\n", time_stamp);
143 1
        (void)VSC_Iter(vsc, vsm, do_json_cb, &jp);
144 1
        printf("\n}\n");
145 1
}
146
147
148
/*--------------------------------------------------------------------*/
149
150
struct once_priv {
151
        double  up;
152
        int pad;
153
};
154
155
static int v_matchproto_(VSC_iter_f)
156 6
do_once_cb_first(void *priv, const struct VSC_point * const pt)
157
{
158
        struct once_priv *op;
159
        uint64_t val;
160
161 6
        if (pt == NULL)
162 0
                return (0);
163 6
        op = priv;
164 6
        AZ(strcmp(pt->ctype, "uint64_t"));
165 6
        if (strcmp(pt->name, "MAIN.uptime"))
166 0
                return (0);
167 6
        val = *(const volatile uint64_t*)pt->ptr;
168 6
        op->up = (double)val;
169 6
        return (1);
170
}
171
172
static int v_matchproto_(VSC_iter_f)
173 3009
do_once_cb(void *priv, const struct VSC_point * const pt)
174
{
175
        struct once_priv *op;
176
        uint64_t val;
177
        int i;
178
179 3009
        if (pt == NULL)
180 0
                return (0);
181 3009
        op = priv;
182 3009
        AZ(strcmp(pt->ctype, "uint64_t"));
183 3009
        val = *(const volatile uint64_t*)pt->ptr;
184 3009
        i = 0;
185 3009
        i += printf("%s", pt->name);
186 3009
        if (i >= op->pad)
187 16
                op->pad = i + 1;
188 3009
        printf("%*.*s", op->pad - i, op->pad - i, "");
189 3009
        if (pt->semantics == 'c')
190 5870
                printf("%12ju %12.2f %s\n",
191 3240
                    (uintmax_t)val, op->up ? val / op->up : 0,
192
                    pt->sdesc);
193
        else
194 379
                printf("%12ju %12s %s\n",
195
                    (uintmax_t)val, ".  ", pt->sdesc);
196 3009
        return (0);
197
}
198
199
static void
200 6
do_once(struct vsm *vsm, struct vsc *vsc)
201
{
202 6
        struct vsc *vsconce = VSC_New();
203
        struct once_priv op;
204
205 6
        AN(vsconce);
206 6
        AN(VSC_Arg(vsconce, 'f', "MAIN.uptime"));
207
208 6
        memset(&op, 0, sizeof op);
209 6
        op.pad = 18;
210
211 6
        (void)VSC_Iter(vsconce, vsm, do_once_cb_first, &op);
212 6
        VSC_Destroy(&vsconce, vsm);
213 6
        (void)VSC_Iter(vsc, vsm, do_once_cb, &op);
214 6
}
215
216
/*--------------------------------------------------------------------*/
217
218
static int v_matchproto_(VSC_iter_f)
219 289
do_list_cb(void *priv, const struct VSC_point * const pt)
220
{
221
        int i;
222
223
        (void)priv;
224
225 289
        if (pt == NULL)
226 0
                return (0);
227
228 289
        i = 0;
229 289
        i += printf("%s", pt->name);
230 289
        if (i < 30)
231 286
                printf("%*s", i - 30, "");
232 289
        printf(" %s\n", pt->sdesc);
233 289
        return (0);
234
}
235
236
static void
237 1
list_fields(struct vsm *vsm, struct vsc *vsc)
238
{
239 1
        printf("Varnishstat -f option fields:\n");
240 1
        printf("Field name                     Description\n");
241 1
        printf("----------                     -----------\n");
242
243 1
        (void)VSC_Iter(vsc, vsm, do_list_cb, NULL);
244 1
}
245
246
/*--------------------------------------------------------------------*/
247
248
static void v_noreturn_
249 2
usage(int status)
250
{
251
        const char **opt;
252
253 2
        fprintf(stderr, "Usage: %s <options>\n\n", vut->progname);
254 2
        fprintf(stderr, "Options:\n");
255 20
        for (opt = vopt_spec.vopt_usage; *opt != NULL; opt +=2)
256 18
                fprintf(stderr, " %-25s %s\n", *opt, *(opt + 1));
257 2
        exit(status);
258
}
259
260
int
261 19
main(int argc, char * const *argv)
262
{
263
        struct vsm *vd;
264 19
        int once = 0, xml = 0, json = 0, f_list = 0, curses = 0;
265
        signed char opt;
266
        int i;
267
        struct vsc *vsc;
268
269 19
        vut = VUT_InitProg(argc, argv, &vopt_spec);
270 17
        AN(vut);
271 17
        vd = VSM_New();
272 17
        AN(vd);
273 17
        vsc = VSC_New();
274 17
        AN(vsc);
275
276 63
        while ((opt = getopt(argc, argv, vopt_spec.vopt_optstring)) != -1) {
277 34
                switch (opt) {
278
                case '1':
279 6
                        once = 1;
280 6
                        break;
281
                case 'h':
282
                        /* Usage help */
283 1
                        usage(0);
284
                        break;
285
                case 'l':
286 1
                        f_list = 1;
287 1
                        break;
288
                case 'x':
289 1
                        xml = 1;
290 1
                        break;
291
                case 'j':
292 1
                        json = 1;
293 1
                        break;
294
                case 'f':
295 8
                        AN(VSC_Arg(vsc, opt, optarg));
296 8
                        break;
297
                case 'V':
298 1
                        AN(VUT_Arg(vut, opt, optarg));
299 0
                        break;
300
                default:
301 15
                        i = VSM_Arg(vd, opt, optarg);
302 15
                        if (i < 0)
303 3
                                VUT_Error(vut, 1, "%s", VSM_Error(vd));
304 12
                        if (!i)
305 0
                                usage(1);
306
                }
307
        }
308
309 12
        if (optind != argc)
310 1
                usage(1);
311
312 11
        if (!(xml || json || once || f_list))
313 2
                curses = 1;
314
315 11
        if (VSM_Attach(vd, STDERR_FILENO))
316 1
                VUT_Error(vut, 1, "%s", VSM_Error(vd));
317
318 10
        if (curses)
319 1
                do_curses(vd, vsc, 1.0);
320 9
        else if (xml)
321 1
                do_xml(vd, vsc);
322 8
        else if (json)
323 1
                do_json(vd, vsc);
324 7
        else if (once)
325 6
                do_once(vd, vsc);
326 1
        else if (f_list)
327 1
                list_fields(vd, vsc);
328
        else
329 0
                assert(0);
330
331 10
        exit(0);
332
}