Skip to content
This repository was archived by the owner on Nov 14, 2019. It is now read-only.

Commit fe3ebd0

Browse files
author
Vicent Marti
committed
Implement sempla rates
1 parent efc01e2 commit fe3ebd0

8 files changed

Lines changed: 156 additions & 88 deletions

File tree

src/histogram.c

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,28 @@
11
#include "brubeck.h"
2+
#include <limits.h>
23

34
#define HISTO_INIT_SIZE 16
45

5-
void brubeck_histo_push(struct brubeck_histo *histo, value_t value)
6+
void brubeck_histo_push(struct brubeck_histo *histo, value_t value, value_t sample_rate)
67
{
8+
histo->count += (1.0 / sample_rate);
9+
710
if (histo->size == histo->alloc) {
8-
histo->alloc *= 2;
9-
if (histo->alloc < HISTO_INIT_SIZE)
10-
histo->alloc = HISTO_INIT_SIZE;
11+
size_t new_size;
12+
13+
if (histo->size == USHRT_MAX)
14+
return;
15+
16+
new_size = histo->alloc * 2;
1117

12-
histo->values = xrealloc(histo->values, histo->alloc * sizeof(value_t));
18+
if (new_size > USHRT_MAX)
19+
new_size = USHRT_MAX;
20+
if (new_size < HISTO_INIT_SIZE)
21+
new_size = HISTO_INIT_SIZE;
22+
if (new_size != histo->alloc) {
23+
histo->alloc = (uint16_t)new_size;
24+
histo->values = xrealloc(histo->values, histo->alloc * sizeof(value_t));
25+
}
1326
}
1427

1528
histo->values[histo->size++] = value;
@@ -63,7 +76,7 @@ void brubeck_histo_sample(
6376
sample->max = histo->values[histo->size - 1];
6477
sample->mean = sample->sum / histo->size;
6578
sample->median = histo_percentile(histo, 0.5f);
66-
sample->count = histo->size;
79+
sample->count = histo->count;
6780

6881
sample->percentile[PC_75] = histo_percentile(histo, 0.75f);
6982
sample->percentile[PC_95] = histo_percentile(histo, 0.95f);

src/histogram.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33

44
struct brubeck_histo {
55
value_t *values;
6-
uint32_t alloc, size;
6+
uint32_t count;
7+
uint16_t alloc, size;
78
};
89

910
struct brubeck_histo_sample {
@@ -19,7 +20,7 @@ struct brubeck_histo_sample {
1920

2021
enum { PC_75, PC_95, PC_98, PC_99, PC_999 };
2122

22-
void brubeck_histo_push(struct brubeck_histo *histo, value_t value);
23+
void brubeck_histo_push(struct brubeck_histo *histo, value_t value, value_t sample_rate);
2324
void brubeck_histo_sample(
2425
struct brubeck_histo_sample *sample,
2526
struct brubeck_histo *histo);

src/metric.c

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ new_metric(struct brubeck_server *server, const char *key, size_t key_len, uint8
3030
return metric;
3131
}
3232

33-
typedef void (*mt_prototype_record)(struct brubeck_metric *, value_t);
33+
typedef void (*mt_prototype_record)(struct brubeck_metric *, value_t, value_t);
3434
typedef void (*mt_prototype_sample)(struct brubeck_metric *, brubeck_sample_cb, void *);
3535

3636

@@ -40,7 +40,7 @@ typedef void (*mt_prototype_sample)(struct brubeck_metric *, brubeck_sample_cb,
4040
* ALLOC: mt + 4 bytes
4141
*********************************************/
4242
static void
43-
gauge__record(struct brubeck_metric *metric, value_t value)
43+
gauge__record(struct brubeck_metric *metric, value_t value, value_t sample_rate)
4444
{
4545
pthread_spin_lock(&metric->lock);
4646
{
@@ -70,8 +70,11 @@ gauge__sample(struct brubeck_metric *metric, brubeck_sample_cb sample, void *opa
7070
* ALLOC: mt + 4
7171
*********************************************/
7272
static void
73-
meter__record(struct brubeck_metric *metric, value_t value)
73+
meter__record(struct brubeck_metric *metric, value_t value, value_t sample_rate)
7474
{
75+
/* upsample */
76+
value *= (1.0 / sample_rate);
77+
7578
pthread_spin_lock(&metric->lock);
7679
{
7780
metric->as.meter.value += value;
@@ -101,8 +104,11 @@ meter__sample(struct brubeck_metric *metric, brubeck_sample_cb sample, void *opa
101104
* ALLOC: mt + 4 + 4 + 4
102105
*********************************************/
103106
static void
104-
counter__record(struct brubeck_metric *metric, value_t value)
107+
counter__record(struct brubeck_metric *metric, value_t value, value_t sample_rate)
105108
{
109+
/* upsample */
110+
value *= (1.0 / sample_rate);
111+
106112
pthread_spin_lock(&metric->lock);
107113
{
108114
if (metric->as.counter.previous > 0.0) {
@@ -140,11 +146,11 @@ counter__sample(struct brubeck_metric *metric, brubeck_sample_cb sample, void *o
140146
* ALLOC: mt + 16 + 4
141147
*********************************************/
142148
static void
143-
histogram__record(struct brubeck_metric *metric, value_t value)
149+
histogram__record(struct brubeck_metric *metric, value_t value, value_t sample_rate)
144150
{
145151
pthread_spin_lock(&metric->lock);
146152
{
147-
brubeck_histo_push(&metric->as.histogram, value);
153+
brubeck_histo_push(&metric->as.histogram, value, sample_rate);
148154
}
149155
pthread_spin_unlock(&metric->lock);
150156
}
@@ -260,9 +266,9 @@ void brubeck_metric_sample(struct brubeck_metric *metric, brubeck_sample_cb cb,
260266
_prototypes[metric->type].sample(metric, cb, backend);
261267
}
262268

263-
void brubeck_metric_record(struct brubeck_metric *metric, value_t value)
269+
void brubeck_metric_record(struct brubeck_metric *metric, value_t value, value_t sample_rate)
264270
{
265-
_prototypes[metric->type].record(metric, value);
271+
_prototypes[metric->type].record(metric, value, sample_rate);
266272
}
267273

268274
struct brubeck_metric *

src/metric.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ typedef void (*brubeck_sample_cb)(
5656
void *backend);
5757

5858
void brubeck_metric_sample(struct brubeck_metric *metric, brubeck_sample_cb cb, void *backend);
59-
void brubeck_metric_record(struct brubeck_metric *metric, value_t value);
59+
void brubeck_metric_record(struct brubeck_metric *metric, value_t value, value_t sample_rate);
6060

6161
struct brubeck_metric *brubeck_metric_new(struct brubeck_server *server, const char *, size_t, uint8_t);
6262
struct brubeck_metric *brubeck_metric_find(struct brubeck_server *server, const char *, size_t, uint8_t);

src/samplers/statsd.c

Lines changed: 55 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,47 @@ static void statsd_run_recvmsg(struct brubeck_statsd *statsd, int sock)
8787
}
8888
}
8989

90+
static inline char *
91+
parse_float(char *buffer, value_t *result)
92+
{
93+
int negative = 0;
94+
char *start = buffer;
95+
value_t value = 0.0;
96+
97+
if (*buffer == '-') {
98+
++buffer;
99+
negative = 1;
100+
}
101+
102+
while (*buffer >= '0' && *buffer <= '9') {
103+
value = (value * 10.0) + (*buffer - '0');
104+
++buffer;
105+
}
106+
107+
if (*buffer == '.') {
108+
double f = 0.0;
109+
int n = 0;
110+
++buffer;
111+
112+
while (*buffer >= '0' && *buffer <= '9') {
113+
f = (f * 10.0) + (*buffer - '0');
114+
buffer++;
115+
n++;
116+
}
117+
118+
value += f / pow(10.0, n);
119+
}
120+
121+
if (negative)
122+
value = -value;
123+
124+
if (unlikely(*buffer == 'e'))
125+
value = strtod(start, &buffer);
126+
127+
*result = value;
128+
return buffer;
129+
}
130+
90131
int brubeck_statsd_msg_parse(struct brubeck_statsd_msg *msg, char *buffer, char *end)
91132
{
92133
*end = '\0';
@@ -125,40 +166,7 @@ int brubeck_statsd_msg_parse(struct brubeck_statsd_msg *msg, char *buffer, char
125166
* ^^^
126167
*/
127168
{
128-
int negative = 0;
129-
char *start = buffer;
130-
131-
msg->value = 0.0;
132-
133-
if (*buffer == '-') {
134-
++buffer;
135-
negative = 1;
136-
}
137-
138-
while (*buffer >= '0' && *buffer <= '9') {
139-
msg->value = (msg->value * 10.0) + (*buffer - '0');
140-
++buffer;
141-
}
142-
143-
if (*buffer == '.') {
144-
double f = 0.0, n = 0.0;
145-
++buffer;
146-
147-
while (*buffer >= '0' && *buffer <= '9') {
148-
f = (f * 10.0) + (*buffer - '0');
149-
++buffer;
150-
n += 1.0;
151-
}
152-
153-
msg->value += f / pow(10.0, n);
154-
}
155-
156-
if (negative)
157-
msg->value = -msg->value;
158-
159-
if (unlikely(*buffer == 'e')) {
160-
msg->value = strtod(start, &buffer);
161-
}
169+
buffer = parse_float(buffer, &msg->value);
162170

163171
if (*buffer != '|')
164172
return -1;
@@ -189,29 +197,29 @@ int brubeck_statsd_msg_parse(struct brubeck_statsd_msg *msg, char *buffer, char
189197
default:
190198
return -1;
191199
}
200+
201+
buffer++;
192202
}
193203

194204
/**
195-
* Trailing bytes: data appended at the end of the message.
196-
* This is stored verbatim and will be parsed when processing
197-
* the specific message type. This is optional.
205+
* Sample rate: parse the sample rate trailer if it exists.
206+
* It must be a floating point number between 0.0 and 1.0
198207
*
199208
* gorets:1|c|@0.1
200209
* ^^^^----
201210
*/
202211
{
203-
buffer++;
212+
if (buffer[0] == '|' && buffer[1] == '@') {
213+
buffer = parse_float(buffer + 2, &msg->sample_rate);
214+
if (msg->sample_rate <= 0.0 || msg->sample_rate > 1.0)
215+
return -1;
216+
} else {
217+
msg->sample_rate = 1.0;
218+
}
204219

205-
if (buffer[0] == '\0' || (buffer[0] == '\n' && buffer[1] == '\0')) {
206-
msg->trail = NULL;
220+
if (buffer[0] == '\0' || (buffer[0] == '\n' && buffer[1] == '\0'))
207221
return 0;
208-
}
209222

210-
if (*buffer == '@' || *buffer == '|') {
211-
msg->trail = buffer;
212-
return 0;
213-
}
214-
215223
return -1;
216224
}
217225
}
@@ -234,7 +242,7 @@ void brubeck_statsd_packet_parse(struct brubeck_server *server, char *buffer, ch
234242

235243
metric = brubeck_metric_find(server, msg.key, msg.key_len, msg.type);
236244
if (metric != NULL)
237-
brubeck_metric_record(metric, msg.value);
245+
brubeck_metric_record(metric, msg.value, msg.sample_rate);
238246
}
239247

240248
/* move buf past this stat */

src/samplers/statsd.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44
#include "bloom.h"
55

66
struct brubeck_statsd_msg {
7-
char *key; /* The key of the message, NULL terminated */
8-
uint16_t key_len; /* length of the key */
9-
uint16_t type; /* type of the messaged, as a brubeck_mt_t */
10-
value_t value; /* integer value of the message */
11-
char *trail; /* Any data following the 'key:value|type' construct, NULL terminated*/
7+
char *key; /* The key of the message, NULL terminated */
8+
uint16_t key_len; /* length of the key */
9+
uint16_t type; /* type of the messaged, as a brubeck_mt_t */
10+
value_t value; /* floating point value of the message */
11+
value_t sample_rate; /* floating poit sample rate */
1212
};
1313

1414
struct brubeck_statsd {

tests/histogram.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ static void *thread_histo(void *ptr)
2525
} else {
2626
pthread_spin_lock(&t->lock);
2727
{
28-
brubeck_histo_push(&t->h, 0.42);
28+
brubeck_histo_push(&t->h, 0.42, 1.0);
2929
}
3030
pthread_spin_unlock(&t->lock);
3131
}
@@ -50,7 +50,7 @@ void test_histogram__single_element(void)
5050

5151
memset(&h, 0x0, sizeof(h));
5252

53-
brubeck_histo_push(&h, 42.0);
53+
brubeck_histo_push(&h, 42.0, 1.0);
5454
sput_fail_unless(h.size == 1, "push value to histogram");
5555

5656
brubeck_histo_sample(&sample, &h);
@@ -70,9 +70,9 @@ void test_histogram__large_range(void)
7070

7171
memset(&h, 0x0, sizeof(h));
7272

73-
brubeck_histo_push(&h, 1.3e12);
74-
brubeck_histo_push(&h, 42.0);
75-
brubeck_histo_push(&h, 42.0);
73+
brubeck_histo_push(&h, 1.3e12, 1.0);
74+
brubeck_histo_push(&h, 42.0, 1.0);
75+
brubeck_histo_push(&h, 42.0, 1.0);
7676

7777
brubeck_histo_sample(&sample, &h);
7878

0 commit comments

Comments
 (0)