summary refs log tree commit diff
diff options
context:
space:
mode:
authorLeah Neukirchen <leah@vuxu.org>2023-10-15 18:39:18 +0200
committerLeah Neukirchen <leah@vuxu.org>2023-10-15 18:39:18 +0200
commit9ed51426baac47f3fe4b45cc7a018b9f6eeff2dd (patch)
tree9b2cd8a30e2ce69f32e50aeb559c2ffdb6f00cc2
parent54ab34df86362785200e69d39f3b1fb5ee6cdce3 (diff)
downloadmico-9ed51426baac47f3fe4b45cc7a018b9f6eeff2dd.tar.gz
mico-9ed51426baac47f3fe4b45cc7a018b9f6eeff2dd.tar.xz
mico-9ed51426baac47f3fe4b45cc7a018b9f6eeff2dd.zip
add mico-sort
-rw-r--r--Makefile6
-rw-r--r--mico-sort.c170
2 files changed, 174 insertions, 2 deletions
diff --git a/Makefile b/Makefile
index 2f8f289..6abbfbf 100644
--- a/Makefile
+++ b/Makefile
@@ -1,12 +1,14 @@
 CFLAGS=-g -O2 -Wall -Wno-switch -Wextra -Wwrite-strings
 LDLIBS=-lzip
 
-all: mico-store mico-dump metra/metra
+ALL=mico-dump mico-sort mico-store metra/metra
+
+all: $(ALL)
 
 metra/metra: metra/metra.go metra/go.mod
 	cd metra && go build -v
 
 clean: FRC
-	rm -f mico-store mico-dump metra/metra
+	rm -f $(ALL)
 
 FRC:
diff --git a/mico-sort.c b/mico-sort.c
new file mode 100644
index 0000000..b070d67
--- /dev/null
+++ b/mico-sort.c
@@ -0,0 +1,170 @@
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <zip.h>
+
+#define STB_DS_IMPLEMENTATION
+#include "stb_ds.h"
+
+struct event {
+	int64_t t;
+	double v;
+};
+
+struct metric {
+	char *key;
+	struct event *value;  // array
+};
+
+struct metric *metrics;
+
+int
+timecmp(const void *a, const void *b)
+{
+        struct event *ea = (struct event *)a;
+        struct event *eb = (struct event *)b;
+
+	if (ea->t < eb->t)
+		return -1;
+	else if (ea->t > eb->t)
+		return 1;
+	else
+		return 0;  // needed?
+}
+
+static int
+mystrcmp(const void *a, const void *b)
+{
+	return strcmp((char *)a, (char *)b);
+}
+
+void
+normalize(char *name, char *end, char *out)
+{
+	// XXX handle ""
+
+	char *brace = strchr(name, '{');
+	end--;
+	if (!name || !brace || *end != '}') {
+		fprintf(stderr, "invalid name: %s\n", name);
+		return;
+	}
+
+	*end = ',';
+	printf("LINE %s", name);
+
+	char **labels = 0;
+	for (char *s = brace + 1; s && s < end; s = strchr(s + 1, ',')) {
+		if (*s == ',')
+			s++;
+		if (*s == ',')
+			continue;            /* empty label */
+		if (s == end)
+			break;
+
+		printf("label: %s\n", s);
+		arrput(labels, s);
+	}
+
+	qsort(labels, arrlen(labels), sizeof (char *), mystrcmp);
+
+	memcpy(out, name, brace - name);
+	char *t = out + (brace - name);
+	*t++ = '{';
+	for (ssize_t i = 0; i < arrlen(labels); i++) {
+		printf("append %s %d\n", labels[i], end - labels[i]);
+		char *stop = memccpy(t, labels[i], ',', end - labels[i]);
+		if (stop) {
+			printf("copied %d\n", stop - t);
+			t = stop;
+		} else {
+			break;
+		}
+	}
+	*t++ = '}';
+	*t = 0;
+
+	printf("outf=%s\n", out);
+}
+
+int
+main()
+{
+	sh_new_arena(metrics);
+
+	char name[255];
+	char lastname[255];
+
+	char *line = 0;
+	size_t linebuflen = 0;
+	ssize_t linelen = 0;
+	int i = 0;
+
+	while ((linelen = getdelim(&line, &linebuflen, '\n', stdin)) >= 0) {
+		char *start = strchr(line, ' ');
+		if (!start) {
+			fprintf(stderr, "skipping invalid line: %s\n", line);
+			continue;
+		}
+		char *start2 = strchr(start+1, ' ');
+		if (!start2) {
+			fprintf(stderr, "skipping invalid line: %s\n", line);
+			continue;
+		}
+
+		struct event ev;
+		char *eend;
+		ev.v = strtod(start, &eend);
+		ev.t = strtoll(eend+1, 0, 10);
+
+		if (start - line > (ssize_t)sizeof name) {
+			fprintf(stderr, "metric too long: %s\n", line);
+			continue;
+		}
+		memcpy(name, line, start-line);
+		name[start-line] = 0;
+
+// XXX		normalize(line, start, name);
+
+		// ts = ts / 1000;  // XXX
+
+		if (strcmp(name, lastname) == 0) {
+			// same name, skip hash lookup, use old i
+		} else {
+			if (shgeti(metrics, name) < 0)
+				shput(metrics, name, 0);
+			i = shgeti(metrics, name);
+		}
+
+		arrput(metrics[i].value, ev);
+
+		strcpy(lastname, name);
+	}
+
+	// XXX output order of metrics?
+
+	for (int m = 0; m < shlen(metrics); m++) {
+		// ensure events are ordered by time
+		qsort(metrics[m].value, arrlen(metrics[m].value),
+		    sizeof (struct event), timecmp);
+
+		int64_t t, pt = INT64_MIN;
+		double v;
+
+		for (ssize_t i = 0; i < arrlen(metrics[m].value); i++) {
+			t = metrics[m].value[i].t;
+			v = metrics[m].value[i].v;
+
+			if (t == pt) {
+				fprintf(stderr, "duplicate timestamp: %ld", t);
+				continue;
+			}
+
+			printf("%s %f %ld\n", metrics[m].key, v, t);
+
+			pt = t;
+		}
+	}
+}