2 * Copyright (c) 2017 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@backplane.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
28 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #define SLEEP_INTERVAL 60 /* minimum is KCOLLECT_INTERVAL */
36 static void dump_text(kcollect_t
*ary
, size_t count
, size_t total_count
);
37 static void dump_dbm(kcollect_t
*ary
, size_t count
, const char *datafile
);
38 static void dump_fields(kcollect_t
*ary
);
39 static void adjust_fields(kcollect_t
*ent
, const char *fields
);
43 int OutputWidth
= 1024;
44 int OutputHeight
= 1024;
47 main(int ac
, char **av
)
53 const char *datafile
= NULL
;
54 const char *fields
= NULL
;
63 sysctlbyname("kern.collect_data", NULL
, &bytes
, NULL
, 0);
65 fprintf(stderr
, "kern.collect_data not available\n");
69 while ((ch
= getopt(ac
, av
, "o:b:flgxw:GW:H:")) != -1) {
98 OutputWidth
= strtol(optarg
, NULL
, 0);
101 OutputHeight
= strtol(optarg
, NULL
, 0);
104 fprintf(stderr
, "Unknown option %c\n", ch
);
109 if (cmd
!= 'x' && ac
!= optind
) {
110 fprintf(stderr
, "Unknown argument %s\n", av
[optind
]);
118 if (cmd
== 'x' || cmd
== 'w')
119 start_gnuplot(ac
- optind
, av
+ optind
);
123 * Snarf as much data as we can. If we are looping,
124 * snarf less (no point snarfing stuff we already have).
127 sysctlbyname("kern.collect_data", NULL
, &bytes
, NULL
, 0);
129 bytes
= sizeof(kcollect_t
) * 2;
134 loop_bytes
= sizeof(kcollect_t
) *
135 (4 + SLEEP_INTERVAL
/ KCOLLECT_INTERVAL
);
136 if (bytes
> loop_bytes
)
141 sysctlbyname("kern.collect_data", ary
, &bytes
, NULL
, 0);
144 adjust_fields(&ary
[1], fields
);
146 count
= bytes
/ sizeof(kcollect_t
);
149 if ((int)(ary
[count
-1].ticks
- last_ticks
) > 0)
158 dump_text(ary
, count
, total_count
);
162 dump_dbm(ary
, count
, datafile
);
167 break; /* NOT REACHED */
170 dump_gnuplot(ary
, count
, NULL
);
174 dump_gnuplot(ary
, count
, datafile
);
178 dump_gnuplot(ary
, count
, NULL
);
198 last_ticks
= ary
[2].ticks
;
200 total_count
+= count
- 2;
203 * Loop for incremental aquisition. When outputting to
204 * gunplot, we have to send the whole data-set again so
205 * do not increment loops in that case.
207 if (cmd
!= 'g' && cmd
!= 'x' && cmd
!= 'w')
219 dump_text(kcollect_t
*ary
, size_t count
, size_t total_count
)
230 for (i
= count
- 1; i
>= 2; --i
) {
231 if ((total_count
& 15) == 0) {
232 printf("%8.8s", "time");
233 for (j
= 0; j
< KCOLLECT_ENTRIES
; ++j
) {
234 if (ary
[1].data
[j
]) {
236 (char *)&ary
[1].data
[j
]);
245 t
= ary
[i
].realtime
.tv_sec
;
250 strftime(buf
, sizeof(buf
), "%H:%M:%S", tmv
);
251 printf("%8.8s", buf
);
253 for (j
= 0; j
< KCOLLECT_ENTRIES
; ++j
) {
254 if (ary
[1].data
[j
] == 0)
258 * NOTE: kernel does not have to provide the scale
259 * (that is, the highest likely value), nor
260 * does it make sense in all cases.
262 * Example scale - kernel provides total amount
263 * of memory available for memory related
264 * statistics in the scale field.
266 value
= ary
[i
].data
[j
];
267 scale
= KCOLLECT_GETSCALE(ary
[0].data
[j
]);
268 fmt
= KCOLLECT_GETFMT(ary
[0].data
[j
]);
277 printf("%5ju.%02ju", value
/ 100, value
% 100);
281 * Percentage fractional x100 (100% = 10000)
283 printf("%4ju.%02ju%%",
284 value
/ 100, value
% 100);
290 humanize_number(buf
, sizeof(buf
), value
, "",
294 printf("%8.8s", buf
);
298 * Raw count over period (this is not total)
300 humanize_number(buf
, sizeof(buf
), value
, "",
305 printf("%8.8s", buf
);
309 * Total bytes (this is a total), output
312 if (scale
> 100000000) {
313 humanize_number(buf
, sizeof(buf
),
319 humanize_number(buf
, sizeof(buf
),
325 printf("%8.8s", buf
);
338 dump_dbm(kcollect_t
*ary __unused
, size_t count __unused
, const char *datafile __unused
)
343 dump_fields(kcollect_t
*ary
)
347 for (j
= 0; j
< KCOLLECT_ENTRIES
; ++j
) {
348 if (ary
[1].data
[j
] == 0)
351 (char *)&ary
[1].data
[j
],
352 KCOLLECT_GETFMT(ary
[0].data
[j
]));
357 adjust_fields(kcollect_t
*ent
, const char *fields
)
359 char *copy
= strdup(fields
);
361 int selected
[KCOLLECT_ENTRIES
];
364 bzero(selected
, sizeof(selected
));
366 word
= strtok(copy
, ", \t");
368 for (j
= 0; j
< KCOLLECT_ENTRIES
; ++j
) {
369 if (strncmp(word
, (char *)&ent
->data
[j
], 8) == 0) {
374 word
= strtok(NULL
, ", \t");
377 for (j
= 0; j
< KCOLLECT_ENTRIES
; ++j
) {