1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
|
#pragma once
#include <stddef.h>
#include "fieldstat.h" // for fieldstat_tag
#ifdef __cplusplus
extern "C"
{
#endif
struct fieldstat_easy;
/*
* new a fieldstat_easy instance.
* @param max_thread_num: max thread number of this instance.
* @param name: name of this instance. Will appear in output json. Can be NULL.
* @param tags: tags of this instance. Will appear in output json. Can be NULL.
*/
struct fieldstat_easy *fieldstat_easy_new(int max_thread_num, const char *name, const struct fieldstat_tag *tags, size_t n_tag);
/*
* free a fieldstat_easy instance.
*/
void fieldstat_easy_free(struct fieldstat_easy *fse);
/*
* reset the instance. Will fail and return -1 if fieldstat_easy_enable_auto_output is called, since the behavior is hard to define.
*/
int fieldstat_easy_reset(struct fieldstat_easy *fse);
/*
* enable auto output. both data of accumulated and delta will be output.
* @param output_path: output file path. Should be identical to the one in python config.
* @param interval_second: output interval in second.
* @return: 0 if success, -1 if failed to open file. -2 if the output is already enabled.
*/
int fieldstat_easy_enable_auto_output(struct fieldstat_easy *pthis, const char *output_path, int interval_second);
/*
* @brief add a metric to the cube of cube_id. One metric may be associated with different cells.
* @param metric_name: name of the metric. Cannot be NULL. Must be unique.
* @return metric id>=0 if success. If failed, return FS_ERR_NULL_HANDLER, FS_ERR_INVALID_KEY(when metric_name is not unique in this cube).
* For the error code, see fieldstat.h
*/
int fieldstat_easy_register_counter(struct fieldstat_easy *fse, const char *name);
/*
* @brief refer to fieldstat_easy_register_counter.
* @param lowest_trackable_value: the lowest value that can be tracked (distinguishable from 0) by the histogram. Must be >= 1.
* @param highest_trackable_value: the highest value to be tracked by the histogram. Must be >= 2 * lowest_trackable_value.
* @param significant_figures: the precision of the histogram. Must be in [1, 5].
* @return metric id if success. If failed, return FS_ERR_NULL_HANDLER, FS_ERR_INVALID_KEY(when metric_name is not unique in this cube), or FS_ERR_INVALID_PARAM(if any of the 3 params are out of range)
* For the error code, see fieldstat.h
*/
int fieldstat_easy_register_histogram(struct fieldstat_easy *fse, const char *name, long long lowest_trackable_value, long long highest_trackable_value, int significant_figures);
/*
* Output the accumulated data to a json string.
* @param buff: output buffer. User should free it after use.
*/
void fieldstat_easy_output(struct fieldstat_easy *fse, char **buff, size_t *buff_len);
void fieldstat_easy_output_array(struct fieldstat_easy *fse, char ***json_objects, size_t *n_object);
/*
* @brief let the value of counter metric of cell_id increase by `increment`.
* @param thread_id: thread id. Must be in [0, max_thread_num).
* @param metric_id: metric id, previously returned by fieldstat_register_counter.
* @param increment: increment of the counter metric. Can be negative.
* @return FS_OK if success. FS_ERR_NULL_HANDLER, FS_ERR_INVALID_CUBE_ID, FS_ERR_INVALID_METRIC_ID if fail.
* return -1 also when the thread_id is out of range.
*/
int fieldstat_easy_counter_incrby(struct fieldstat_easy *fse, int thread_id, int metric_id, const struct fieldstat_tag *tags, size_t n_tag, long long increment);
/*
* @brief Add a value to the histogram metric of cell_id. Histogram will record the distribution of the values.
The value bigger than highest_trackable_value will be set to highest_trackable_value. The value less than lowest_trackable_value will be tried to record, and, if succeed, remains in the record as -inf(most of the time) or 0(if value == 0)
* @param value: value of the histogram metric.
* @return FS_OK if success. FS_ERR_NULL_HANDLER, FS_ERR_INVALID_CUBE_ID, FS_ERR_INVALID_METRIC_ID if fail.
* return -1 also when the thread_id is out of range.
*/
int fieldstat_easy_histogram_record(struct fieldstat_easy *fse, int thread_id, int metric_id, const struct fieldstat_tag *tags, size_t n_tag, long long value);
#ifdef __cplusplus
}
#endif
/*
关于输出delta:
fs_write;
fs_accumulate;
fs_delta;
一个在write上register的metric,同样会随merge进入accumulate,delta的metric 名字后面希望跟一个delta,但是因为它是切换过来的,而且最终要加到accumulate上,所以。。。
delta的形成一定靠reset。
输出的时候,acc 和 delta的本来分别在两个json上,但是文件里只有一个json。
最好提供一个exportPair 的接口,由json聚合。如果输出两个json,我还要读出来再写一套,更恶心了。
另外一个方法,干脆给histogram算差值,这样是不是更干净一点?从算法上讲,histogram没道理不能算差。
然后就变成fs_write, fs_reading. 最终的输出是一个总量。
这个方法总体很好,但是需要我在exporter上保存metric数据,依赖metric。光这一条就可以直接否了方案。
这个easy自己维护一套metric呢?查询到的histogram和counter都merge,然后改名,再merge进来。。。这个改名就特别莫名其妙,输出的东西当然要输出自己来搞。
算了,调用两遍exporter得了,然后我把一个的加到另外一个上?这样的问题是我要用cjson来解,真的不要,太恶心了。。
还是搞个duo吧..?
不行,因为我真的没办法保证acc 和 delta的cell一样,delta的cell是调用者来搞的, 太容易顺序错了。于是counter history 那套是必须的。
不过传入delta而不是由exporter保留,这部分还是对的。如果还是想要这个history,那么exporter就还得是有状态的,不然总不能每次都拿delta重建一份。(感觉就重建一份吧)
算了,果然只能这样了。。
那么干脆每次都新来一个acc呢?我记录acc,合成acc,delta咋办?也不对。
得得得得,算delta这个逃不掉了。
提供一个fieldstat减法怎么样?首先hll不支持减。另外我不希望动fs4的接口。
---------------------------------- plan1 ---------------------------------
改动最小,性能影响最大,所有的还都得搞两份
instance = new()
register_metric(i,"A");
intance_delt
register_metric(i_delta, "A_delta");
counter_incyby(instance, id, 1);
counter_incyby(instance_delta, id, 1);
dst = merge(instance);
dst_delta = merge(instance_delta);
merge(dst, dst_delta)
---------------------------------- plan2 ---------------------------------
// 最莫名其妙,而且merge 改起来容易出问题
instance_delta = new()
incyby
instance = merge_and_add_delta(instance_delta) // 新增接口
---------------------------------- plan3 ---------------------------------
// 仅仅需要修改exporter,但是编码量比较大,选择这种。export只有一遍,而merge是每个线程一遍,还是慢export吧
json_total = exporter_export_duo(acc, delta); // 新增接口
---------------------------------- plan4 ---------------------------------
enable-delta()
histogram_decode()
histogram_substract()
*/
|