aboutsummaryrefslogtreecommitdiffstats
path: root/web/stream.tg13.gathering.org/streamstats.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'web/stream.tg13.gathering.org/streamstats.cpp')
-rw-r--r--web/stream.tg13.gathering.org/streamstats.cpp217
1 files changed, 217 insertions, 0 deletions
diff --git a/web/stream.tg13.gathering.org/streamstats.cpp b/web/stream.tg13.gathering.org/streamstats.cpp
new file mode 100644
index 0000000..e81419f
--- /dev/null
+++ b/web/stream.tg13.gathering.org/streamstats.cpp
@@ -0,0 +1,217 @@
+#include <stdio.h>
+#include <string.h>
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+#include <stdlib.h>
+
+using namespace std;
+
+map<string, string> port_desc = {
+ { "3013", "main (3013)" },
+ { "3014", "main-sd (3014)" },
+ { "3015", "webcam (3015)" },
+ { "3016", "webcam-south (3016)" },
+ { "3017", "webcam-south-transcode (3017)" },
+ { "3018", "webcam-fisheye (3018)" },
+ { "5013", "main-transcode (5013)" },
+ { "5015", "webcam-transcode (5015)" },
+};
+
+struct Spec {
+ set<string> incl;
+ bool compare;
+};
+
+Spec parse_spec(const string &spec)
+{
+ Spec ret;
+ ret.compare = false;
+
+ if (spec == "compare") {
+ ret.compare = true;
+ return ret;
+ }
+ if (spec == "dontcare") {
+ return ret;
+ }
+
+ const char *ptr = spec.c_str();
+ if (strncmp(ptr, "compare:", 8) == 0) {
+ ptr += 8;
+ ret.compare = true;
+ }
+
+ for ( ;; ) {
+ const char *end = strchr(ptr, ',');
+ if (end == NULL) {
+ ret.incl.insert(ptr);
+ break;
+ } else {
+ ret.incl.insert(string(ptr, end));
+ ptr = end + 1;
+ }
+ }
+
+ return ret;
+}
+
+bool filter(const string &entry, const Spec &spec)
+{
+ if (spec.incl.empty()) {
+ return false;
+ }
+ return spec.incl.count(entry) == 0;
+}
+
+vector<string> get_stream_id(const string& port, const string &proto, const string &audience,
+ const Spec& port_spec, const Spec &proto_spec, const Spec &audience_spec)
+{
+ vector<string> keys;
+ if (port_spec.compare) {
+ if (port_desc.count(port)) {
+ keys.push_back(port_desc[port]);
+ } else {
+ char buf[256];
+ sprintf(buf, "___%s___", port.c_str());
+ keys.push_back(buf);
+ }
+ }
+ if (proto_spec.compare) {
+ keys.push_back(proto);
+ }
+ if (audience_spec.compare) {
+ keys.push_back(audience);
+ }
+ return keys;
+}
+
+string get_stream_desc(const vector<string> &stream_id)
+{
+ string ret;
+ for (int i = 0; i < stream_id.size(); ++i) {
+ if (i != 0) {
+ ret += ",";
+ }
+ ret += stream_id[i];
+ }
+ return ret;
+}
+
+int main(int argc, char **argv)
+{
+ Spec port_spec = parse_spec(argv[2]);
+ Spec proto_spec = parse_spec(argv[3]);
+ Spec audience_spec = parse_spec(argv[4]);
+
+ map<string, map<vector<string>, int> > lines;
+ map<vector<string>, int> stream_ids;
+ vector<string> stream_descs;
+
+ // Parse the log.
+ FILE *fp;
+ if (strcmp(argv[1], "-") == 0) {
+ fp = stdin;
+ } else {
+ fp = fopen(argv[1], "r");
+ }
+ while (!feof(fp)) {
+ char buf[1024];
+ fgets(buf, 1024, fp);
+
+ if (buf == NULL) {
+ break;
+ }
+ char *ptr = strchr(buf, '\n');
+ if (ptr != NULL) {
+ *ptr = 0;
+ }
+
+ char *date = strtok(buf, " ");
+ char *port = strtok(NULL, " ");
+ char *proto = strtok(NULL, " ");
+ char *audience = strtok(NULL, " ");
+ char *count = strtok(NULL, " ");
+
+ if (date == NULL || port == NULL || proto == NULL || audience == NULL || count == NULL) {
+ continue;
+ }
+
+ if (filter(port, port_spec)) {
+ continue;
+ }
+ if (filter(proto, proto_spec)) {
+ continue;
+ }
+ if (filter(audience, audience_spec)) {
+ continue;
+ }
+
+ vector<string> stream_id = get_stream_id(port, proto, audience, port_spec, proto_spec, audience_spec);
+ if (stream_ids.count(stream_id) == 0) {
+ int stream_id_num = stream_ids.size();
+ stream_ids.insert(make_pair(stream_id, stream_id_num));
+ stream_descs.push_back(get_stream_desc(stream_id));
+ }
+ lines[date][stream_id] += atoi(count);
+ }
+ fclose(fp);
+
+ // Output.
+ char *data_file = tempnam(NULL, "data");
+ FILE *datafp = fopen(data_file, "w");
+ if (datafp == NULL) {
+ perror(data_file);
+ exit(1);
+ }
+
+ vector<int> cols(stream_ids.size());
+ for (auto& it : lines) {
+ const string& date = it.first;
+
+ for (const auto& it2 : stream_ids) {
+ const vector<string>& stream_id = it2.first;
+ int stream_id_num = it2.second;
+
+ cols[stream_id_num] = it.second[stream_id]; // note: might zero-initialize
+ }
+ fprintf(datafp, "%s", date.c_str());
+ for (int i = 0; i < cols.size(); ++i) {
+ fprintf(datafp, " %d", cols[i]);
+ }
+ fprintf(datafp, "\n");
+ }
+ fclose(datafp);
+
+ // Make gnuplot script.
+ char *plot_file = tempnam(NULL, "plot");
+ FILE *plotfp = fopen(plot_file, "w");
+ if (plotfp == NULL) {
+ perror(plot_file);
+ exit(1);
+ }
+
+ fprintf(plotfp, "set terminal png\n");
+ fprintf(plotfp, "set xdata time\n");
+ fprintf(plotfp, "set timefmt \"20%%y-%%m-%%d-%%H:%%M:%%S\"\n");
+ fprintf(plotfp, "set xtics axis \"2000-00-00-01:00:00\"\n");
+ fprintf(plotfp, "set format x \"%%H\"\n");
+
+ fprintf(plotfp, "plot");
+ for (int i = 0; i < cols.size(); ++i) {
+ if (i == 0) {
+ fprintf(plotfp, " ");
+ } else {
+ fprintf(plotfp, ",");
+ }
+ fprintf(plotfp, "\"%s\" using 1:%d title \"%s\" with lines", data_file, i + 2, stream_descs[i].c_str());
+ }
+ fprintf(plotfp, "\n");
+
+ fclose(plotfp);
+
+ char buf[1024];
+ sprintf(buf, "gnuplot < %s", plot_file);
+ system(buf);
+}