libwebsockets
Lightweight C library for HTML5 websockets
Loading...
Searching...
No Matches
lws-metrics.h
Go to the documentation of this file.
1 /*
2 * libwebsockets - small server side websockets and web server implementation
3 *
4 * Copyright (C) 2010 - 2021 Andy Green <andy@warmcat.com>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 * IN THE SOFTWARE.
23 *
24 * Public apis related to metric collection and reporting
25 */
26
27/* lws_metrics public part */
28
29typedef uint64_t u_mt_t;
30
31enum {
47};
48
49/*
50 * lws_metrics_tag allows your object to accumulate OpenMetrics-style
51 * descriptive tags before accounting for it with a metrics object at the end.
52 *
53 * Tags should represent low entropy information that is likely to repeat
54 * identically, so, eg, http method name, not eg, latency in us which is
55 * unlikely to be seen the same twice.
56 *
57 * Tags are just a list of name=value pairs, used for qualifying the final
58 * metrics entry with decorations in additional dimensions. For example,
59 * rather than keep individual metrics on methods, scheme, mountpoint, result
60 * code, you can keep metrics on http transactions only, and qualify the
61 * transaction metrics entries with tags that can be queried on the metrics
62 * backend to get the finer-grained information.
63 *
64 * http_srv{code="404",mount="/",method="GET",scheme="http"} 3
65 *
66 * For OpenMetrics the tags are converted to a { list } and appended to the base
67 * metrics name before using with actual metrics objects, the same set of tags
68 * on different transactions resolve to the same qualification string.
69 */
70
71typedef struct lws_metrics_tag {
73
74 const char *name; /* tag, intended to be in .rodata, not copied */
75 /* overallocated value */
77
79lws_metrics_tag_add(lws_dll2_owner_t *owner, const char *name, const char *val);
80
81#if defined(LWS_WITH_SYS_METRICS)
82/*
83 * wsi-specific version that also appends the tag value to the lifecycle tag
84 * used for logging the wsi identity
85 */
87lws_metrics_tag_wsi_add(struct lws *wsi, const char *name, const char *val);
88#else
89#define lws_metrics_tag_wsi_add(_a, _b, _c)
90#endif
91
92#if defined(LWS_WITH_SECURE_STREAMS)
93/*
94 * ss-specific version that also appends the tag value to the lifecycle tag
95 * used for logging the ss identity
96 */
97#if defined(LWS_WITH_SYS_METRICS)
99lws_metrics_tag_ss_add(struct lws_ss_handle *ss, const char *name, const char *val);
100#else
101#define lws_metrics_tag_ss_add(_a, _b, _c)
102#endif
103#endif
104
107
109lws_metrics_tags_serialize(lws_dll2_owner_t *owner, char *buf, size_t len);
110
111LWS_EXTERN LWS_VISIBLE const char *
112lws_metrics_tag_get(lws_dll2_owner_t *owner, const char *name);
113
114/* histogram bucket */
115
116typedef struct lws_metric_bucket {
118 uint64_t count;
119
120 /* name + NUL is overallocated */
122
123/* get overallocated name of bucket from bucket pointer */
124#define lws_metric_bucket_name_len(_b) (*((uint8_t *)&(_b)[1]))
125#define lws_metric_bucket_name(_b) (((const char *)&(_b)[1]) + 1)
126
127/*
128 * These represent persistent local event measurements. They may aggregate
129 * a large number of events inbetween external dumping of summaries of the
130 * period covered, in two different ways
131 *
132 * 1) aggregation by sum or mean, to absorb multiple scalar readings
133 *
134 * - go / no-go ratio counting
135 * - mean averaging for, eg, latencies
136 * - min / max for averaged values
137 * - period the stats covers
138 *
139 * 2) aggregation by histogram, to absorb a range of outcomes that may occur
140 * multiple times
141 *
142 * - add named buckets to histogram
143 * - bucket has a 64-bit count
144 * - bumping a bucket just increments the count if already exists, else adds
145 * a new one with count set to 1
146 *
147 * The same type with a union covers both cases.
148 *
149 * The lws_system ops api that hooks lws_metrics up to a metrics backend is
150 * given a pointer to these according to the related policy, eg, hourly, or
151 * every event passed straight through.
152 */
153
154typedef struct lws_metric_pub {
155 const char *name;
159
166
167 /* scope of data in .u is "since last dump" --> */
168
169 union {
170 /* aggregation, by sum or mean */
171
172 struct {
173 u_mt_t sum[2];
175 u_mt_t min;
177 u_mt_t max;
179
180 uint32_t count[2];
182 } agg;
183
184 /* histogram with dynamic named buckets */
185
186 struct {
189
190 uint64_t total_count;
194 } hist;
195 } u;
196
198
200
203 lws_dll2_owner_t *tow2);
204
205
206/*
207 * Calipers are a helper struct for implementing "hanging latency" detection,
208 * where setting the start time and finding the end time may happen in more than
209 * one place.
210 *
211 * There are convenience wrappers to eliminate caliper definitions and code
212 * cleanly if WITH_SYS_METRICS is disabled for the build.
213 */
214
215struct lws_metric;
216
223
224#if defined(LWS_WITH_SYS_METRICS)
225#define lws_metrics_caliper_compose(_name) \
226 lws_metric_caliper_t _name;
227#define lws_metrics_caliper_bind(_name, _mt) \
228 { if (_name.mt) { \
229 lwsl_err("caliper: overwrite %s\n", \
230 lws_metrics_priv_to_pub(_name.mt)->name); \
231 assert(0); } \
232 _name.mt = _mt; _name.us_start = lws_now_usecs(); }
233#define lws_metrics_caliper_declare(_name, _mt) \
234 lws_metric_caliper_t _name = { .mt = _mt, .us_start = lws_now_usecs() }
235#define lws_metrics_caliper_report(_name, _go_nogo) \
236 { if (_name.us_start) { lws_metric_event(_name.mt, _go_nogo, \
237 (u_mt_t)(lws_now_usecs() - \
238 _name.us_start)); \
239 } lws_metrics_caliper_done(_name); }
240#define lws_metrics_caliper_report_hist(_name, pwsi) if (_name.mt) { \
241 lws_metrics_hist_bump_priv_tagged(lws_metrics_priv_to_pub(_name.mt), \
242 &_name.mtags_owner, \
243 pwsi ? &((pwsi)->cal_conn.mtags_owner) : NULL); \
244 lws_metrics_caliper_done(_name); }
245
246#define lws_metrics_caliper_cancel(_name) { lws_metrics_caliper_done(_name); }
247#define lws_metrics_hist_bump(_mt, _name) \
248 lws_metrics_hist_bump_(_mt, _name)
249#define lws_metrics_hist_bump_priv(_mt, _name) \
250 lws_metrics_hist_bump_(lws_metrics_priv_to_pub(_mt), _name)
251#define lws_metrics_caliper_done(_name) { \
252 _name.us_start = 0; _name.mt = NULL; \
253 lws_metrics_tags_destroy(&_name.mtags_owner); }
254#else
255#define lws_metrics_caliper_compose(_name)
256#define lws_metrics_caliper_bind(_name, _mt)
257#define lws_metrics_caliper_declare(_name, _mp)
258#define lws_metrics_caliper_report(_name, _go_nogo)
259#define lws_metrics_caliper_report_hist(_name, pwsiconn)
260#define lws_metrics_caliper_cancel(_name)
261#define lws_metrics_hist_bump(_mt, _name)
262#define lws_metrics_hist_bump_priv(_mt, _name)
263#define lws_metrics_caliper_done(_name)
264#endif
265
283 char *buf, size_t len);
284
303
305lws_metrics_foreach(struct lws_context *ctx, void *user,
306 int (*cb)(lws_metric_pub_t *pub, void *user));
307
310 const char *name);
311
312enum {
313 LMT_NORMAL = 0, /* related to successful events */
314 LMT_OUTLIER, /* related to successful events outside of bounds */
315
316 LMT_FAIL, /* related to failed events */
317
319};
320
321typedef enum lws_metric_rpt {
322 LMR_PERIODIC = 0, /* we are reporting on a schedule */
323 LMR_OUTLIER, /* we are reporting the last outlier */
325
326#define METRES_GO 0
327#define METRES_NOGO 1
328
329
struct lws_dll2 lws_dll2_t
struct lws_dll2_owner lws_dll2_owner_t
unsigned int uint32_t
#define LWS_EXTERN
int64_t lws_usec_t
unsigned char uint8_t
#define LWS_VISIBLE
lws_usec_t us_first
void * backend_opaque
const char * name
@ LWSMTFL_REPORT_OUTLIERS
Definition lws-metrics.h:32
@ LWSMTFL_REPORT_ONLY_GO
Definition lws-metrics.h:41
@ LWSMTFL_REPORT_INACTIVITY_AT_PERIODIC
Definition lws-metrics.h:36
@ LWSMTFL_REPORT_OOB
Definition lws-metrics.h:34
@ LWSMTFL_REPORT_HIST
Definition lws-metrics.h:45
@ LWSMTFL_REPORT_DUTY_WALLCLOCK_US
Definition lws-metrics.h:43
@ LWSMTFL_REPORT_MEAN
Definition lws-metrics.h:39
struct lws_metric_bucket lws_metric_bucket_t
LWS_EXTERN LWS_VISIBLE int lws_metrics_hist_bump_(lws_metric_pub_t *pub, const char *name)
union lws_metric_pub::@127310320105355021375264000263310114310375034363 u
lws_dll2_t list
Definition lws-metrics.h:72
lws_usec_t us_dumped
lws_metric_rpt
@ LMR_PERIODIC
@ LMR_OUTLIER
LWS_EXTERN LWS_VISIBLE int lws_metrics_format(lws_metric_pub_t *pub, lws_metric_bucket_t **sub, char *buf, size_t len)
struct lws_metric_bucket * next
LWS_EXTERN LWS_VISIBLE size_t lws_metrics_tags_serialize(lws_dll2_owner_t *owner, char *buf, size_t len)
struct lws_metrics_tag lws_metrics_tag_t
LWS_EXTERN LWS_VISIBLE const char * lws_metrics_tag_get(lws_dll2_owner_t *owner, const char *name)
lws_usec_t us_start
lws_metric_bucket_t * head
uint64_t u_mt_t
Definition lws-metrics.h:29
LWS_EXTERN LWS_VISIBLE void lws_metrics_tags_destroy(lws_dll2_owner_t *owner)
LWS_VISIBLE LWS_EXTERN int lws_metrics_foreach(struct lws_context *ctx, void *user, int(*cb)(lws_metric_pub_t *pub, void *user))
lws_usec_t us_last
struct lws_metric_caliper lws_metric_caliper_t
struct lws_metric * mt
LWS_EXTERN LWS_VISIBLE int lws_metrics_tag_add(lws_dll2_owner_t *owner, const char *name, const char *val)
struct lws_dll2_owner mtags_owner
@ LMT_OUTLIER
@ LMT_COUNT
@ LMT_NORMAL
@ LMT_FAIL
struct lws_metric_pub lws_metric_pub_t
enum lws_metric_rpt lws_metric_rpt_kind_t
#define lws_metrics_tag_wsi_add(_a, _b, _c)
Definition lws-metrics.h:89
LWS_EXTERN LWS_VISIBLE void lws_metrics_hist_bump_priv_tagged(lws_metric_pub_t *mt, lws_dll2_owner_t *tow, lws_dll2_owner_t *tow2)
LWS_VISIBLE LWS_EXTERN int lws_metrics_hist_bump_describe_wsi(struct lws *wsi, lws_metric_pub_t *pub, const char *name)
const char * name
Definition lws-metrics.h:74