Support --stats-every with intervals <60 seconds. Add --json-stats-every option
Previously, json stats updates were fixed to 60 seconds, and using --stats--every with an interval less than 60 seconds produced confusing results. This commit fixes --stats-every with short intervals, and adds --json-stats-every to control the json stats update interval. Note that if --json-stats-every is not a multiple of 60 seconds, then the 1-/5-/15-minute data may not include all data up to the current time (in that case, the most recent data is reflected in the "latest" stats) This implements the alternative approach discussed in PR #89
This commit is contained in:
parent
490b5ce36f
commit
f1c576b657
61
dump1090.c
61
dump1090.c
|
|
@ -116,6 +116,7 @@ static void modesInitConfig(void) {
|
|||
Modes.net_heartbeat_interval = MODES_NET_HEARTBEAT_INTERVAL;
|
||||
Modes.interactive_display_ttl = MODES_INTERACTIVE_DISPLAY_TTL;
|
||||
Modes.json_interval = 1000;
|
||||
Modes.json_stats_interval = 60000;
|
||||
Modes.json_location_accuracy = 1;
|
||||
Modes.maxRange = 1852 * 300; // 300NM default max range
|
||||
Modes.mode_ac_auto = 1;
|
||||
|
|
@ -345,7 +346,8 @@ static void showHelp(void)
|
|||
"--quiet Disable output to stdout. Use for daemon applications\n"
|
||||
"--show-only <addr> Show only messages from the given ICAO on stdout\n"
|
||||
"--write-json <dir> Periodically write json output to <dir> (for serving by a separate webserver)\n"
|
||||
"--write-json-every <t> Write json output every t seconds (default 1)\n"
|
||||
"--write-json-every <t> Write json aircraft output every t seconds (default 1)\n"
|
||||
"--json-stats-every <t> Write json stats output every t seconds (default 60)\n"
|
||||
"--json-location-accuracy <n> Accuracy of receiver location in json metadata: 0=no location, 1=approximate, 2=exact\n"
|
||||
#if 0
|
||||
"--dcfilter Apply a 1Hz DC filter to input data (requires more CPU)\n"
|
||||
|
|
@ -356,11 +358,16 @@ static void showHelp(void)
|
|||
);
|
||||
}
|
||||
|
||||
static void display_total_stats(void)
|
||||
// Accumulate stats data from stats_current to stats_periodic, stats_alltime and stats_latest;
|
||||
// reset stats_current
|
||||
static void flush_stats(uint64_t now)
|
||||
{
|
||||
struct stats added;
|
||||
add_stats(&Modes.stats_alltime, &Modes.stats_current, &added);
|
||||
display_stats(&added);
|
||||
add_stats(&Modes.stats_current, &Modes.stats_periodic, &Modes.stats_periodic);
|
||||
add_stats(&Modes.stats_current, &Modes.stats_alltime, &Modes.stats_alltime);
|
||||
add_stats(&Modes.stats_current, &Modes.stats_latest, &Modes.stats_latest);
|
||||
|
||||
reset_stats(&Modes.stats_current);
|
||||
Modes.stats_current.start = Modes.stats_current.end = now;
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -373,6 +380,7 @@ static void display_total_stats(void)
|
|||
static void backgroundTasks(void) {
|
||||
static uint64_t next_stats_display;
|
||||
static uint64_t next_stats_update;
|
||||
static uint64_t next_json_stats_update;
|
||||
static uint64_t next_json, next_history;
|
||||
|
||||
uint64_t now = mstime();
|
||||
|
|
@ -396,41 +404,41 @@ static void backgroundTasks(void) {
|
|||
// always update end time so it is current when requests arrive
|
||||
Modes.stats_current.end = mstime();
|
||||
|
||||
// 1-minute stats update
|
||||
if (now >= next_stats_update) {
|
||||
int i;
|
||||
|
||||
if (next_stats_update == 0) {
|
||||
next_stats_update = now + 60000;
|
||||
} else {
|
||||
Modes.stats_latest_1min = (Modes.stats_latest_1min + 1) % 15;
|
||||
Modes.stats_1min[Modes.stats_latest_1min] = Modes.stats_current;
|
||||
flush_stats(now); // Ensure stats_latest is up to date
|
||||
|
||||
add_stats(&Modes.stats_current, &Modes.stats_alltime, &Modes.stats_alltime);
|
||||
add_stats(&Modes.stats_current, &Modes.stats_periodic, &Modes.stats_periodic);
|
||||
// move stats_latest into 1-min ring buffer
|
||||
Modes.stats_newest_1min = (Modes.stats_newest_1min + 1) % 15;
|
||||
Modes.stats_1min[Modes.stats_newest_1min] = Modes.stats_latest;
|
||||
reset_stats(&Modes.stats_latest);
|
||||
|
||||
// recalculate 5-min window
|
||||
reset_stats(&Modes.stats_5min);
|
||||
for (i = 0; i < 5; ++i)
|
||||
add_stats(&Modes.stats_1min[(Modes.stats_latest_1min - i + 15) % 15], &Modes.stats_5min, &Modes.stats_5min);
|
||||
add_stats(&Modes.stats_1min[(Modes.stats_newest_1min - i + 15) % 15], &Modes.stats_5min, &Modes.stats_5min);
|
||||
|
||||
// recalculate 15-min window
|
||||
reset_stats(&Modes.stats_15min);
|
||||
for (i = 0; i < 15; ++i)
|
||||
add_stats(&Modes.stats_1min[i], &Modes.stats_15min, &Modes.stats_15min);
|
||||
|
||||
reset_stats(&Modes.stats_current);
|
||||
Modes.stats_current.start = Modes.stats_current.end = now;
|
||||
|
||||
if (Modes.json_dir)
|
||||
writeJsonToFile("stats.json", generateStatsJson);
|
||||
|
||||
next_stats_update += 60000;
|
||||
}
|
||||
}
|
||||
|
||||
// --stats-every display
|
||||
if (Modes.stats && now >= next_stats_display) {
|
||||
if (next_stats_display == 0) {
|
||||
next_stats_display = now + Modes.stats;
|
||||
} else {
|
||||
add_stats(&Modes.stats_periodic, &Modes.stats_current, &Modes.stats_periodic);
|
||||
flush_stats(now); // Ensure stats_periodic is up to date
|
||||
|
||||
display_stats(&Modes.stats_periodic);
|
||||
reset_stats(&Modes.stats_periodic);
|
||||
|
||||
|
|
@ -442,6 +450,17 @@ static void backgroundTasks(void) {
|
|||
}
|
||||
}
|
||||
|
||||
// json stats update
|
||||
if (Modes.json_dir && now >= next_json_stats_update) {
|
||||
if (next_json_stats_update == 0) {
|
||||
next_json_stats_update = now + Modes.json_stats_interval;
|
||||
} else {
|
||||
flush_stats(now); // Ensure everything we'll write is up to date
|
||||
writeJsonToFile("stats.json", generateStatsJson);
|
||||
next_json_stats_update += Modes.json_stats_interval;
|
||||
}
|
||||
}
|
||||
|
||||
if (Modes.json_dir && now >= next_json) {
|
||||
writeJsonToFile("aircraft.json", generateAircraftJson);
|
||||
next_json = now + Modes.json_interval;
|
||||
|
|
@ -631,6 +650,8 @@ int main(int argc, char **argv) {
|
|||
Modes.stats_range_histo = 1;
|
||||
} else if (!strcmp(argv[j],"--stats-every") && more) {
|
||||
Modes.stats = (uint64_t) (1000 * atof(argv[++j]));
|
||||
} else if (!strcmp(argv[j],"--json-stats-every") && more) {
|
||||
Modes.json_stats_interval = (uint64_t) (1000 * atof(argv[++j]));
|
||||
} else if (!strcmp(argv[j],"--snip") && more) {
|
||||
snipMode(atoi(argv[++j]));
|
||||
exit(0);
|
||||
|
|
@ -702,6 +723,7 @@ int main(int argc, char **argv) {
|
|||
Modes.stats_current.start = Modes.stats_current.end =
|
||||
Modes.stats_alltime.start = Modes.stats_alltime.end =
|
||||
Modes.stats_periodic.start = Modes.stats_periodic.end =
|
||||
Modes.stats_latest.start = Modes.stats_latest.end =
|
||||
Modes.stats_5min.start = Modes.stats_5min.end =
|
||||
Modes.stats_15min.start = Modes.stats_15min.end = mstime();
|
||||
|
||||
|
|
@ -778,9 +800,10 @@ int main(int argc, char **argv) {
|
|||
|
||||
interactiveCleanup();
|
||||
|
||||
// If --stats were given, print statistics
|
||||
// If --stats was given, print final statistics
|
||||
if (Modes.stats) {
|
||||
display_total_stats();
|
||||
flush_stats(0);
|
||||
display_stats(&Modes.stats_alltime);
|
||||
}
|
||||
|
||||
sdrClose();
|
||||
|
|
|
|||
16
dump1090.h
16
dump1090.h
|
|
@ -355,6 +355,7 @@ struct _Modes { // Internal state
|
|||
int mlat; // Use Beast ascii format for raw data output, i.e. @...; iso *...;
|
||||
char *json_dir; // Path to json base directory, or NULL not to write json.
|
||||
uint64_t json_interval; // Interval between rewriting the json aircraft file, in milliseconds; also the advertised map refresh interval
|
||||
uint64_t json_stats_interval; // Interval between rewriting the json stats file, in milliseconds
|
||||
int json_location_accuracy; // Accuracy of location metadata: 0=none, 1=approx, 2=exact
|
||||
|
||||
int json_aircraft_history_next;
|
||||
|
|
@ -373,13 +374,14 @@ struct _Modes { // Internal state
|
|||
struct aircraft *aircrafts;
|
||||
|
||||
// Statistics
|
||||
struct stats stats_current;
|
||||
struct stats stats_alltime;
|
||||
struct stats stats_periodic;
|
||||
struct stats stats_1min[15];
|
||||
int stats_latest_1min;
|
||||
struct stats stats_5min;
|
||||
struct stats stats_15min;
|
||||
struct stats stats_current; // Currently accumulating stats, this is where all stats are initially collected
|
||||
struct stats stats_alltime; // Accumulated stats since the start of the process
|
||||
struct stats stats_periodic; // Accumulated stats since the last periodic stats display (--stats-every)
|
||||
struct stats stats_latest; // Accumulated stats since the end of the last 1-minute period
|
||||
struct stats stats_1min[15]; // Accumulated stats for a full 1-minute window; this is a ring buffer maintaining a history of 15 minutes
|
||||
int stats_newest_1min; // Index into stats_1min of the most recent 1-minute window
|
||||
struct stats stats_5min; // Accumulated stats from the last 5 complete 1-minute windows
|
||||
struct stats stats_15min; // Accumulated stats from the last 15 complete 1-minute windows
|
||||
};
|
||||
|
||||
extern struct _Modes Modes;
|
||||
|
|
|
|||
7
net_io.c
7
net_io.c
|
|
@ -1831,10 +1831,10 @@ char *generateStatsJson(const char *url_path, int *len) {
|
|||
MODES_NOTUSED(url_path);
|
||||
|
||||
p = safe_snprintf(p, end, "{\n");
|
||||
p = appendStatsJson(p, end, &Modes.stats_current, "latest");
|
||||
p = appendStatsJson(p, end, &Modes.stats_latest, "latest");
|
||||
p = safe_snprintf(p, end, ",\n");
|
||||
|
||||
p = appendStatsJson(p, end, &Modes.stats_1min[Modes.stats_latest_1min], "last1min");
|
||||
p = appendStatsJson(p, end, &Modes.stats_1min[Modes.stats_newest_1min], "last1min");
|
||||
p = safe_snprintf(p, end, ",\n");
|
||||
|
||||
p = appendStatsJson(p, end, &Modes.stats_5min, "last5min");
|
||||
|
|
@ -1843,8 +1843,7 @@ char *generateStatsJson(const char *url_path, int *len) {
|
|||
p = appendStatsJson(p, end, &Modes.stats_15min, "last15min");
|
||||
p = safe_snprintf(p, end, ",\n");
|
||||
|
||||
add_stats(&Modes.stats_alltime, &Modes.stats_current, &add);
|
||||
p = appendStatsJson(p, end, &add, "total");
|
||||
p = appendStatsJson(p, end, &Modes.stats_alltime, "total");
|
||||
p = safe_snprintf(p, end, "\n}\n");
|
||||
|
||||
if (p <= end) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue