add tcp rtt measurement / graph range improvements
folkert
11 years ago
7 | 7 | { |
8 | 8 | memset(data, 0x00, sizeof(stats_t)); |
9 | 9 | |
10 | data -> min = 999999999999.0; | |
10 | data -> min = MY_DOUBLE_INF; | |
11 | 11 | data -> max = -data -> min; |
12 | 12 | } |
13 | 13 |
15 | 15 | #define SSL_CTX void |
16 | 16 | #define BIO void |
17 | 17 | #endif |
18 | ||
19 | #define MY_DOUBLE_INF 999999999999999.9 | |
18 | 20 | |
19 | 21 | #ifdef TCP_TFO |
20 | 22 | #ifndef MSG_FASTOPEN |
171 | 171 | Show the version and exit. |
172 | 172 | |
173 | 173 | .SH GRAPH |
174 | The graph in the ncurses uses colors to encode a meaning. Green: value is less than 1 block. Red: the value did not fit in the graph. Blue: the value was limitted by --graph-limit. | |
174 | The graph in the ncurses uses colors to encode a meaning. Green: value is less than 1 block. Red: the value did not fit in the graph. Blue: the value was limitted by --graph-limit. Cyan: no measurement for that point in time. | |
175 | 175 | |
176 | 176 | .SH KEYS |
177 | 177 | Press <CTRL> + <c> to exit the program. It will display a summary of what was measured. |
37 | 37 | #ifdef NC |
38 | 38 | #include "nc.h" |
39 | 39 | #endif |
40 | ||
41 | #define MI_MA 999999999.9 | |
42 | 40 | |
43 | 41 | static volatile int stop = 0; |
44 | 42 | |
583 | 581 | memset(&(*aggregates)[*n_aggregates - 1], 0x00, sizeof(aggregate_t)); |
584 | 582 | |
585 | 583 | (*aggregates)[*n_aggregates - 1].interval = atoi(dummy); |
586 | (*aggregates)[*n_aggregates - 1].max = -MI_MA; | |
587 | (*aggregates)[*n_aggregates - 1].min = MI_MA; | |
584 | (*aggregates)[*n_aggregates - 1].max = -MY_DOUBLE_INF; | |
585 | (*aggregates)[*n_aggregates - 1].min = MY_DOUBLE_INF; | |
588 | 586 | |
589 | 587 | dummy = strchr(dummy, ','); |
590 | 588 | if (dummy) |
650 | 648 | |
651 | 649 | aggregates[index].value = |
652 | 650 | aggregates[index].sd = 0.0; |
653 | aggregates[index].min = MI_MA; | |
654 | aggregates[index].max = -MI_MA; | |
651 | aggregates[index].min = MY_DOUBLE_INF; | |
652 | aggregates[index].max = -MY_DOUBLE_INF; | |
655 | 653 | aggregates[index].n_values = 0; |
656 | 654 | aggregates[index].last_ts = cur_ts; |
657 | 655 | } |
941 | 939 | int n_aggregates = 0; |
942 | 940 | aggregate_t *aggregates = NULL; |
943 | 941 | char *au_dummy = NULL, *ap_dummy = NULL; |
944 | stats_t t_connect, t_request, t_total, t_resolve, t_ssl, stats_to; | |
942 | stats_t t_connect, t_request, t_total, t_resolve, t_ssl, stats_to, tcp_rtt_stats; | |
945 | 943 | double total_took = 0; |
946 | 944 | char first_resolve = 1; |
947 | double graph_limit = 9999999.9; | |
945 | double graph_limit = MY_DOUBLE_INF; | |
948 | 946 | char nc_graph = 1; |
949 | 947 | char adaptive_interval = 0; |
950 | double show_slow_log = 9999999.0; | |
948 | double show_slow_log = MY_DOUBLE_INF; | |
951 | 949 | |
952 | 950 | init_statst(&t_resolve); |
953 | 951 | init_statst(&t_connect); |
956 | 954 | init_statst(&t_ssl); |
957 | 955 | |
958 | 956 | init_statst(&stats_to); |
957 | #if defined(linux) || defined(__FreeBSD__) | |
958 | init_statst(&tcp_rtt_stats); | |
959 | #endif | |
959 | 960 | |
960 | 961 | static struct option long_options[] = |
961 | 962 | { |
1537 | 1538 | double their_est_ts = -1.0, toff_diff_ts = -1.0; |
1538 | 1539 | char tfo_success = 0; |
1539 | 1540 | double ssl_handshake = 0.0; |
1540 | #ifdef TCP_TFO | |
1541 | #if defined(linux) || defined(__FreeBSD__) | |
1541 | 1542 | struct tcp_info info; |
1542 | 1543 | socklen_t info_len = sizeof(struct tcp_info); |
1543 | 1544 | #endif |
1875 | 1876 | } |
1876 | 1877 | #endif |
1877 | 1878 | |
1878 | #ifdef TCP_TFO | |
1879 | #if defined(linux) || defined(__FreeBSD__) | |
1879 | 1880 | if (getsockopt(fd, IPPROTO_TCP, TCP_INFO, &info, &info_len) == 0 && (info.tcpi_options & TCPI_OPT_SYN_DATA)) |
1880 | 1881 | tfo_success = 1; |
1881 | 1882 | /* printf("%d %d %d %d %d %d\n", info.tcpi_retransmits, info.tcpi_unacked, info.tcpi_sacked, info.tcpi_lost, info.tcpi_retrans, info.tcpi_fackets); */ |
1883 | ||
1884 | update_statst(&tcp_rtt_stats, (double)info.tcpi_rtt / 1000.0); | |
1882 | 1885 | #endif |
1883 | 1886 | |
1884 | 1887 | if (!persistent_connections) |
1893 | 1896 | dummy_ms = (dend - dstart) * 1000.0; |
1894 | 1897 | update_statst(&t_total, dummy_ms); |
1895 | 1898 | |
1896 | /* estimate of when other end started replying */ | |
1897 | their_est_ts = (dend + dafter_connect) / 2.0; | |
1899 | their_est_ts = (dend + dafter_connect) / 2.0; /* estimate of when other end started replying */ | |
1898 | 1900 | toff_diff_ts = ((double)their_ts - their_est_ts) * 1000.0; |
1899 | 1901 | update_statst(&stats_to, toff_diff_ts); |
1900 | 1902 | |
2076 | 2078 | emit_statuslines(get_ts() - started_at); |
2077 | 2079 | #ifdef NC |
2078 | 2080 | if (ncurses_mode) |
2079 | update_stats(&t_resolve, &t_connect, &t_request, &t_total, &t_ssl, curncount, err, sc, fp, use_tfo, nc_graph, use_ssl, &stats_to); | |
2081 | update_stats(&t_resolve, &t_connect, &t_request, &t_total, &t_ssl, curncount, err, sc, fp, use_tfo, nc_graph, use_ssl, &stats_to, &tcp_rtt_stats); | |
2080 | 2082 | #endif |
2081 | 2083 | |
2082 | 2084 | free(sc); |
26 | 26 | char **slow_history = NULL, **fast_history = NULL; |
27 | 27 | int window_history_n = 0; |
28 | 28 | |
29 | double graph_limit = 99999999.9; | |
29 | double graph_limit = MY_DOUBLE_INF; | |
30 | 30 | double hz = 1.0; |
31 | ||
32 | double graph_avg = 0.0, graph_sd = 0.0, graph_min = 999999999999.0, graph_max = -99999999999999999.0; | |
33 | int graph_n = 0; | |
34 | 31 | |
35 | 32 | double *history = NULL, *history_temp = NULL, *history_fft = NULL; |
36 | 33 | char *history_set = NULL; |
463 | 460 | |
464 | 461 | void draw_graph(double val) |
465 | 462 | { |
466 | int index = 0, n = min(max_x, history_n); | |
463 | int index = 0, loop_n = min(max_x, history_n), n = 0, n2 = 0; | |
467 | 464 | double avg = 0, sd = 0; |
468 | double mi = 0.0, ma = 0.0, diff = 0.0; | |
469 | ||
470 | graph_min = min(val, graph_min); | |
471 | graph_max = max(val, graph_max); | |
472 | ||
473 | graph_avg += val; | |
474 | graph_sd += val * val; | |
475 | graph_n++; | |
476 | ||
477 | avg = graph_avg / (double)graph_n; | |
478 | sd = sqrt((graph_sd / (double)graph_n) - pow(avg, 2.0)); | |
479 | ||
480 | mi = max(graph_min, max(0.0, avg - sd)); | |
481 | ma = min(graph_max, avg + sd); | |
465 | double avg2 = 0, sd2 = 0; | |
466 | double mi = MY_DOUBLE_INF, ma = -MY_DOUBLE_INF, diff = 0.0; | |
467 | ||
468 | for(index=0; index<loop_n; index++) | |
469 | { | |
470 | double val = history[index]; | |
471 | ||
472 | if (!history_set[index]) | |
473 | continue; | |
474 | ||
475 | mi = min(val, mi); | |
476 | ma = max(val, ma); | |
477 | ||
478 | avg += val; | |
479 | sd += val * val; | |
480 | n++; | |
481 | } | |
482 | ||
483 | avg /= (double)n; | |
484 | sd = sqrt((sd / (double)n) - pow(avg, 2.0)); | |
485 | ||
486 | mi = max(mi, avg - sd); | |
487 | ma = min(ma, avg + sd); | |
488 | ||
489 | for(index=0; index<loop_n; index++) | |
490 | { | |
491 | double val = history[index]; | |
492 | ||
493 | if (!history_set[index]) | |
494 | continue; | |
495 | ||
496 | if (val < mi || val > ma) | |
497 | continue; | |
498 | ||
499 | avg2 += val; | |
500 | sd2 += val * val; | |
501 | n2++; | |
502 | } | |
503 | ||
504 | avg2 /= (double)n2; | |
505 | sd2 = sqrt((sd2 / (double)n2) - pow(avg2, 2.0)); | |
506 | ||
507 | mi = max(mi, avg2 - sd2); | |
508 | ma = min(ma, avg2 + sd2); | |
482 | 509 | diff = ma - mi; |
483 | 510 | |
484 | 511 | if (diff == 0.0) |
491 | 518 | |
492 | 519 | /* fprintf(stderr, "%d| %f %f %f %f\n", h_stats.n, mi, avg, ma, sd); */ |
493 | 520 | |
494 | for(index=0; index<n; index++) | |
521 | for(index=0; index<loop_n; index++) | |
495 | 522 | { |
496 | 523 | char overflow = 0, limitter = 0; |
497 | 524 | double val = 0, height = 0; |
498 | int i_h = 0; | |
525 | int i_h = 0, x = max_x - (1 + index); | |
526 | ||
527 | if (!history_set[index]) | |
528 | { | |
529 | mvwchgat(w_stats, stats_h - 1, x, 1, A_REVERSE, C_CYAN, NULL); | |
530 | continue; | |
531 | } | |
499 | 532 | |
500 | 533 | if (history[index] < graph_limit) |
501 | 534 | val = history[index]; |
516 | 549 | i_h = (int)(height * stats_h); |
517 | 550 | /* fprintf(stderr, "%d %f %f %d %d\n", index, history[index], height, i_h, overflow); */ |
518 | 551 | |
519 | draw_column(w_stats, max_x - (1 + index), i_h, overflow, limitter); | |
520 | } | |
521 | } | |
522 | ||
523 | void update_stats(stats_t *resolve, stats_t *connect, stats_t *request, stats_t *total, stats_t *ssl_setup, int n_ok, int n_fail, const char *last_connect_str, const char *fp, char use_tfo, char dg, char use_ssl, stats_t *st_to) | |
552 | draw_column(w_stats, x, i_h, overflow, limitter); | |
553 | } | |
554 | } | |
555 | ||
556 | void update_stats(stats_t *resolve, stats_t *connect, stats_t *request, stats_t *total, stats_t *ssl_setup, int n_ok, int n_fail, const char *last_connect_str, const char *fp, char use_tfo, char dg, char use_ssl, stats_t *st_to, stats_t *tcp_rtt_stats) | |
524 | 557 | { |
525 | 558 | double k = 0.0; |
526 | 559 | char force_redraw = 0; |
561 | 594 | mvwprintw(w_stats, 0, 45, " %6s %6s %6s %6s %6s", "cur", "min", "avg", "max", "sd"); |
562 | 595 | mvwprintw(w_stats, 1, 45, "t offst: %6.2f %6.2f %6.2f %6.2f %6.2f", |
563 | 596 | st_to -> cur, st_to -> min, st_to -> avg / (double)st_to -> n, st_to -> max, calc_sd(st_to)); |
597 | ||
598 | #if defined(linux) || defined(__FreeBSD__) | |
599 | mvwprintw(w_stats, 2, 45, "tcp rtt: %6.2f %6.2f %6.2f %6.2f %6.2f", | |
600 | tcp_rtt_stats -> cur, tcp_rtt_stats -> min, tcp_rtt_stats -> avg / (double)tcp_rtt_stats -> n, tcp_rtt_stats -> max, calc_sd(tcp_rtt_stats)); | |
601 | #endif | |
564 | 602 | } |
565 | 603 | |
566 | 604 | buflen = snprintf(buffer, sizeof buffer, "http result code: %s, SSL fingerprint: %s", last_connect_str, fp ? fp : "n/a"); |
9 | 9 | void my_beep(void); |
10 | 10 | void update_terminal(void); |
11 | 11 | void status_line(char *fmt, ...); |
12 | void update_stats(stats_t *resolve, stats_t *connect, stats_t *request, stats_t *total, stats_t *ssl_setup, int n_ok, int n_fail, const char *last_connect_str, const char *fp, char use_tfo, char dg, char use_ssl, stats_t *st_to); | |
12 | void update_stats(stats_t *resolve, stats_t *connect, stats_t *request, stats_t *total, stats_t *ssl_setup, int n_ok, int n_fail, const char *last_connect_str, const char *fp, char use_tfo, char dg, char use_ssl, stats_t *st_to, stats_t *tcp_rtt_stats); |
32 | 32 | If this script fails with the following error: |
33 | 33 | ValueError: Expecting object: [...] |
34 | 34 | then make sure the json-file ends with a ']' (without the quotes). |
35 | In sm cases this character is missing. | |
35 | In some cases this character is missing. | |
36 | 36 | |
37 | 37 | |
38 | 38 | Thanks to Thanatos for cookie and authentication support. |