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 272
do_xml_cb(void *priv, const struct VSC_point * const pt)
60
{
61
        uint64_t val;
62
63
        (void)priv;
64 272
        if (pt == NULL)
65 0
                return (0);
66 272
        AZ(strcmp(pt->ctype, "uint64_t"));
67 272
        val = *(const volatile uint64_t*)pt->ptr;
68
69 272
        printf("\t<stat>\n");
70 272
        printf("\t\t<name>%s</name>\n", pt->name);
71 272
        printf("\t\t<value>%ju</value>\n", (uintmax_t)val);
72 272
        printf("\t\t<flag>%c</flag>\n", pt->semantics);
73 272
        printf("\t\t<format>%c</format>\n", pt->format);
74 272
        printf("\t\t<description>%s</description>\n", pt->sdesc);
75 272
        printf("\t</stat>\n");
76 272
        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 272
do_json_cb(void *priv, const struct VSC_point * const pt)
98
{
99
        uint64_t val;
100
        int *jp;
101
102 272
        if (pt == NULL)
103 0
                return (0);
104
105 272
        jp = priv;
106 272
        AZ(strcmp(pt->ctype, "uint64_t"));
107 272
        val = *(const volatile uint64_t*)pt->ptr;
108
109 272
        if (*jp)
110 1
                *jp = 0;
111
        else
112 271
                printf(",\n");
113
114 272
        printf("  \"");
115
        /* build the JSON key name.  */
116 272
        printf("%s\": {\n", pt->name);
117 272
        printf("    \"description\": \"%s\",\n", pt->sdesc);
118
119 272
        printf("    \"flag\": \"%c\", ", pt->semantics);
120 272
        printf("\"format\": \"%c\",\n", pt->format);
121 272
        printf("    \"value\": %ju", (uintmax_t)val);
122 272
        printf("\n  }");
123
124 272
        if (*jp)
125 0
                printf("\n");
126 272
        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 170
do_once_cb_first(void *priv, const struct VSC_point * const pt)
157
{
158
        struct once_priv *op;
159
        uint64_t val;
160
161 170
        if (pt == NULL)
162 0
                return (0);
163 170
        op = priv;
164 170
        AZ(strcmp(pt->ctype, "uint64_t"));
165 170
        if (strcmp(pt->name, "MAIN.uptime"))
166 168
                return (0);
167 2
        val = *(const volatile uint64_t*)pt->ptr;
168 2
        op->up = (double)val;
169 2
        return (1);
170
}
171
172
static int v_matchproto_(VSC_iter_f)
173 696
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 696
        if (pt == NULL)
180 0
                return (0);
181 696
        op = priv;
182 696
        AZ(strcmp(pt->ctype, "uint64_t"));
183 696
        val = *(const volatile uint64_t*)pt->ptr;
184 696
        i = 0;
185 696
        i += printf("%s", pt->name);
186 696
        if (i >= op->pad)
187 18
                op->pad = i + 1;
188 696
        printf("%*.*s", op->pad - i, op->pad - i, "");
189 696
        if (pt->semantics == 'c')
190 1574
                printf("%12ju %12.2f %s\n",
191 1008
                    (uintmax_t)val, op->up ? val / op->up : 0,
192
                    pt->sdesc);
193
        else
194 130
                printf("%12ju %12s %s\n",
195
                    (uintmax_t)val, ".  ", pt->sdesc);
196 696
        return (0);
197
}
198
199
static void
200 5
do_once(struct vsm *vsm, struct vsc *vsc)
201
{
202
        struct once_priv op;
203
204 5
        memset(&op, 0, sizeof op);
205 5
        op.pad = 18;
206
207 5
        (void)VSC_Iter(vsc, vsm, do_once_cb_first, &op);
208 5
        (void)VSC_Iter(vsc, vsm, do_once_cb, &op);
209 5
}
210
211
/*--------------------------------------------------------------------*/
212
213
static int v_matchproto_(VSC_iter_f)
214 272
do_list_cb(void *priv, const struct VSC_point * const pt)
215
{
216
        int i;
217
218
        (void)priv;
219
220 272
        if (pt == NULL)
221 0
                return (0);
222
223 272
        i = 0;
224 272
        i += printf("%s", pt->name);
225 272
        if (i < 30)
226 270
                printf("%*s", i - 30, "");
227 272
        printf(" %s\n", pt->sdesc);
228 272
        return (0);
229
}
230
231
static void
232 1
list_fields(struct vsm *vsm, struct vsc *vsc)
233
{
234 1
        printf("Varnishstat -f option fields:\n");
235 1
        printf("Field name                     Description\n");
236 1
        printf("----------                     -----------\n");
237
238 1
        (void)VSC_Iter(vsc, vsm, do_list_cb, NULL);
239 1
}
240
241
/*--------------------------------------------------------------------*/
242
243
static void v_noreturn_
244 2
usage(int status)
245
{
246
        const char **opt;
247
248 2
        fprintf(stderr, "Usage: %s <options>\n\n", vut->progname);
249 2
        fprintf(stderr, "Options:\n");
250 20
        for (opt = vopt_spec.vopt_usage; *opt != NULL; opt +=2)
251 18
                fprintf(stderr, " %-25s %s\n", *opt, *(opt + 1));
252 2
        exit(status);
253
}
254
255
int
256 17
main(int argc, char * const *argv)
257
{
258
        struct vsm *vd;
259 17
        int once = 0, xml = 0, json = 0, f_list = 0, curses = 0;
260
        signed char opt;
261
        int i;
262
        struct vsc *vsc;
263
264 17
        vut = VUT_InitProg(argc, argv, &vopt_spec);
265 15
        AN(vut);
266 15
        vd = VSM_New();
267 15
        AN(vd);
268 15
        vsc = VSC_New();
269 15
        AN(vsc);
270
271 56
        while ((opt = getopt(argc, argv, vopt_spec.vopt_optstring)) != -1) {
272 31
                switch (opt) {
273
                case '1':
274 5
                        once = 1;
275 5
                        break;
276
                case 'h':
277
                        /* Usage help */
278 1
                        usage(0);
279
                case 'l':
280 1
                        f_list = 1;
281 1
                        break;
282
                case 'x':
283 1
                        xml = 1;
284 1
                        break;
285
                case 'j':
286 1
                        json = 1;
287 1
                        break;
288
                case 'f':
289 8
                        AN(VSC_Arg(vsc, opt, optarg));
290 8
                        break;
291
                case 'V':
292 1
                        AN(VUT_Arg(vut, opt, optarg));
293 0
                        break;
294
                default:
295 13
                        i = VSM_Arg(vd, opt, optarg);
296 13
                        if (i < 0)
297 3
                                VUT_Error(vut, 1, "%s", VSM_Error(vd));
298 10
                        if (!i)
299 0
                                usage(1);
300
                }
301
        }
302
303 10
        if (optind != argc)
304 1
                usage(1);
305
306 9
        if (!(xml || json || once || f_list))
307 1
                curses = 1;
308
309 9
        if (VSM_Attach(vd, STDERR_FILENO))
310 1
                VUT_Error(vut, 1, "%s", VSM_Error(vd));
311
312 8
        if (curses)
313 0
                do_curses(vd, vsc, 1.0);
314 8
        else if (xml)
315 1
                do_xml(vd, vsc);
316 7
        else if (json)
317 1
                do_json(vd, vsc);
318 6
        else if (once)
319 5
                do_once(vd, vsc);
320 1
        else if (f_list)
321 1
                list_fields(vd, vsc);
322
        else
323 0
                assert(0);
324
325 8
        exit(0);
326
}