summaryrefslogtreecommitdiff
path: root/app/src/monit.c
blob: f0d79efdcc51a6827d317f27a64353b042d0f4b2 (plain)
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
/* \brief 应用状态监测数据输出
 *
 * \author Lu Qiuwen<[email protected]>
 * \date 2016-11-30
 */

#include <cJSON.h>
#include <mrapp.h>
#include <mrdp_trace.h>

unsigned int g_monit_interval = 1;

int vdev_instance_stats_get(struct vdev_instance * vdi, struct vdev_stat_info * stat_info)
{
    struct vnode_cons_stat * st_cons_rx = NULL;
    struct vnode_prod_stat * st_prod_tx = NULL;
    struct vnode_prod_stat * st_prod_ftx = NULL;

    stat_info->nr_rxstream = vdi->nr_rxstream;
    stat_info->nr_txstream = vdi->nr_txstream;

    if (vdi->nr_rxstream > 0)
    {
        st_cons_rx = vnode_mirror_cons_stat_get(vdi->vnode_rx_cons);
    }

    if (vdi->nr_txstream > 0)
    {
        st_prod_tx = vnode_mirror_prod_stat_get(vdi->vnode_tx_prod);
        st_prod_ftx = vnode_mirror_prod_stat_get(vdi->vnode_ftx_prod);
    }

    for (int i = 0; i < vdi->nr_rxstream; i++)
    {
        stat_info->rx_on_line[i] = VNODE_STAT_READ(&st_cons_rx[i].on_line);
        stat_info->rx_deliver[i] = VNODE_STAT_READ(&st_cons_rx[i].deliver);
        stat_info->rx_missed[i] = VNODE_STAT_READ(&st_cons_rx[i].missed);
        stat_info->rx_total_len[i] = VNODE_STAT_READ(&st_cons_rx[i].total_len);

        stat_info->rx_q_len_max[i] = VNODE_STAT_READ(&st_cons_rx[i].q_len_max);
        stat_info->rx_q_len_avg_max[i] = VNODE_STAT_READ(&st_cons_rx[i].q_len_avg_max);
    }

    for (int i = 0; i < vdi->nr_txstream; i++)
    {
        stat_info->tx_on_line[i] = VNODE_STAT_READ(&st_prod_tx[i].on_line);
        stat_info->tx_deliver[i] = VNODE_STAT_READ(&st_prod_tx[i].deliver);
        stat_info->tx_missed[i] = VNODE_STAT_READ(&st_prod_tx[i].missed);
        stat_info->tx_total_len[i] = VNODE_STAT_READ(&st_prod_tx[i].total_len);

        stat_info->ftx_on_line[i] = VNODE_STAT_READ(&st_prod_ftx[i].on_line);
        stat_info->ftx_deliver[i] = VNODE_STAT_READ(&st_prod_ftx[i].deliver);
        stat_info->ftx_missed[i] = VNODE_STAT_READ(&st_prod_ftx[i].missed);
        stat_info->ftx_total_len[i] = VNODE_STAT_READ(&st_prod_ftx[i].total_len);
    }

    return 0;
}

void vdev_instance_stat_last_save(struct vdev_instance * vdi, struct vdev_stat_info * stat_info)
{
    vdi->stat_info_last = *stat_info;
}

void vdev_instance_stats_last_get(struct vdev_instance * vdi, struct vdev_stat_info * stat_info)
{
    *stat_info = vdi->stat_info_last;
}

static cJSON * __create_uint64_array(const uint64_t * value, int nr_value)
{
    struct cJSON * uint64_array = cJSON_CreateArray();
    for (int i = 0; i < nr_value; i++)
        cJSON_AddItemToArray(uint64_array, cJSON_CreateNumber(value[i]));
    return uint64_array;
}

static cJSON * __create_uint64_delta_array(const uint64_t * value_large, const uint64_t * value_small, int nr_value,
                                           int interval)
{
    struct cJSON * uint64_array = cJSON_CreateArray();
    for (int i = 0; i < nr_value; i++)
    {
        uint64_t delta = (value_large[i] - value_small[i]) / interval;
        cJSON_AddItemToArray(uint64_array, cJSON_CreateNumber(delta));
    }

    return uint64_array;
}

