mirror of
https://codeberg.org/redict/redict.git
synced 2025-01-22 16:18:28 -05:00
ASCII sparklines generation API.
This commit is contained in:
parent
ed4980243a
commit
cc4df5a6b8
@ -107,7 +107,7 @@ endif
|
|||||||
|
|
||||||
REDIS_SERVER_NAME=redis-server
|
REDIS_SERVER_NAME=redis-server
|
||||||
REDIS_SENTINEL_NAME=redis-sentinel
|
REDIS_SENTINEL_NAME=redis-sentinel
|
||||||
REDIS_SERVER_OBJ=adlist.o ae.o anet.o dict.o redis.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o
|
REDIS_SERVER_OBJ=adlist.o ae.o anet.o dict.o redis.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o
|
||||||
REDIS_CLI_NAME=redis-cli
|
REDIS_CLI_NAME=redis-cli
|
||||||
REDIS_CLI_OBJ=anet.o sds.o adlist.o redis-cli.o zmalloc.o release.o anet.o ae.o crc64.o
|
REDIS_CLI_OBJ=anet.o sds.o adlist.o redis-cli.o zmalloc.o release.o anet.o ae.o crc64.o
|
||||||
REDIS_BENCHMARK_NAME=redis-benchmark
|
REDIS_BENCHMARK_NAME=redis-benchmark
|
||||||
|
@ -64,6 +64,7 @@ typedef long long mstime_t; /* millisecond time type. */
|
|||||||
#include "version.h" /* Version macro */
|
#include "version.h" /* Version macro */
|
||||||
#include "util.h" /* Misc functions useful in many places */
|
#include "util.h" /* Misc functions useful in many places */
|
||||||
#include "latency.h" /* Latency monitor API */
|
#include "latency.h" /* Latency monitor API */
|
||||||
|
#include "sparkline.h" /* ASII graphs API */
|
||||||
|
|
||||||
/* Error codes */
|
/* Error codes */
|
||||||
#define REDIS_OK 0
|
#define REDIS_OK 0
|
||||||
|
172
src/sparkline.c
Normal file
172
src/sparkline.c
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
/* sparkline.c -- ASCII Sparklines
|
||||||
|
* This code is modified from http://github.com/antirez/aspark and adapted
|
||||||
|
* in order to return SDS strings instead of outputting directly to
|
||||||
|
* the terminal.
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* Copyright(C) 2011-2014 Salvatore Sanfilippo <antirez@gmail.com>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "redis.h"
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
/* This is the charset used to display the graphs, but multiple rows are used
|
||||||
|
* to increase the resolution. */
|
||||||
|
static char charset[] = "_-`";
|
||||||
|
static char charset_fill[] = "_o#";
|
||||||
|
static int charset_len = sizeof(charset)-1;
|
||||||
|
static int label_margin_top = 1;
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
* Sequences are arrays of samples we use to represent data to turn
|
||||||
|
* into sparklines. This is the API in order to generate a sparkline:
|
||||||
|
*
|
||||||
|
* struct sequence *seq = createSparklineSequence();
|
||||||
|
* sparklineSequenceAddSample(seq, 10, NULL);
|
||||||
|
* sparklineSequenceAddSample(seq, 20, NULL);
|
||||||
|
* sparklineSequenceAddSample(seq, 30, "last sample label");
|
||||||
|
* sds output = sparklineRender(seq, 80, 4);
|
||||||
|
* freeSparklineSequence(seq);
|
||||||
|
* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* Create a new sequence. */
|
||||||
|
struct sequence *createSparklineSequence(void) {
|
||||||
|
struct sequence *seq = zmalloc(sizeof(*seq));
|
||||||
|
seq->length = 0;
|
||||||
|
seq->samples = NULL;
|
||||||
|
return seq;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add a new sample into a sequence. */
|
||||||
|
void sparklineSequenceAddSample(struct sequence *seq, double value, char *label) {
|
||||||
|
if (seq->length == 0) {
|
||||||
|
seq->min = seq->max = value;
|
||||||
|
} else {
|
||||||
|
if (value < seq->min) seq->min = value;
|
||||||
|
else if (value > seq->max) seq->max = value;
|
||||||
|
}
|
||||||
|
seq->samples = zrealloc(seq->samples,sizeof(struct sample)*(seq->length+1));
|
||||||
|
seq->samples[seq->length].value = value;
|
||||||
|
seq->samples[seq->length].label = label;
|
||||||
|
seq->length++;
|
||||||
|
if (label) seq->labels++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free a sequence. */
|
||||||
|
void freeSparklineSequence(struct sequence *seq) {
|
||||||
|
zfree(seq->samples);
|
||||||
|
zfree(seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
* ASCII rendering of sequence
|
||||||
|
* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* Render part of a sequence, so that render_sequence() call call this function
|
||||||
|
* with differnent parts in order to create the full output without overflowing
|
||||||
|
* the current terminal columns. */
|
||||||
|
sds sparklineRenderRange(sds output, struct sequence *seq, int rows, int offset, int len, int flags) {
|
||||||
|
int j;
|
||||||
|
double relmax = seq->max - seq->min;
|
||||||
|
int steps = charset_len*rows;
|
||||||
|
int row = 0;
|
||||||
|
char *chars = zmalloc(len);
|
||||||
|
int loop = 1;
|
||||||
|
int opt_fill = flags & SPARKLINE_FILL;
|
||||||
|
int opt_log = flags & SPARKLINE_LOG_SCALE;
|
||||||
|
|
||||||
|
if (opt_log) {
|
||||||
|
relmax = log(relmax+1);
|
||||||
|
} else if (relmax == 0) {
|
||||||
|
relmax = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(loop) {
|
||||||
|
loop = 0;
|
||||||
|
memset(chars,' ',len);
|
||||||
|
for (j = 0; j < len; j++) {
|
||||||
|
struct sample *s = &seq->samples[j+offset];
|
||||||
|
double relval = s->value - seq->min;
|
||||||
|
int step;
|
||||||
|
|
||||||
|
if (opt_log) relval = log(relval+1);
|
||||||
|
step = (int) (relval*steps)/relmax;
|
||||||
|
if (step < 0) step = 0;
|
||||||
|
if (step >= steps) step = steps-1;
|
||||||
|
|
||||||
|
if (row < rows) {
|
||||||
|
/* Print the character needed to create the sparkline */
|
||||||
|
int charidx = step-((rows-row-1)*charset_len);
|
||||||
|
loop = 1;
|
||||||
|
if (charidx >= 0 && charidx < charset_len) {
|
||||||
|
chars[j] = opt_fill ? charset_fill[charidx] :
|
||||||
|
charset[charidx];
|
||||||
|
} else if(opt_fill && charidx >= charset_len) {
|
||||||
|
chars[j] = '|';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Labels spacing */
|
||||||
|
if (seq->labels && row-rows < label_margin_top) {
|
||||||
|
loop = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Print the label if needed. */
|
||||||
|
if (s->label) {
|
||||||
|
int label_len = strlen(s->label);
|
||||||
|
int label_char = row - rows - label_margin_top;
|
||||||
|
|
||||||
|
if (label_len > label_char) {
|
||||||
|
loop = 1;
|
||||||
|
chars[j] = s->label[label_char];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (loop) {
|
||||||
|
row++;
|
||||||
|
output = sdscatlen(output,chars,len);
|
||||||
|
output = sdscatlen(output,"\n",1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
zfree(chars);
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Turn a sequence into its ASCII representation */
|
||||||
|
sds sparklineRender(struct sequence *seq, int columns, int rows, int flags) {
|
||||||
|
int j;
|
||||||
|
sds output = sdsempty();
|
||||||
|
|
||||||
|
for (j = 0; j < seq->length; j += columns) {
|
||||||
|
int sublen = (seq->length-j) < columns ? (seq->length-j) : columns;
|
||||||
|
|
||||||
|
if (j != 0) output = sdscatlen(output,"\n",1);
|
||||||
|
output = sparklineRenderRange(output, seq, rows, j, sublen, flags);
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
56
src/sparkline.h
Normal file
56
src/sparkline.h
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/* sparkline.h -- ASCII Sparklines header file
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* Copyright(C) 2011-2014 Salvatore Sanfilippo <antirez@gmail.com>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SPARKLINE_H
|
||||||
|
#define __SPARKLINE_H
|
||||||
|
|
||||||
|
/* A sequence is represented of many "samples" */
|
||||||
|
struct sample {
|
||||||
|
double value;
|
||||||
|
char *label;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sequence {
|
||||||
|
int length;
|
||||||
|
int labels;
|
||||||
|
struct sample *samples;
|
||||||
|
double min, max;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define SPARKLINE_NO_FLAGS 0
|
||||||
|
#define SPARKLINE_FILL 1 /* Fill the area under the curve. */
|
||||||
|
#define SPARKLINE_LOG_SCALE 2 /* Use logarithmic scale. */
|
||||||
|
|
||||||
|
struct sequence *createSparklineSequence(void);
|
||||||
|
void sparklineSequenceAddSample(struct sequence *seq, double value, char *label);
|
||||||
|
void freeSparklineSequence(struct sequence *seq);
|
||||||
|
sds sparklineRenderRange(sds output, struct sequence *seq, int rows, int offset, int len, int flags);
|
||||||
|
sds sparklineRender(struct sequence *seq, int columns, int rows, int flags);
|
||||||
|
|
||||||
|
#endif /* __SPARKLINE_H */
|
Loading…
Reference in New Issue
Block a user