From 9ed51426baac47f3fe4b45cc7a018b9f6eeff2dd Mon Sep 17 00:00:00 2001 From: Leah Neukirchen Date: Sun, 15 Oct 2023 18:39:18 +0200 Subject: add mico-sort --- Makefile | 6 ++- mico-sort.c | 170 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 174 insertions(+), 2 deletions(-) create mode 100644 mico-sort.c 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 +#include +#include +#include + +#include + +#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; + } + } +} -- cgit 1.4.1