/* * haproxy log statistics reporter * * Copyright 2000-2012 Willy Tarreau * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define SOURCE_FIELD 5 #define ACCEPT_FIELD 6 #define SERVER_FIELD 8 #define TIME_FIELD 9 #define STATUS_FIELD 10 #define BYTES_SENT_FIELD 11 #define TERM_CODES_FIELD 14 #define CONN_FIELD 15 #define QUEUE_LEN_FIELD 16 #define METH_FIELD 17 #define URL_FIELD 18 #define MAXLINE 16384 #define QBITS 4 #define SEP(c) ((unsigned char)(c) <= ' ') #define SKIP_CHAR(p,c) do { while (1) { int __c = (unsigned char)*p++; if (__c == c) break; if (__c <= ' ') { p--; break; } } } while (0) /* [0] = err/date, [1] = req, [2] = conn, [3] = resp, [4] = data */ static struct eb_root timers[5] = { EB_ROOT_UNIQUE, EB_ROOT_UNIQUE, EB_ROOT_UNIQUE, EB_ROOT_UNIQUE, EB_ROOT_UNIQUE, }; struct timer { struct eb32_node node; unsigned int count; }; struct srv_st { unsigned int st_cnt[6]; /* 0xx to 5xx */ unsigned int nb_ct, nb_rt, nb_ok; unsigned long long cum_ct, cum_rt; struct ebmb_node node; /* don't put anything else here, the server name will be there */ }; struct url_stat { union { struct ebpt_node url; struct eb64_node val; } node; char *url; unsigned long long total_time; /* sum(all reqs' times) */ unsigned long long total_time_ok; /* sum(all OK reqs' times) */ unsigned long long total_bytes_sent; /* sum(all bytes sent) */ unsigned int nb_err, nb_req; }; #define FILT_COUNT_ONLY 0x01 #define FILT_INVERT 0x02 #define FILT_QUIET 0x04 #define FILT_ERRORS_ONLY 0x08 #define FILT_ACC_DELAY 0x10 #define FILT_ACC_COUNT 0x20 #define FILT_GRAPH_TIMERS 0x40 #define FILT_PERCENTILE 0x80 #define FILT_TIME_RESP 0x100 #define FILT_INVERT_ERRORS 0x200 #define FILT_INVERT_TIME_RESP 0x400 #define FILT_COUNT_STATUS 0x800 #define FILT_COUNT_SRV_STATUS 0x1000 #define FILT_COUNT_TERM_CODES 0x2000 #define FILT_COUNT_URL_ONLY 0x004000 #define FILT_COUNT_URL_COUNT 0x008000 #define FILT_COUNT_URL_ERR 0x010000 #define FILT_COUNT_URL_TTOT 0x020000 #define FILT_COUNT_URL_TAVG 0x040000 #define FILT_COUNT_URL_TTOTO 0x080000 #define FILT_COUNT_URL_TAVGO 0x100000 #define FILT_HTTP_ONLY 0x200000 #define FILT_TERM_CODE_NAME 0x400000 #define FILT_INVERT_TERM_CODE_NAME 0x800000 #define FILT_HTTP_STATUS 0x1000000 #define FILT_INVERT_HTTP_STATUS 0x2000000 #define FILT_QUEUE_ONLY 0x4000000 #define FILT_QUEUE_SRV_ONLY 0x8000000 #define FILT_COUNT_URL_BAVG 0x10000000 #define FILT_COUNT_URL_BTOT 0x20000000 #define FILT_COUNT_URL_ANY (FILT_COUNT_URL_ONLY|FILT_COUNT_URL_COUNT|FILT_COUNT_URL_ERR| \ FILT_COUNT_URL_TTOT|FILT_COUNT_URL_TAVG|FILT_COUNT_URL_TTOTO|FILT_COUNT_URL_TAVGO| \ FILT_COUNT_URL_BAVG|FILT_COUNT_URL_BTOT) #define FILT_COUNT_COOK_CODES 0x40000000 #define FILT_COUNT_IP_COUNT 0x80000000 #define FILT2_TIMESTAMP 0x01 #define FILT2_PRESERVE_QUERY 0x02 #define FILT2_EXTRACT_CAPTURE 0x04 unsigned int filter = 0; unsigned int filter2 = 0; unsigned int filter_invert = 0; const char *line; int linenum = 0; int parse_err = 0; int lines_out = 0; int lines_max = -1; const char *fgets2(FILE *stream); void filter_count_url(const char *accept_field, const char *time_field, struct timer **tptr); void filter_count_ip(const char *source_field, const char *accept_field, const char *time_field, struct timer **tptr); void filter_count_srv_status(const char *accept_field, const char *time_field, struct timer **tptr); void filter_count_cook_codes(const char *accept_field, const char *time_field, struct timer **tptr); void filter_count_term_codes(const char *accept_field, const char *time_field, struct timer **tptr); void filter_count_status(const char *accept_field, const char *time_field, struct timer **tptr); void filter_graphs(const char *accept_field, const char *time_field, struct timer **tptr); void filter_output_line(const char *accept_field, const char *time_field, struct timer **tptr); void filter_extract_capture(const char *accept_field, const char *time_field, unsigned int, unsigned int); void filter_accept_holes(const char *accept_field, const char *time_field, struct timer **tptr); void usage(FILE *output, const char *msg) { fprintf(output, "%s" "Usage:\n" " halog [-h|--help] for long help\n" " halog [input_filters]* [modifiers]* [output_format] < log\n" " inp = [-e|-E] [-H] [-Q|-QS] [-rt|-RT