31
31
#define warn (...) fprintf(stderr, __VA_ARGS__)
32
32
#define OUTPUT_ROWS_LIMIT 10240
33
33
34
+ #define OPT_OUTPUT 1 /* --output */
35
+
34
36
enum SORT {
35
37
ALL ,
36
38
IO ,
@@ -50,6 +52,11 @@ struct vector {
50
52
void * * elems ;
51
53
};
52
54
55
+ struct data_t {
56
+ struct info_t key ;
57
+ struct val_t value ;
58
+ };
59
+
53
60
int grow_vector (struct vector * vector ) {
54
61
if (vector -> nr >= vector -> capacity ) {
55
62
void * * reallocated ;
@@ -87,6 +94,8 @@ static int interval = 1;
87
94
static int count = 99999999 ;
88
95
static pid_t target_pid = 0 ;
89
96
static bool verbose = false;
97
+ enum output_format output = 0 ;
98
+ static struct data_t datas [OUTPUT_ROWS_LIMIT ];
90
99
91
100
const char * argp_program_version = "biotop 0.1" ;
92
101
const char * argp_program_bug_address =
@@ -107,6 +116,7 @@ static const struct argp_option opts[] = {
107
116
{ "rows" , 'r' , "ROWS" , 0 , "Maximum rows to print, default 20" , 0 },
108
117
{ "pid" , 'p' , "PID" , 0 , "Process ID to trace" , 0 },
109
118
{ "verbose" , 'v' , NULL , 0 , "Verbose debug output" , 0 },
119
+ { "output" , OPT_OUTPUT , "FORMAT" , OPTION_ARG_OPTIONAL , "Output metrics in specified format (currently only 'line' supported)" , 0 },
110
120
{ NULL , 'h' , NULL , OPTION_HIDDEN , "Show the full help" , 0 },
111
121
{},
112
122
};
@@ -160,6 +170,16 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state)
160
170
case 'h' :
161
171
argp_state_help (state , stderr , ARGP_HELP_STD_HELP );
162
172
break ;
173
+ case OPT_OUTPUT :
174
+ output = FORMAT_LINE_PROTOCOL ;
175
+ if (arg ) {
176
+ if (strcmp (arg , "line" ) == 0 )
177
+ output = FORMAT_LINE_PROTOCOL ;
178
+ else
179
+ argp_error (state , "Invalid output format: %s. "
180
+ "Only 'line' is supported." , arg );
181
+ }
182
+ break ;
163
183
case ARGP_KEY_ARG :
164
184
errno = 0 ;
165
185
if (pos_args == 0 ) {
@@ -198,11 +218,6 @@ static void sig_int(int signo)
198
218
exiting = 1 ;
199
219
}
200
220
201
- struct data_t {
202
- struct info_t key ;
203
- struct val_t value ;
204
- };
205
-
206
221
static int sort_column (const void * obj1 , const void * obj2 )
207
222
{
208
223
struct data_t * d1 = (struct data_t * ) obj1 ;
@@ -299,13 +314,58 @@ static int read_stat(struct biotop_bpf *obj, struct data_t *datas, __u32 *count)
299
314
return 0 ;
300
315
}
301
316
317
+ static int print_metrics (struct biotop_bpf * obj )
318
+ {
319
+ int i , err = 0 , rows = OUTPUT_ROWS_LIMIT ;
320
+ time_t ts = time (NULL );
321
+ struct metric m = {
322
+ .name = "biotop" ,
323
+ .tags = {{ "pid" , "" }},
324
+ .nr_tags = 1 ,
325
+ .fields = {
326
+ { "I/O" , 0 },
327
+ { "Kbytes" , 0 },
328
+ { "AVGms" , 0 }
329
+ },
330
+ .nr_fields = 3 ,
331
+ .ts = ts
332
+ };
333
+
334
+ err = read_stat (obj , datas , (__u32 * ) & rows );
335
+ if (err ) {
336
+ fprintf (stderr , "read stat failed: %s\n" , strerror (errno ));
337
+ return err ;
338
+ }
339
+
340
+ for (i = 0 ; i < rows ; i ++ ) {
341
+ struct info_t * key = & datas [i ].key ;
342
+ struct val_t * value = & datas [i ].value ;
343
+ float avg_ms = 0 ;
344
+
345
+ /* Tag */
346
+ snprintf (m .tags [0 ].value , sizeof (m .tags [0 ].value ), "%u" , key -> pid );
347
+
348
+ /* To avoid floating point exception. */
349
+ if (value -> io )
350
+ avg_ms = ((float ) value -> us ) / 1000 / value -> io ;
351
+
352
+ /* Fields */
353
+ m .fields [0 ].value = value -> io ;
354
+ m .fields [1 ].value = value -> bytes ;
355
+ m .fields [2 ].value = avg_ms ;
356
+
357
+ print_metric (& m , output );
358
+ }
359
+
360
+ return 0 ;
361
+ }
362
+
302
363
static int print_stat (struct biotop_bpf * obj )
303
364
{
304
365
FILE * f ;
305
366
time_t t ;
306
367
struct tm * tm ;
307
368
char ts [16 ], buf [256 ];
308
- static struct data_t datas [OUTPUT_ROWS_LIMIT ];
309
369
int n , i , err = 0 , rows = OUTPUT_ROWS_LIMIT ;
310
370
311
371
f = fopen ("/proc/loadavg" , "r" );
@@ -319,6 +379,7 @@ static int print_stat(struct biotop_bpf *obj)
319
379
printf ("%8s loadavg: %s\n" , ts , buf );
320
380
fclose (f );
321
381
}
382
+
322
383
printf ("%-7s %-16s %1s %-3s %-3s %-8s %5s %7s %6s\n" ,
323
384
"PID" , "COMM" , "D" , "MAJ" , "MIN" , "DISK" , "I/O" , "Kbytes" , "AVGms" );
324
385
@@ -448,15 +509,21 @@ int main(int argc, char **argv)
448
509
while (1 ) {
449
510
sleep (interval );
450
511
451
- if (clear_screen ) {
452
- err = system ( "clear" );
512
+ if (output ) {
513
+ err = print_metrics ( obj );
453
514
if (err )
454
515
goto cleanup ;
455
- }
516
+ } else {
517
+ if (clear_screen ) {
518
+ err = system ("clear" );
519
+ if (err )
520
+ goto cleanup ;
521
+ }
456
522
457
- err = print_stat (obj );
458
- if (err )
459
- goto cleanup ;
523
+ err = print_stat (obj );
524
+ if (err )
525
+ goto cleanup ;
526
+ }
460
527
461
528
count -- ;
462
529
if (exiting || !count )
0 commit comments