static cJSON * __create_vdev_stats(struct vdev_instance * vdi)
{
    struct vdev_stat_info _stat_info;
    struct vdev_stat_info _stat_info_last;

    vdev_instance_stats_get(vdi, &_stat_info);
    vdev_instance_stats_last_get(vdi, &_stat_info_last);
    vdev_instance_stat_last_save(vdi, &_stat_info);

    unsigned int nr_rx_stream = _stat_info.nr_rxstream;
    unsigned int nr_tx_stream = _stat_info.nr_txstream;

    /* 统计节点句柄 */
    struct cJSON * j_vdev_stats = cJSON_CreateObject();
    /* 累计量 */
    struct cJSON * j_vdev_value = cJSON_CreateObject();
    /* 瞬时值 */
    struct cJSON * j_vdev_speed = cJSON_CreateObject();
    /* Gauge */
    struct cJSON * j_vdev_gauge = cJSON_CreateObject();

#define __JOIN_VDEV_VALUE_STATS_ITEM(item, streams)                                                                    \
    do                                                                                                                 \
    {                                                                                                                  \
        cJSON_AddItemToObject(j_vdev_value, #item, __create_uint64_array(_stat_info.item, streams));                   \
    } while (0)

#define __JOIN_VDEV_VALUE_BYTES_TO_BITS_STAT_ITEM(item, streams)                                                       \
    do                                                                                                                 \
    {                                                                                                                  \
        uint64_t __bits_item[MR_SID_MAX];                                                                              \
        for (int i = 0; i < streams; i++)                                                                              \
            __bits_item[i] = _stat_info.item[i] * 8;                                                                   \
                                                                                                                       \
        cJSON_AddItemToObject(j_vdev_value, #item, __create_uint64_array(__bits_item, streams));                       \
    } while (0)

    __JOIN_VDEV_VALUE_STATS_ITEM(rx_on_line, nr_rx_stream);
    __JOIN_VDEV_VALUE_STATS_ITEM(rx_deliver, nr_rx_stream);
    __JOIN_VDEV_VALUE_STATS_ITEM(rx_missed, nr_rx_stream);
    __JOIN_VDEV_VALUE_BYTES_TO_BITS_STAT_ITEM(rx_total_len, nr_rx_stream);

    __JOIN_VDEV_VALUE_STATS_ITEM(tx_on_line, nr_tx_stream);
    __JOIN_VDEV_VALUE_STATS_ITEM(tx_deliver, nr_tx_stream);
    __JOIN_VDEV_VALUE_STATS_ITEM(tx_missed, nr_tx_stream);
    __JOIN_VDEV_VALUE_BYTES_TO_BITS_STAT_ITEM(tx_total_len, nr_tx_stream);

    __JOIN_VDEV_VALUE_STATS_ITEM(ftx_on_line, nr_tx_stream);
    __JOIN_VDEV_VALUE_STATS_ITEM(ftx_deliver, nr_tx_stream);
    __JOIN_VDEV_VALUE_STATS_ITEM(ftx_missed, nr_tx_stream);
    __JOIN_VDEV_VALUE_BYTES_TO_BITS_STAT_ITEM(ftx_total_len, nr_tx_stream);

    __JOIN_VDEV_VALUE_STATS_ITEM(ltx_on_line, nr_tx_stream);
    __JOIN_VDEV_VALUE_STATS_ITEM(ltx_deliver, nr_tx_stream);
    __JOIN_VDEV_VALUE_STATS_ITEM(ltx_missed, nr_tx_stream);
    __JOIN_VDEV_VALUE_BYTES_TO_BITS_STAT_ITEM(ltx_total_len, nr_tx_stream);

#define __JOIN_VDEV_SPEED_STATS_ITEM(item, streams)                                                                    \
    do                                                                                                                 \
    {                                                                                                                  \
        cJSON_AddItemToObject(                                                                                         \
            j_vdev_speed, #item,                                                                                       \
            __create_uint64_delta_array(_stat_info.item, _stat_info_last.item, streams, g_monit_interval));            \
    } while (0)

#define __JOIN_VDEV_SPEED_BYTES_TO_BITS_STAT_ITEM(item, streams)                                                       \
    do                                                                                                                 \
    {                                                                                                                  \
        uint64_t __bits_item[MR_SID_MAX];                                                                              \
        for (int i = 0; i < streams; i++)                                                                              \
            __bits_item[i] = _stat_info.item[i] * 8;                                                                   \
                                                                                                                       \
        uint64_t __bits_item_last[MR_SID_MAX];                                                                         \
        for (int i = 0; i < streams; i++)                                                                              \
            __bits_item_last[i] = _stat_info_last.item[i] * 8;                                                         \
                                                                                                                       \
        cJSON_AddItemToObject(j_vdev_speed, #item,                                                                     \
                              __create_uint64_delta_array(__bits_item, __bits_item_last, streams, g_monit_interval));  \
    } while (0)

    __JOIN_VDEV_SPEED_STATS_ITEM(rx_on_line, nr_rx_stream);
    __JOIN_VDEV_SPEED_STATS_ITEM(rx_deliver, nr_rx_stream);
    __JOIN_VDEV_SPEED_STATS_ITEM(rx_missed, nr_rx_stream);
    __JOIN_VDEV_SPEED_BYTES_TO_BITS_STAT_ITEM(rx_total_len, nr_rx_stream);

    __JOIN_VDEV_SPEED_STATS_ITEM(tx_on_line, nr_tx_stream);
    __JOIN_VDEV_SPEED_STATS_ITEM(tx_deliver, nr_tx_stream);
    __JOIN_VDEV_SPEED_STATS_ITEM(tx_missed, nr_tx_stream);
    __JOIN_VDEV_SPEED_BYTES_TO_BITS_STAT_ITEM(tx_total_len, nr_tx_stream);

    __JOIN_VDEV_SPEED_STATS_ITEM(ftx_on_line, nr_tx_stream);
    __JOIN_VDEV_SPEED_STATS_ITEM(ftx_deliver, nr_tx_stream);
    __JOIN_VDEV_SPEED_STATS_ITEM(ftx_missed, nr_tx_stream);
    __JOIN_VDEV_SPEED_BYTES_TO_BITS_STAT_ITEM(ftx_total_len, nr_tx_stream);

    __JOIN_VDEV_SPEED_STATS_ITEM(ltx_on_line, nr_tx_stream);
    __JOIN_VDEV_SPEED_STATS_ITEM(ltx_deliver, nr_tx_stream);
    __JOIN_VDEV_SPEED_STATS_ITEM(ltx_missed, nr_tx_stream);
    __JOIN_VDEV_SPEED_BYTES_TO_BITS_STAT_ITEM(ltx_total_len, nr_tx_stream);

    cJSON * rx_q_len_array = cJSON_CreateArray();
    for (unsigned int i = 0; i < nr_rx_stream; i++)
    {
        cJSON_AddItemToArray(rx_q_len_array, cJSON_CreateNumber(_stat_info.rx_q_len_max[i]));
    }
    cJSON_AddItemToObject(j_vdev_gauge, "rx_q_len", rx_q_len_array);

    cJSON * rx_q_avg_len_array = cJSON_CreateArray();
    for (unsigned int i = 0; i < nr_rx_stream; i++)
    {
        cJSON_AddItemToArray(rx_q_avg_len_array, cJSON_CreateNumber(_stat_info.rx_q_len_avg_max[i]));
    }

    cJSON_AddItemToObject(j_vdev_gauge, "rx_q_len_avg", rx_q_avg_len_array);

    /*************************************************************************/
    cJSON_AddItemToObject(j_vdev_stats, "accumulative", j_vdev_value);
    cJSON_AddItemToObject(j_vdev_stats, "speed", j_vdev_speed);
    cJSON_AddItemToObject(j_vdev_stats, "gauge", j_vdev_gauge);
    return j_vdev_stats;
}

// 运行时原始报文设备统计计数
static cJSON * monit_vdev(struct mr_instance * instance)
{
    struct cJSON * j_vdev_array = cJSON_CreateArray();
    for (int i = 0; i < instance->nr_vdevs; i++)
    {
        struct mr_vdev * vdev = &instance->vdevs[i];
        if (vdev == NULL)
            continue;

        cJSON * j_vdev = cJSON_CreateObject();
        cJSON_AddStringToObject(j_vdev, "symbol", vdev->devsym);
        cJSON_AddNumberToObject(j_vdev, "rxstreams", vdev->nr_rxstream);
        cJSON_AddNumberToObject(j_vdev, "txstreams", vdev->nr_txstream);
        cJSON_AddItemToObject(j_vdev, "stats", __create_vdev_stats(vdev->vdi));
        cJSON_AddItemToArray(j_vdev_array, j_vdev);
    }

    return j_vdev_array;
}

static cJSON * monit_app_stat(struct mr_instance * instance)
{
    struct cJSON * j_root = cJSON_CreateObject();

#define _trans_app_stat(item)                                                                                          \
    uint64_t __trans_##item[MR_SID_MAX];                                                                               \
    for (int i = 0; i < instance->nr_dataplane_thread; i++)                                                            \
    {                                                                                                                  \
        __trans_##item[i] = instance->stat[i].item;                                                                    \
    }

#define _trans_app_stat_array(item) __trans_##item

    _trans_app_stat(packet_recv_count);
    _trans_app_stat(packet_recv_length);
    _trans_app_stat(packet_send_count);
    _trans_app_stat(packet_send_length);
    _trans_app_stat(packet_recv_drop);
    _trans_app_stat(packet_send_drop);
    _trans_app_stat(mbuf_alloc_count);
    _trans_app_stat(mbuf_free_count);
    _trans_app_stat(poll_wake_up_by_ev);
    _trans_app_stat(poll_wake_up_timeout);

    /* 在用Buffer数量统计 */
    uint64_t __trans_mbuf_in_use_count[MR_SID_MAX];
    for (int i = 0; i < instance->nr_dataplane_thread; i++)
    {
        __trans_mbuf_in_use_count[i] = __trans_packet_recv_count[i] + __trans_mbuf_alloc_count[i] -
                                       __trans_packet_send_count[i] - __trans_mbuf_free_count[i];
    }

#define _json_generate(item)                                                                                           \
    do                                                                                                                 \
    {                                                                                                                  \
        cJSON_AddItemToObject(j_root, #item,                                                                           \
                              __create_uint64_array(_trans_app_stat_array(item), instance->nr_dataplane_thread));      \
    } while (0)

    _json_generate(packet_recv_count);
    _json_generate(packet_recv_length);
    _json_generate(packet_send_count);
    _json_generate(packet_send_length);
    _json_generate(packet_recv_drop);
    _json_generate(packet_send_drop);
    _json_generate(mbuf_alloc_count);
    _json_generate(mbuf_free_count);
    _json_generate(mbuf_in_use_count);
    _json_generate(poll_wake_up_by_ev);
    _json_generate(poll_wake_up_timeout);

#undef _trans_app_stat
#undef _trans_app_stat_array
#undef _json_generate

    return j_root;
}

static cJSON * monit_app_info(struct mr_instance * instance)
{
    struct cJSON * j_root = cJSON_CreateObject();
    cJSON_AddStringToObject(j_root, "symbol", instance->appsym);
    return j_root;
}

static cJSON * monit_root(struct mr_instance * instance)
{
    struct cJSON * j_root = cJSON_CreateObject();
    cJSON_AddItemToObject(j_root, "appinfo", monit_app_info(instance));
    cJSON_AddItemToObject(j_root, "raw", monit_vdev(instance));
    cJSON_AddItemToObject(j_root, "appstat", monit_app_stat(instance));
    cJSON_AddItemToObject(j_root, "dp-trace-path", marsio_dp_trace_monit_loop(instance));
	return j_root;
}

int mrapp_monit_loop(struct mr_instance * instance)
{
    cJSON * j_root = monit_root(instance);
    char * str_json_print = cJSON_Print(j_root);

    FILE * fp_monit = fopen(instance->monit_file_path, "w");
    if (fp_monit == NULL)
    {
        MR_WARNING("monit file %s open failed, cannot dump program stat info : %s", instance->monit_file_path,
                   strerror(errno));
        return 0;
    }

    fprintf(fp_monit, "%s", str_json_print);
    cJSON_Delete(j_root);
    free(str_json_print);
    fclose(fp_monit);
    return 0;
}