void anl_reset_columns(char *log) { /* get number of columns */ char *line; if(anl_conf->tunerpromode == 1) { line = line_start(log,1); } else { line = line_start(log,0); } int x = 0; while(field_start(line,x) != NULL) x++; anl_conf->n_cols = x; /* get column numbers */ anl_conf->col_lblm = anl_get_col("COL_LBLM",log); anl_conf->col_cell = anl_get_col("COL_CELL",log); anl_conf->col_rblm = anl_get_col("COL_RBLM",log); if(anl_conf->use_int == 1) { anl_conf->col_lint = anl_get_col("COL_LINT",log); anl_conf->col_rint = anl_get_col("COL_RINT",log); } anl_conf->col_knock = anl_get_col("COL_KNOCK",log); if(anl_conf->wb_on == 1) { anl_conf->col_wb = anl_get_col("COL_WB",log); } else { anl_conf->col_ro2 = anl_get_col("COL_RO2",log); anl_conf->col_lo2 = anl_get_col("COL_LO2",log); } anl_conf->col_timestamp = anl_get_col("COL_TIMESTAMP",log); anl_conf->col_rpm = anl_get_col("COL_RPM",log); anl_conf->col_temp = anl_get_col("COL_TEMP",log); anl_conf->col_map = anl_get_col("COL_MAP",log); anl_conf->col_maf = anl_get_col("COL_MAF",log); anl_conf->col_cl = anl_get_col("COL_CL",log); anl_conf->col_blm = anl_get_col("COL_BLM",log); anl_conf->col_wot = anl_get_col("COL_WOT",log); }
/** @brief extract a field from a delimited string. * * copies at most <i>n</i> characters from field <i>i</i> of * <i>delim</i>-delimited string <i>ct</i> into <i>cs</i>. * * @param dest destination buffer * @param line delimited string * @param n max chars to copy into buffer * @param i field to be copied (0-based) * @param delim delimiter of ct * * @return number of chars copied into buffer, or -1 if i is greater * than the number of fields in ct */ int get_line_field(char *dest, const char *line, size_t n, int i, const char *delim) { int field_len; char *fstart, *fend; /* start and end of field at index i */ if (!(delim && delim[0])) { strncpy(dest, line, n); dest[n] = 0; return (strlen(dest)); } fstart = field_start(line, i + 1, delim); if (fstart == NULL) { dest[0] = 0x00; return -1; } fend = strstr(fstart, delim); if (fend == NULL) { /* cast away const-ness of line */ fend = (char *) line + strlen(line) - 1; while (*fend == '\n' || *fend == '\r') fend--; fend++; } /* fend is now pointing at the first char after the field */ field_len = (fend - fstart > n - 1 ? n - 1 : fend - fstart); strncpy(dest, fstart, field_len); dest[field_len] = '\0'; return field_len; }
int anl_get_col(char *copt, char *log) { char *cname = configopt_fatal(dconf,copt); /* get col name from conf file */ char *line; if(anl_conf->tunerpromode == 1) { line = line_start(log,1); /* second line in tunerpro */ } else { line = line_start(log,0); /* should always be first line ... */ } char *in; int x = 0; /* column index */ int y; /* slicer */ for(x=0;x<anl_conf->n_cols;x++) { in = csv_get_string(field_start(line,x)); if(in == NULL) continue; /* no input string */ y = 0; /* fix terminator (to ignore bracketed suffix) */ while(in[y] != 0 && in[y] != '(') y++; in[y] = 0; if(rf_strcmp(cname,in) == 1) { free(in); return x; /* found column */ } else { free(in); } } error("Couldn't find a column named %s in the log.\nYour log file may be in the wrong format, or the config file is incorrect.\nPlease check the parameter %s= in the config file...",cname,copt); return 0; }
int verify_line(char *line) { if(line == NULL) return 0; /* check for too many columns */ if(field_start(line,anl_conf->n_cols - 1) == NULL) { stats->badlines++; return 0; } /* check for not enough columns */ if(field_start(line,anl_conf->n_cols) != NULL) { stats->badlines++; return 0; } stats->goodlines++; return 1; }
int get_line_pos(const char *line, int field_no, const char *d, int *start, int *end) { char *field, *field_end; field = field_start(line, field_no + 1, d); if (field == NULL) { *start = -1; *end = -1; return -1; } *start = field - line; field_end = strstr(field, d); if (field_end == NULL) { /* last field of line. comparison against *start handles the case where the field is empty. */ *end = strlen(line) - 1; /* don't include linebreaks as field data. */ while (line[*end] == '\n' || line[*end] == '\r') (*end)--; if (*end < *start) *end = *start; } else if (field_end == field) { /* empty field */ *end = field_end - line; } else { *end = field_end - line - 1; } /* if start & end indexes are the same, the field could either be empty or a single charalineer */ if (*start == *end) { /* if empty, start of field will either be a delimiter (if in the middle of the line) or an EOL or null terminator (end of line) */ if (line[*start] == '\0' || line[*start] == '\n' || line[*start] == '\r' || strncmp(line + *start, d, strlen(d)) == 0) { return 0; } return 1; } else { return *end - *start + 1; } }
float csvfloat(char *line, int f) { return csv_get_float(field_start(line,f)); }
int csvint(char *line, int f) { return csv_get_int(field_start(line,f)); }
int main(int argc, char **argv) { const char *b, *e, *p; const char *output_file = NULL; int f, tot, last, linenum, err, parse_err; struct timer *t = NULL, *t2; struct eb32_node *n; int val, test; int array[5]; int filter_acc_delay = 0, filter_acc_count = 0; int filter_time_resp = 0; int skip_fields = 1; argc--; argv++; while (argc > 0) { if (*argv[0] != '-') break; if (strcmp(argv[0], "-ad") == 0) { if (argc < 2) die("missing option for -ad"); argc--; argv++; filter |= FILT_ACC_DELAY; filter_acc_delay = atol(*argv); } else if (strcmp(argv[0], "-ac") == 0) { if (argc < 2) die("missing option for -ac"); argc--; argv++; filter |= FILT_ACC_COUNT; filter_acc_count = atol(*argv); } else if (strcmp(argv[0], "-rt") == 0) { if (argc < 2) die("missing option for -rt"); argc--; argv++; filter |= FILT_TIME_RESP; filter_time_resp = atol(*argv); } else if (strcmp(argv[0], "-RT") == 0) { if (argc < 2) die("missing option for -RT"); argc--; argv++; filter |= FILT_TIME_RESP | FILT_INVERT_TIME_RESP; filter_time_resp = atol(*argv); } else if (strcmp(argv[0], "-s") == 0) { if (argc < 2) die("missing option for -s"); argc--; argv++; skip_fields = atol(*argv); } else if (strcmp(argv[0], "-e") == 0) filter |= FILT_ERRORS_ONLY; else if (strcmp(argv[0], "-E") == 0) filter |= FILT_ERRORS_ONLY | FILT_INVERT_ERRORS; else if (strcmp(argv[0], "-c") == 0) filter |= FILT_COUNT_ONLY; else if (strcmp(argv[0], "-q") == 0) filter |= FILT_QUIET; else if (strcmp(argv[0], "-v") == 0) filter_invert = !filter_invert; else if (strcmp(argv[0], "-gt") == 0) filter |= FILT_GRAPH_TIMERS; else if (strcmp(argv[0], "-pct") == 0) filter |= FILT_PERCENTILE; else if (strcmp(argv[0], "-o") == 0) { if (output_file) die("Fatal: output file name already specified.\n"); if (argc < 2) die("Fatal: missing output file name.\n"); output_file = argv[1]; } argc--; argv++; } if (!filter) die("No action specified.\n"); if (filter & FILT_ACC_COUNT && !filter_acc_count) filter_acc_count=1; if (filter & FILT_ACC_DELAY && !filter_acc_delay) filter_acc_delay = 1; linenum = 0; tot = 0; parse_err = 0; while ((line = fgets2(stdin)) != NULL) { linenum++; test = 1; if (filter & FILT_TIME_RESP) { int tps; /* only report lines with response times larger than filter_time_resp */ b = field_start(line, TIME_FIELD + skip_fields); if (!*b) { truncated_line(linenum, line); continue; } e = field_stop(b + 1); /* we have field TIME_FIELD in [b]..[e-1] */ p = b; err = 0; for (f = 0; f < 4 && *p; f++) { tps = str2ic(p); if (tps < 0) { tps = -1; err = 1; } SKIP_CHAR(p, '/'); } if (f < 4) { parse_err++; continue; } test &= (tps >= filter_time_resp) ^ !!(filter & FILT_INVERT_TIME_RESP); } if (filter & FILT_ERRORS_ONLY) { /* only report erroneous status codes */ b = field_start(line, STATUS_FIELD + skip_fields); if (!*b) { truncated_line(linenum, line); continue; } if (*b == '-') { test &= !!(filter & FILT_INVERT_ERRORS); } else { val = strl2ui(b, 3); test &= (val >= 500 && val <= 599) ^ !!(filter & FILT_INVERT_ERRORS); } } if (filter & (FILT_ACC_COUNT|FILT_ACC_DELAY)) { b = field_start(line, ACCEPT_FIELD + skip_fields); if (!*b) { truncated_line(linenum, line); continue; } tot++; val = convert_date(b); //printf("date=%s => %d\n", b, val); if (val < 0) { parse_err++; continue; } t2 = insert_value(&timers[0], &t, val); t2->count++; continue; } if (filter & (FILT_GRAPH_TIMERS|FILT_PERCENTILE)) { int f; b = field_start(line, TIME_FIELD + skip_fields); if (!*b) { truncated_line(linenum, line); continue; } e = field_stop(b + 1); /* we have field TIME_FIELD in [b]..[e-1] */ p = b; err = 0; for (f = 0; f < 5 && *p; f++) { array[f] = str2ic(p); if (array[f] < 0) { array[f] = -1; err = 1; } SKIP_CHAR(p, '/'); } if (f < 5) { parse_err++; continue; } /* if we find at least one negative time, we count one error * with a time equal to the total session time. This will * emphasize quantum timing effects associated to known * timeouts. Note that on some buggy machines, it is possible * that the total time is negative, hence the reason to reset * it. */ if (filter & FILT_GRAPH_TIMERS) { if (err) { if (array[4] < 0) array[4] = -1; t2 = insert_timer(&timers[0], &t, array[4]); // total time t2->count++; } else { int v; t2 = insert_timer(&timers[1], &t, array[0]); t2->count++; // req t2 = insert_timer(&timers[2], &t, array[2]); t2->count++; // conn t2 = insert_timer(&timers[3], &t, array[3]); t2->count++; // resp v = array[4] - array[0] - array[1] - array[2] - array[3]; // data time if (v < 0 && !(filter & FILT_QUIET)) fprintf(stderr, "ERR: %s (%d %d %d %d %d => %d)\n", line, array[0], array[1], array[2], array[3], array[4], v); t2 = insert_timer(&timers[4], &t, v); t2->count++; tot++; } } else { /* percentile */ if (err) { if (array[4] < 0) array[4] = -1; t2 = insert_value(&timers[0], &t, array[4]); // total time t2->count++; } else { int v; t2 = insert_value(&timers[1], &t, array[0]); t2->count++; // req t2 = insert_value(&timers[2], &t, array[2]); t2->count++; // conn t2 = insert_value(&timers[3], &t, array[3]); t2->count++; // resp v = array[4] - array[0] - array[1] - array[2] - array[3]; // data time if (v < 0 && !(filter & FILT_QUIET)) fprintf(stderr, "ERR: %s (%d %d %d %d %d => %d)\n", line, array[0], array[1], array[2], array[3], array[4], v); t2 = insert_value(&timers[4], &t, v); t2->count++; tot++; } } continue; } test ^= filter_invert; if (!test) continue; /* all other cases mean we just want to count lines */ tot++; if (!(filter & FILT_COUNT_ONLY)) puts(line); } if (t) free(t); if (filter & FILT_COUNT_ONLY) { printf("%d\n", tot); exit(0); } if (filter & FILT_ERRORS_ONLY) exit(0); if (filter & (FILT_ACC_COUNT|FILT_ACC_DELAY)) { /* sort and count all timers. Output will look like this : * <accept_date> <delta_ms from previous one> <nb entries> */ n = eb32_first(&timers[0]); if (n) last = n->key; while (n) { unsigned int d, h, m, s, ms; t = container_of(n, struct timer, node); h = n->key; d = h - last; last = h; if (d >= filter_acc_delay && t->count >= filter_acc_count) { ms = h % 1000; h = h / 1000; s = h % 60; h = h / 60; m = h % 60; h = h / 60; tot++; printf("%02d:%02d:%02d.%03d %d %d %d\n", h, m, s, ms, last, d, t->count); } n = eb32_next(n); } }