1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker * lws Generic Metrics
3*1c60b9acSAndroid Build Coastguard Worker *
4*1c60b9acSAndroid Build Coastguard Worker * Copyright (C) 2019 - 2021 Andy Green <[email protected]>
5*1c60b9acSAndroid Build Coastguard Worker *
6*1c60b9acSAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a copy
7*1c60b9acSAndroid Build Coastguard Worker * of this software and associated documentation files (the "Software"), to
8*1c60b9acSAndroid Build Coastguard Worker * deal in the Software without restriction, including without limitation the
9*1c60b9acSAndroid Build Coastguard Worker * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10*1c60b9acSAndroid Build Coastguard Worker * sell copies of the Software, and to permit persons to whom the Software is
11*1c60b9acSAndroid Build Coastguard Worker * furnished to do so, subject to the following conditions:
12*1c60b9acSAndroid Build Coastguard Worker *
13*1c60b9acSAndroid Build Coastguard Worker * The above copyright notice and this permission notice shall be included in
14*1c60b9acSAndroid Build Coastguard Worker * all copies or substantial portions of the Software.
15*1c60b9acSAndroid Build Coastguard Worker *
16*1c60b9acSAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*1c60b9acSAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*1c60b9acSAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19*1c60b9acSAndroid Build Coastguard Worker * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*1c60b9acSAndroid Build Coastguard Worker * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21*1c60b9acSAndroid Build Coastguard Worker * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22*1c60b9acSAndroid Build Coastguard Worker * IN THE SOFTWARE.
23*1c60b9acSAndroid Build Coastguard Worker */
24*1c60b9acSAndroid Build Coastguard Worker
25*1c60b9acSAndroid Build Coastguard Worker #include "private-lib-core.h"
26*1c60b9acSAndroid Build Coastguard Worker #include <assert.h>
27*1c60b9acSAndroid Build Coastguard Worker
28*1c60b9acSAndroid Build Coastguard Worker int
lws_metrics_tag_add(lws_dll2_owner_t * owner,const char * name,const char * val)29*1c60b9acSAndroid Build Coastguard Worker lws_metrics_tag_add(lws_dll2_owner_t *owner, const char *name, const char *val)
30*1c60b9acSAndroid Build Coastguard Worker {
31*1c60b9acSAndroid Build Coastguard Worker size_t vl = strlen(val);
32*1c60b9acSAndroid Build Coastguard Worker lws_metrics_tag_t *tag;
33*1c60b9acSAndroid Build Coastguard Worker
34*1c60b9acSAndroid Build Coastguard Worker // lwsl_notice("%s: adding %s=%s\n", __func__, name, val);
35*1c60b9acSAndroid Build Coastguard Worker
36*1c60b9acSAndroid Build Coastguard Worker /*
37*1c60b9acSAndroid Build Coastguard Worker * Remove (in order to replace) any existing tag of same name
38*1c60b9acSAndroid Build Coastguard Worker */
39*1c60b9acSAndroid Build Coastguard Worker
40*1c60b9acSAndroid Build Coastguard Worker lws_start_foreach_dll(struct lws_dll2 *, d, owner->head) {
41*1c60b9acSAndroid Build Coastguard Worker tag = lws_container_of(d, lws_metrics_tag_t, list);
42*1c60b9acSAndroid Build Coastguard Worker
43*1c60b9acSAndroid Build Coastguard Worker if (!strcmp(name, tag->name)) {
44*1c60b9acSAndroid Build Coastguard Worker lws_dll2_remove(&tag->list);
45*1c60b9acSAndroid Build Coastguard Worker lws_free(tag);
46*1c60b9acSAndroid Build Coastguard Worker break;
47*1c60b9acSAndroid Build Coastguard Worker }
48*1c60b9acSAndroid Build Coastguard Worker
49*1c60b9acSAndroid Build Coastguard Worker } lws_end_foreach_dll(d);
50*1c60b9acSAndroid Build Coastguard Worker
51*1c60b9acSAndroid Build Coastguard Worker /*
52*1c60b9acSAndroid Build Coastguard Worker * Create the new tag
53*1c60b9acSAndroid Build Coastguard Worker */
54*1c60b9acSAndroid Build Coastguard Worker
55*1c60b9acSAndroid Build Coastguard Worker tag = lws_malloc(sizeof(*tag) + vl + 1, __func__);
56*1c60b9acSAndroid Build Coastguard Worker if (!tag)
57*1c60b9acSAndroid Build Coastguard Worker return 1;
58*1c60b9acSAndroid Build Coastguard Worker
59*1c60b9acSAndroid Build Coastguard Worker lws_dll2_clear(&tag->list);
60*1c60b9acSAndroid Build Coastguard Worker tag->name = name;
61*1c60b9acSAndroid Build Coastguard Worker memcpy(&tag[1], val, vl + 1);
62*1c60b9acSAndroid Build Coastguard Worker
63*1c60b9acSAndroid Build Coastguard Worker lws_dll2_add_tail(&tag->list, owner);
64*1c60b9acSAndroid Build Coastguard Worker
65*1c60b9acSAndroid Build Coastguard Worker return 0;
66*1c60b9acSAndroid Build Coastguard Worker }
67*1c60b9acSAndroid Build Coastguard Worker
68*1c60b9acSAndroid Build Coastguard Worker int
lws_metrics_tag_wsi_add(struct lws * wsi,const char * name,const char * val)69*1c60b9acSAndroid Build Coastguard Worker lws_metrics_tag_wsi_add(struct lws *wsi, const char *name, const char *val)
70*1c60b9acSAndroid Build Coastguard Worker {
71*1c60b9acSAndroid Build Coastguard Worker __lws_lc_tag(wsi->a.context, NULL, &wsi->lc, "|%s", val);
72*1c60b9acSAndroid Build Coastguard Worker
73*1c60b9acSAndroid Build Coastguard Worker return lws_metrics_tag_add(&wsi->cal_conn.mtags_owner, name, val);
74*1c60b9acSAndroid Build Coastguard Worker }
75*1c60b9acSAndroid Build Coastguard Worker
76*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SECURE_STREAMS)
77*1c60b9acSAndroid Build Coastguard Worker int
lws_metrics_tag_ss_add(struct lws_ss_handle * ss,const char * name,const char * val)78*1c60b9acSAndroid Build Coastguard Worker lws_metrics_tag_ss_add(struct lws_ss_handle *ss, const char *name, const char *val)
79*1c60b9acSAndroid Build Coastguard Worker {
80*1c60b9acSAndroid Build Coastguard Worker __lws_lc_tag(ss->context, NULL, &ss->lc, "|%s", val);
81*1c60b9acSAndroid Build Coastguard Worker return lws_metrics_tag_add(&ss->cal_txn.mtags_owner, name, val);
82*1c60b9acSAndroid Build Coastguard Worker }
83*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SECURE_STREAMS_PROXY_API)
84*1c60b9acSAndroid Build Coastguard Worker int
lws_metrics_tag_sspc_add(struct lws_sspc_handle * sspc,const char * name,const char * val)85*1c60b9acSAndroid Build Coastguard Worker lws_metrics_tag_sspc_add(struct lws_sspc_handle *sspc, const char *name,
86*1c60b9acSAndroid Build Coastguard Worker const char *val)
87*1c60b9acSAndroid Build Coastguard Worker {
88*1c60b9acSAndroid Build Coastguard Worker __lws_lc_tag(sspc->context, NULL, &sspc->lc, "|%s", val);
89*1c60b9acSAndroid Build Coastguard Worker return lws_metrics_tag_add(&sspc->cal_txn.mtags_owner, name, val);
90*1c60b9acSAndroid Build Coastguard Worker }
91*1c60b9acSAndroid Build Coastguard Worker #endif
92*1c60b9acSAndroid Build Coastguard Worker #endif
93*1c60b9acSAndroid Build Coastguard Worker
94*1c60b9acSAndroid Build Coastguard Worker void
lws_metrics_tags_destroy(lws_dll2_owner_t * owner)95*1c60b9acSAndroid Build Coastguard Worker lws_metrics_tags_destroy(lws_dll2_owner_t *owner)
96*1c60b9acSAndroid Build Coastguard Worker {
97*1c60b9acSAndroid Build Coastguard Worker lws_metrics_tag_t *t;
98*1c60b9acSAndroid Build Coastguard Worker
99*1c60b9acSAndroid Build Coastguard Worker lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1, owner->head) {
100*1c60b9acSAndroid Build Coastguard Worker t = lws_container_of(d, lws_metrics_tag_t, list);
101*1c60b9acSAndroid Build Coastguard Worker
102*1c60b9acSAndroid Build Coastguard Worker lws_dll2_remove(&t->list);
103*1c60b9acSAndroid Build Coastguard Worker lws_free(t);
104*1c60b9acSAndroid Build Coastguard Worker
105*1c60b9acSAndroid Build Coastguard Worker } lws_end_foreach_dll_safe(d, d1);
106*1c60b9acSAndroid Build Coastguard Worker }
107*1c60b9acSAndroid Build Coastguard Worker
108*1c60b9acSAndroid Build Coastguard Worker size_t
lws_metrics_tags_serialize(lws_dll2_owner_t * owner,char * buf,size_t len)109*1c60b9acSAndroid Build Coastguard Worker lws_metrics_tags_serialize(lws_dll2_owner_t *owner, char *buf, size_t len)
110*1c60b9acSAndroid Build Coastguard Worker {
111*1c60b9acSAndroid Build Coastguard Worker char *end = buf + len - 1, *p = buf;
112*1c60b9acSAndroid Build Coastguard Worker lws_metrics_tag_t *t;
113*1c60b9acSAndroid Build Coastguard Worker
114*1c60b9acSAndroid Build Coastguard Worker lws_start_foreach_dll(struct lws_dll2 *, d, owner->head) {
115*1c60b9acSAndroid Build Coastguard Worker t = lws_container_of(d, lws_metrics_tag_t, list);
116*1c60b9acSAndroid Build Coastguard Worker
117*1c60b9acSAndroid Build Coastguard Worker p += lws_snprintf(p, lws_ptr_diff_size_t(end, p),
118*1c60b9acSAndroid Build Coastguard Worker "%s=\"%s\"", t->name, (const char *)&t[1]);
119*1c60b9acSAndroid Build Coastguard Worker
120*1c60b9acSAndroid Build Coastguard Worker if (d->next && p + 2 < end)
121*1c60b9acSAndroid Build Coastguard Worker *p++ = ',';
122*1c60b9acSAndroid Build Coastguard Worker
123*1c60b9acSAndroid Build Coastguard Worker } lws_end_foreach_dll(d);
124*1c60b9acSAndroid Build Coastguard Worker
125*1c60b9acSAndroid Build Coastguard Worker *p = '\0';
126*1c60b9acSAndroid Build Coastguard Worker
127*1c60b9acSAndroid Build Coastguard Worker return lws_ptr_diff_size_t(p, buf);
128*1c60b9acSAndroid Build Coastguard Worker }
129*1c60b9acSAndroid Build Coastguard Worker
130*1c60b9acSAndroid Build Coastguard Worker const char *
lws_metrics_tag_get(lws_dll2_owner_t * owner,const char * name)131*1c60b9acSAndroid Build Coastguard Worker lws_metrics_tag_get(lws_dll2_owner_t *owner, const char *name)
132*1c60b9acSAndroid Build Coastguard Worker {
133*1c60b9acSAndroid Build Coastguard Worker lws_metrics_tag_t *t;
134*1c60b9acSAndroid Build Coastguard Worker
135*1c60b9acSAndroid Build Coastguard Worker lws_start_foreach_dll(struct lws_dll2 *, d, owner->head) {
136*1c60b9acSAndroid Build Coastguard Worker t = lws_container_of(d, lws_metrics_tag_t, list);
137*1c60b9acSAndroid Build Coastguard Worker
138*1c60b9acSAndroid Build Coastguard Worker if (!strcmp(name, t->name))
139*1c60b9acSAndroid Build Coastguard Worker return (const char *)&t[1];
140*1c60b9acSAndroid Build Coastguard Worker
141*1c60b9acSAndroid Build Coastguard Worker } lws_end_foreach_dll(d);
142*1c60b9acSAndroid Build Coastguard Worker
143*1c60b9acSAndroid Build Coastguard Worker return NULL;
144*1c60b9acSAndroid Build Coastguard Worker }
145*1c60b9acSAndroid Build Coastguard Worker
146*1c60b9acSAndroid Build Coastguard Worker static int
147*1c60b9acSAndroid Build Coastguard Worker lws_metrics_dump_cb(lws_metric_pub_t *pub, void *user);
148*1c60b9acSAndroid Build Coastguard Worker
149*1c60b9acSAndroid Build Coastguard Worker static void
lws_metrics_report_and_maybe_clear(struct lws_context * ctx,lws_metric_pub_t * pub)150*1c60b9acSAndroid Build Coastguard Worker lws_metrics_report_and_maybe_clear(struct lws_context *ctx, lws_metric_pub_t *pub)
151*1c60b9acSAndroid Build Coastguard Worker {
152*1c60b9acSAndroid Build Coastguard Worker if (!pub->us_first || pub->us_last == pub->us_dumped)
153*1c60b9acSAndroid Build Coastguard Worker return;
154*1c60b9acSAndroid Build Coastguard Worker
155*1c60b9acSAndroid Build Coastguard Worker lws_metrics_dump_cb(pub, ctx);
156*1c60b9acSAndroid Build Coastguard Worker }
157*1c60b9acSAndroid Build Coastguard Worker
158*1c60b9acSAndroid Build Coastguard Worker static void
lws_metrics_periodic_cb(lws_sorted_usec_list_t * sul)159*1c60b9acSAndroid Build Coastguard Worker lws_metrics_periodic_cb(lws_sorted_usec_list_t *sul)
160*1c60b9acSAndroid Build Coastguard Worker {
161*1c60b9acSAndroid Build Coastguard Worker lws_metric_policy_dyn_t *dmp = lws_container_of(sul,
162*1c60b9acSAndroid Build Coastguard Worker lws_metric_policy_dyn_t, sul);
163*1c60b9acSAndroid Build Coastguard Worker struct lws_context *ctx = lws_container_of(dmp->list.owner,
164*1c60b9acSAndroid Build Coastguard Worker struct lws_context, owner_mtr_dynpol);
165*1c60b9acSAndroid Build Coastguard Worker
166*1c60b9acSAndroid Build Coastguard Worker if (!ctx->system_ops || !ctx->system_ops->metric_report)
167*1c60b9acSAndroid Build Coastguard Worker return;
168*1c60b9acSAndroid Build Coastguard Worker
169*1c60b9acSAndroid Build Coastguard Worker lws_start_foreach_dll(struct lws_dll2 *, d, dmp->owner.head) {
170*1c60b9acSAndroid Build Coastguard Worker lws_metric_t *mt = lws_container_of(d, lws_metric_t, list);
171*1c60b9acSAndroid Build Coastguard Worker lws_metric_pub_t *pub = lws_metrics_priv_to_pub(mt);
172*1c60b9acSAndroid Build Coastguard Worker
173*1c60b9acSAndroid Build Coastguard Worker lws_metrics_report_and_maybe_clear(ctx, pub);
174*1c60b9acSAndroid Build Coastguard Worker
175*1c60b9acSAndroid Build Coastguard Worker } lws_end_foreach_dll(d);
176*1c60b9acSAndroid Build Coastguard Worker
177*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SYS_SMD) && defined(LWS_WITH_SECURE_STREAMS)
178*1c60b9acSAndroid Build Coastguard Worker (void)lws_smd_msg_printf(ctx, LWSSMDCL_METRICS,
179*1c60b9acSAndroid Build Coastguard Worker "{\"dump\":\"%s\",\"ts\":%lu}",
180*1c60b9acSAndroid Build Coastguard Worker dmp->policy->name,
181*1c60b9acSAndroid Build Coastguard Worker (long)ctx->last_policy);
182*1c60b9acSAndroid Build Coastguard Worker #endif
183*1c60b9acSAndroid Build Coastguard Worker
184*1c60b9acSAndroid Build Coastguard Worker if (dmp->policy->us_schedule)
185*1c60b9acSAndroid Build Coastguard Worker lws_sul_schedule(ctx, 0, &dmp->sul,
186*1c60b9acSAndroid Build Coastguard Worker lws_metrics_periodic_cb,
187*1c60b9acSAndroid Build Coastguard Worker (lws_usec_t)dmp->policy->us_schedule);
188*1c60b9acSAndroid Build Coastguard Worker }
189*1c60b9acSAndroid Build Coastguard Worker
190*1c60b9acSAndroid Build Coastguard Worker /*
191*1c60b9acSAndroid Build Coastguard Worker * Policies are in two pieces, a const policy and a dynamic part that contains
192*1c60b9acSAndroid Build Coastguard Worker * lists and sul timers for the policy etc. This creates a dynmic part
193*1c60b9acSAndroid Build Coastguard Worker * corresponding to the static part.
194*1c60b9acSAndroid Build Coastguard Worker *
195*1c60b9acSAndroid Build Coastguard Worker * Metrics can exist detached from being bound to any policy about how to
196*1c60b9acSAndroid Build Coastguard Worker * report them, these are collected but not reported unless they later become
197*1c60b9acSAndroid Build Coastguard Worker * bound to a reporting policy dynamically.
198*1c60b9acSAndroid Build Coastguard Worker */
199*1c60b9acSAndroid Build Coastguard Worker
200*1c60b9acSAndroid Build Coastguard Worker lws_metric_policy_dyn_t *
lws_metrics_policy_dyn_create(struct lws_context * ctx,const lws_metric_policy_t * po)201*1c60b9acSAndroid Build Coastguard Worker lws_metrics_policy_dyn_create(struct lws_context *ctx,
202*1c60b9acSAndroid Build Coastguard Worker const lws_metric_policy_t *po)
203*1c60b9acSAndroid Build Coastguard Worker {
204*1c60b9acSAndroid Build Coastguard Worker lws_metric_policy_dyn_t *dmet;
205*1c60b9acSAndroid Build Coastguard Worker
206*1c60b9acSAndroid Build Coastguard Worker dmet = lws_zalloc(sizeof(*dmet), __func__);
207*1c60b9acSAndroid Build Coastguard Worker if (!dmet)
208*1c60b9acSAndroid Build Coastguard Worker return NULL;
209*1c60b9acSAndroid Build Coastguard Worker
210*1c60b9acSAndroid Build Coastguard Worker dmet->policy = po;
211*1c60b9acSAndroid Build Coastguard Worker lws_dll2_add_tail(&dmet->list, &ctx->owner_mtr_dynpol);
212*1c60b9acSAndroid Build Coastguard Worker
213*1c60b9acSAndroid Build Coastguard Worker if (po->us_schedule)
214*1c60b9acSAndroid Build Coastguard Worker lws_sul_schedule(ctx, 0, &dmet->sul,
215*1c60b9acSAndroid Build Coastguard Worker lws_metrics_periodic_cb,
216*1c60b9acSAndroid Build Coastguard Worker (lws_usec_t)po->us_schedule);
217*1c60b9acSAndroid Build Coastguard Worker
218*1c60b9acSAndroid Build Coastguard Worker return dmet;
219*1c60b9acSAndroid Build Coastguard Worker }
220*1c60b9acSAndroid Build Coastguard Worker
221*1c60b9acSAndroid Build Coastguard Worker /*
222*1c60b9acSAndroid Build Coastguard Worker * Get a dynamic metrics policy from the const one, may return NULL if OOM
223*1c60b9acSAndroid Build Coastguard Worker */
224*1c60b9acSAndroid Build Coastguard Worker
225*1c60b9acSAndroid Build Coastguard Worker lws_metric_policy_dyn_t *
lws_metrics_policy_get_dyn(struct lws_context * ctx,const lws_metric_policy_t * po)226*1c60b9acSAndroid Build Coastguard Worker lws_metrics_policy_get_dyn(struct lws_context *ctx,
227*1c60b9acSAndroid Build Coastguard Worker const lws_metric_policy_t *po)
228*1c60b9acSAndroid Build Coastguard Worker {
229*1c60b9acSAndroid Build Coastguard Worker lws_start_foreach_dll(struct lws_dll2 *, d, ctx->owner_mtr_dynpol.head) {
230*1c60b9acSAndroid Build Coastguard Worker lws_metric_policy_dyn_t *dm =
231*1c60b9acSAndroid Build Coastguard Worker lws_container_of(d, lws_metric_policy_dyn_t, list);
232*1c60b9acSAndroid Build Coastguard Worker
233*1c60b9acSAndroid Build Coastguard Worker if (dm->policy == po)
234*1c60b9acSAndroid Build Coastguard Worker return dm;
235*1c60b9acSAndroid Build Coastguard Worker
236*1c60b9acSAndroid Build Coastguard Worker } lws_end_foreach_dll(d);
237*1c60b9acSAndroid Build Coastguard Worker
238*1c60b9acSAndroid Build Coastguard Worker /*
239*1c60b9acSAndroid Build Coastguard Worker * no dyn policy part for this const policy --> create one
240*1c60b9acSAndroid Build Coastguard Worker *
241*1c60b9acSAndroid Build Coastguard Worker * We want a dynamic part for listing metrics that bound to the policy
242*1c60b9acSAndroid Build Coastguard Worker */
243*1c60b9acSAndroid Build Coastguard Worker
244*1c60b9acSAndroid Build Coastguard Worker return lws_metrics_policy_dyn_create(ctx, po);
245*1c60b9acSAndroid Build Coastguard Worker }
246*1c60b9acSAndroid Build Coastguard Worker
247*1c60b9acSAndroid Build Coastguard Worker static int
lws_metrics_check_in_policy(const char * polstring,const char * name)248*1c60b9acSAndroid Build Coastguard Worker lws_metrics_check_in_policy(const char *polstring, const char *name)
249*1c60b9acSAndroid Build Coastguard Worker {
250*1c60b9acSAndroid Build Coastguard Worker struct lws_tokenize ts;
251*1c60b9acSAndroid Build Coastguard Worker
252*1c60b9acSAndroid Build Coastguard Worker memset(&ts, 0, sizeof(ts));
253*1c60b9acSAndroid Build Coastguard Worker
254*1c60b9acSAndroid Build Coastguard Worker ts.start = polstring;
255*1c60b9acSAndroid Build Coastguard Worker ts.len = strlen(polstring);
256*1c60b9acSAndroid Build Coastguard Worker ts.flags = (uint16_t)(LWS_TOKENIZE_F_MINUS_NONTERM |
257*1c60b9acSAndroid Build Coastguard Worker LWS_TOKENIZE_F_ASTERISK_NONTERM |
258*1c60b9acSAndroid Build Coastguard Worker LWS_TOKENIZE_F_COMMA_SEP_LIST |
259*1c60b9acSAndroid Build Coastguard Worker LWS_TOKENIZE_F_NO_FLOATS |
260*1c60b9acSAndroid Build Coastguard Worker LWS_TOKENIZE_F_DOT_NONTERM);
261*1c60b9acSAndroid Build Coastguard Worker
262*1c60b9acSAndroid Build Coastguard Worker do {
263*1c60b9acSAndroid Build Coastguard Worker ts.e = (int8_t)lws_tokenize(&ts);
264*1c60b9acSAndroid Build Coastguard Worker
265*1c60b9acSAndroid Build Coastguard Worker if (ts.e == LWS_TOKZE_TOKEN) {
266*1c60b9acSAndroid Build Coastguard Worker if (!lws_strcmp_wildcard(ts.token, ts.token_len, name,
267*1c60b9acSAndroid Build Coastguard Worker strlen(name)))
268*1c60b9acSAndroid Build Coastguard Worker /* yes, we are mentioned in this guy's policy */
269*1c60b9acSAndroid Build Coastguard Worker return 0;
270*1c60b9acSAndroid Build Coastguard Worker }
271*1c60b9acSAndroid Build Coastguard Worker } while (ts.e > 0);
272*1c60b9acSAndroid Build Coastguard Worker
273*1c60b9acSAndroid Build Coastguard Worker /* no, this policy doesn't apply to a metric with our name */
274*1c60b9acSAndroid Build Coastguard Worker
275*1c60b9acSAndroid Build Coastguard Worker return 1;
276*1c60b9acSAndroid Build Coastguard Worker }
277*1c60b9acSAndroid Build Coastguard Worker
278*1c60b9acSAndroid Build Coastguard Worker static const lws_metric_policy_t *
lws_metrics_find_policy(struct lws_context * ctx,const char * name)279*1c60b9acSAndroid Build Coastguard Worker lws_metrics_find_policy(struct lws_context *ctx, const char *name)
280*1c60b9acSAndroid Build Coastguard Worker {
281*1c60b9acSAndroid Build Coastguard Worker const lws_metric_policy_t *mp = ctx->metrics_policies;
282*1c60b9acSAndroid Build Coastguard Worker
283*1c60b9acSAndroid Build Coastguard Worker if (!mp) {
284*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SECURE_STREAMS)
285*1c60b9acSAndroid Build Coastguard Worker if (ctx->pss_policies)
286*1c60b9acSAndroid Build Coastguard Worker mp = ctx->pss_policies->metrics;
287*1c60b9acSAndroid Build Coastguard Worker #endif
288*1c60b9acSAndroid Build Coastguard Worker if (!mp)
289*1c60b9acSAndroid Build Coastguard Worker return NULL;
290*1c60b9acSAndroid Build Coastguard Worker }
291*1c60b9acSAndroid Build Coastguard Worker
292*1c60b9acSAndroid Build Coastguard Worker while (mp) {
293*1c60b9acSAndroid Build Coastguard Worker if (mp->report && !lws_metrics_check_in_policy(mp->report, name))
294*1c60b9acSAndroid Build Coastguard Worker return mp;
295*1c60b9acSAndroid Build Coastguard Worker
296*1c60b9acSAndroid Build Coastguard Worker mp = mp->next;
297*1c60b9acSAndroid Build Coastguard Worker }
298*1c60b9acSAndroid Build Coastguard Worker
299*1c60b9acSAndroid Build Coastguard Worker return NULL;
300*1c60b9acSAndroid Build Coastguard Worker }
301*1c60b9acSAndroid Build Coastguard Worker
302*1c60b9acSAndroid Build Coastguard Worker /*
303*1c60b9acSAndroid Build Coastguard Worker * Create a lws_metric_t, bind to a named policy if possible (or add to the
304*1c60b9acSAndroid Build Coastguard Worker * context list of unbound metrics) and set its lws_system
305*1c60b9acSAndroid Build Coastguard Worker * idx. The metrics objects themselves are typically composed into other
306*1c60b9acSAndroid Build Coastguard Worker * objects and are well-known composed members of them.
307*1c60b9acSAndroid Build Coastguard Worker */
308*1c60b9acSAndroid Build Coastguard Worker
309*1c60b9acSAndroid Build Coastguard Worker lws_metric_t *
lws_metric_create(struct lws_context * ctx,uint8_t flags,const char * name)310*1c60b9acSAndroid Build Coastguard Worker lws_metric_create(struct lws_context *ctx, uint8_t flags, const char *name)
311*1c60b9acSAndroid Build Coastguard Worker {
312*1c60b9acSAndroid Build Coastguard Worker const lws_metric_policy_t *po;
313*1c60b9acSAndroid Build Coastguard Worker lws_metric_policy_dyn_t *dmp;
314*1c60b9acSAndroid Build Coastguard Worker lws_metric_pub_t *pub;
315*1c60b9acSAndroid Build Coastguard Worker lws_metric_t *mt;
316*1c60b9acSAndroid Build Coastguard Worker char pname[32];
317*1c60b9acSAndroid Build Coastguard Worker size_t nl;
318*1c60b9acSAndroid Build Coastguard Worker
319*1c60b9acSAndroid Build Coastguard Worker if (ctx->metrics_prefix) {
320*1c60b9acSAndroid Build Coastguard Worker
321*1c60b9acSAndroid Build Coastguard Worker /*
322*1c60b9acSAndroid Build Coastguard Worker * In multi-process case, we want to prefix metrics from this
323*1c60b9acSAndroid Build Coastguard Worker * process / context with a string distinguishing which
324*1c60b9acSAndroid Build Coastguard Worker * application they came from
325*1c60b9acSAndroid Build Coastguard Worker */
326*1c60b9acSAndroid Build Coastguard Worker
327*1c60b9acSAndroid Build Coastguard Worker nl = (size_t)lws_snprintf(pname, sizeof(pname) - 1, "%s.%s",
328*1c60b9acSAndroid Build Coastguard Worker ctx->metrics_prefix, name);
329*1c60b9acSAndroid Build Coastguard Worker name = pname;
330*1c60b9acSAndroid Build Coastguard Worker } else
331*1c60b9acSAndroid Build Coastguard Worker nl = strlen(name);
332*1c60b9acSAndroid Build Coastguard Worker
333*1c60b9acSAndroid Build Coastguard Worker mt = (lws_metric_t *)lws_zalloc(sizeof(*mt) /* private */ +
334*1c60b9acSAndroid Build Coastguard Worker sizeof(lws_metric_pub_t) +
335*1c60b9acSAndroid Build Coastguard Worker nl + 1 /* copy of metric name */,
336*1c60b9acSAndroid Build Coastguard Worker __func__);
337*1c60b9acSAndroid Build Coastguard Worker if (!mt)
338*1c60b9acSAndroid Build Coastguard Worker return NULL;
339*1c60b9acSAndroid Build Coastguard Worker
340*1c60b9acSAndroid Build Coastguard Worker pub = lws_metrics_priv_to_pub(mt);
341*1c60b9acSAndroid Build Coastguard Worker pub->name = (char *)pub + sizeof(lws_metric_pub_t);
342*1c60b9acSAndroid Build Coastguard Worker memcpy((char *)pub->name, name, nl + 1);
343*1c60b9acSAndroid Build Coastguard Worker pub->flags = flags;
344*1c60b9acSAndroid Build Coastguard Worker
345*1c60b9acSAndroid Build Coastguard Worker /* after these common members, we have to use the right type */
346*1c60b9acSAndroid Build Coastguard Worker
347*1c60b9acSAndroid Build Coastguard Worker if (!(flags & LWSMTFL_REPORT_HIST)) {
348*1c60b9acSAndroid Build Coastguard Worker /* anything is smaller or equal to this */
349*1c60b9acSAndroid Build Coastguard Worker pub->u.agg.min = ~(u_mt_t)0;
350*1c60b9acSAndroid Build Coastguard Worker pub->us_first = lws_now_usecs();
351*1c60b9acSAndroid Build Coastguard Worker }
352*1c60b9acSAndroid Build Coastguard Worker
353*1c60b9acSAndroid Build Coastguard Worker mt->ctx = ctx;
354*1c60b9acSAndroid Build Coastguard Worker
355*1c60b9acSAndroid Build Coastguard Worker /*
356*1c60b9acSAndroid Build Coastguard Worker * Let's see if we can bind to a reporting policy straight away
357*1c60b9acSAndroid Build Coastguard Worker */
358*1c60b9acSAndroid Build Coastguard Worker
359*1c60b9acSAndroid Build Coastguard Worker po = lws_metrics_find_policy(ctx, name);
360*1c60b9acSAndroid Build Coastguard Worker if (po) {
361*1c60b9acSAndroid Build Coastguard Worker dmp = lws_metrics_policy_get_dyn(ctx, po);
362*1c60b9acSAndroid Build Coastguard Worker if (dmp) {
363*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: metpol %s\n", __func__, name);
364*1c60b9acSAndroid Build Coastguard Worker lws_dll2_add_tail(&mt->list, &dmp->owner);
365*1c60b9acSAndroid Build Coastguard Worker
366*1c60b9acSAndroid Build Coastguard Worker return 0;
367*1c60b9acSAndroid Build Coastguard Worker }
368*1c60b9acSAndroid Build Coastguard Worker }
369*1c60b9acSAndroid Build Coastguard Worker
370*1c60b9acSAndroid Build Coastguard Worker /*
371*1c60b9acSAndroid Build Coastguard Worker * If not, well, let's go on without and maybe later at runtime, he'll
372*1c60b9acSAndroid Build Coastguard Worker * get interested in us and apply a reporting policy
373*1c60b9acSAndroid Build Coastguard Worker */
374*1c60b9acSAndroid Build Coastguard Worker
375*1c60b9acSAndroid Build Coastguard Worker lws_dll2_add_tail(&mt->list, &ctx->owner_mtr_no_pol);
376*1c60b9acSAndroid Build Coastguard Worker
377*1c60b9acSAndroid Build Coastguard Worker return mt;
378*1c60b9acSAndroid Build Coastguard Worker }
379*1c60b9acSAndroid Build Coastguard Worker
380*1c60b9acSAndroid Build Coastguard Worker /*
381*1c60b9acSAndroid Build Coastguard Worker * If our metric is bound to a reporting policy, return a pointer to it,
382*1c60b9acSAndroid Build Coastguard Worker * otherwise NULL
383*1c60b9acSAndroid Build Coastguard Worker */
384*1c60b9acSAndroid Build Coastguard Worker
385*1c60b9acSAndroid Build Coastguard Worker const lws_metric_policy_t *
lws_metric_get_policy(lws_metric_t * mt)386*1c60b9acSAndroid Build Coastguard Worker lws_metric_get_policy(lws_metric_t *mt)
387*1c60b9acSAndroid Build Coastguard Worker {
388*1c60b9acSAndroid Build Coastguard Worker lws_metric_policy_dyn_t *dp;
389*1c60b9acSAndroid Build Coastguard Worker
390*1c60b9acSAndroid Build Coastguard Worker /*
391*1c60b9acSAndroid Build Coastguard Worker * Our metric must either be on the "no policy" context list or
392*1c60b9acSAndroid Build Coastguard Worker * listed by the dynamic part of the policy it is bound to
393*1c60b9acSAndroid Build Coastguard Worker */
394*1c60b9acSAndroid Build Coastguard Worker assert(mt->list.owner);
395*1c60b9acSAndroid Build Coastguard Worker
396*1c60b9acSAndroid Build Coastguard Worker if ((char *)mt->list.owner >= (char *)mt->ctx &&
397*1c60b9acSAndroid Build Coastguard Worker (char *)mt->list.owner < (char *)mt->ctx + sizeof(struct lws_context))
398*1c60b9acSAndroid Build Coastguard Worker /* we are on the "no policy" context list */
399*1c60b9acSAndroid Build Coastguard Worker return NULL;
400*1c60b9acSAndroid Build Coastguard Worker
401*1c60b9acSAndroid Build Coastguard Worker /* we are listed by a dynamic policy owner */
402*1c60b9acSAndroid Build Coastguard Worker
403*1c60b9acSAndroid Build Coastguard Worker dp = lws_container_of(mt->list.owner, lws_metric_policy_dyn_t, owner);
404*1c60b9acSAndroid Build Coastguard Worker
405*1c60b9acSAndroid Build Coastguard Worker /* return the const policy the dynamic policy represents */
406*1c60b9acSAndroid Build Coastguard Worker
407*1c60b9acSAndroid Build Coastguard Worker return dp->policy;
408*1c60b9acSAndroid Build Coastguard Worker }
409*1c60b9acSAndroid Build Coastguard Worker
410*1c60b9acSAndroid Build Coastguard Worker void
lws_metric_rebind_policies(struct lws_context * ctx)411*1c60b9acSAndroid Build Coastguard Worker lws_metric_rebind_policies(struct lws_context *ctx)
412*1c60b9acSAndroid Build Coastguard Worker {
413*1c60b9acSAndroid Build Coastguard Worker const lws_metric_policy_t *po;
414*1c60b9acSAndroid Build Coastguard Worker lws_metric_policy_dyn_t *dmp;
415*1c60b9acSAndroid Build Coastguard Worker
416*1c60b9acSAndroid Build Coastguard Worker lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1,
417*1c60b9acSAndroid Build Coastguard Worker ctx->owner_mtr_no_pol.head) {
418*1c60b9acSAndroid Build Coastguard Worker lws_metric_t *mt = lws_container_of(d, lws_metric_t, list);
419*1c60b9acSAndroid Build Coastguard Worker lws_metric_pub_t *pub = lws_metrics_priv_to_pub(mt);
420*1c60b9acSAndroid Build Coastguard Worker
421*1c60b9acSAndroid Build Coastguard Worker po = lws_metrics_find_policy(ctx, pub->name);
422*1c60b9acSAndroid Build Coastguard Worker if (po) {
423*1c60b9acSAndroid Build Coastguard Worker dmp = lws_metrics_policy_get_dyn(ctx, po);
424*1c60b9acSAndroid Build Coastguard Worker if (dmp) {
425*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: %s <- pol %s\n", __func__,
426*1c60b9acSAndroid Build Coastguard Worker pub->name, po->name);
427*1c60b9acSAndroid Build Coastguard Worker lws_dll2_remove(&mt->list);
428*1c60b9acSAndroid Build Coastguard Worker lws_dll2_add_tail(&mt->list, &dmp->owner);
429*1c60b9acSAndroid Build Coastguard Worker }
430*1c60b9acSAndroid Build Coastguard Worker } else
431*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s: no pol for %s\n", __func__, pub->name);
432*1c60b9acSAndroid Build Coastguard Worker
433*1c60b9acSAndroid Build Coastguard Worker } lws_end_foreach_dll_safe(d, d1);
434*1c60b9acSAndroid Build Coastguard Worker }
435*1c60b9acSAndroid Build Coastguard Worker
436*1c60b9acSAndroid Build Coastguard Worker int
lws_metric_destroy(lws_metric_t ** pmt,int keep)437*1c60b9acSAndroid Build Coastguard Worker lws_metric_destroy(lws_metric_t **pmt, int keep)
438*1c60b9acSAndroid Build Coastguard Worker {
439*1c60b9acSAndroid Build Coastguard Worker lws_metric_t *mt = *pmt;
440*1c60b9acSAndroid Build Coastguard Worker lws_metric_pub_t *pub = lws_metrics_priv_to_pub(mt);
441*1c60b9acSAndroid Build Coastguard Worker
442*1c60b9acSAndroid Build Coastguard Worker if (!mt)
443*1c60b9acSAndroid Build Coastguard Worker return 0;
444*1c60b9acSAndroid Build Coastguard Worker
445*1c60b9acSAndroid Build Coastguard Worker lws_dll2_remove(&mt->list);
446*1c60b9acSAndroid Build Coastguard Worker
447*1c60b9acSAndroid Build Coastguard Worker if (keep) {
448*1c60b9acSAndroid Build Coastguard Worker lws_dll2_add_tail(&mt->list, &mt->ctx->owner_mtr_no_pol);
449*1c60b9acSAndroid Build Coastguard Worker
450*1c60b9acSAndroid Build Coastguard Worker return 0;
451*1c60b9acSAndroid Build Coastguard Worker }
452*1c60b9acSAndroid Build Coastguard Worker
453*1c60b9acSAndroid Build Coastguard Worker if (pub->flags & LWSMTFL_REPORT_HIST) {
454*1c60b9acSAndroid Build Coastguard Worker lws_metric_bucket_t *b = pub->u.hist.head, *b1;
455*1c60b9acSAndroid Build Coastguard Worker
456*1c60b9acSAndroid Build Coastguard Worker pub->u.hist.head = NULL;
457*1c60b9acSAndroid Build Coastguard Worker
458*1c60b9acSAndroid Build Coastguard Worker while (b) {
459*1c60b9acSAndroid Build Coastguard Worker b1 = b->next;
460*1c60b9acSAndroid Build Coastguard Worker lws_free(b);
461*1c60b9acSAndroid Build Coastguard Worker b = b1;
462*1c60b9acSAndroid Build Coastguard Worker }
463*1c60b9acSAndroid Build Coastguard Worker }
464*1c60b9acSAndroid Build Coastguard Worker
465*1c60b9acSAndroid Build Coastguard Worker lws_free(mt);
466*1c60b9acSAndroid Build Coastguard Worker *pmt = NULL;
467*1c60b9acSAndroid Build Coastguard Worker
468*1c60b9acSAndroid Build Coastguard Worker return 0;
469*1c60b9acSAndroid Build Coastguard Worker }
470*1c60b9acSAndroid Build Coastguard Worker
471*1c60b9acSAndroid Build Coastguard Worker /*
472*1c60b9acSAndroid Build Coastguard Worker * Allow an existing metric to have its reporting policy changed at runtime
473*1c60b9acSAndroid Build Coastguard Worker */
474*1c60b9acSAndroid Build Coastguard Worker
475*1c60b9acSAndroid Build Coastguard Worker int
lws_metric_switch_policy(lws_metric_t * mt,const char * polname)476*1c60b9acSAndroid Build Coastguard Worker lws_metric_switch_policy(lws_metric_t *mt, const char *polname)
477*1c60b9acSAndroid Build Coastguard Worker {
478*1c60b9acSAndroid Build Coastguard Worker const lws_metric_policy_t *po;
479*1c60b9acSAndroid Build Coastguard Worker lws_metric_policy_dyn_t *dmp;
480*1c60b9acSAndroid Build Coastguard Worker
481*1c60b9acSAndroid Build Coastguard Worker po = lws_metrics_find_policy(mt->ctx, polname);
482*1c60b9acSAndroid Build Coastguard Worker if (!po)
483*1c60b9acSAndroid Build Coastguard Worker return 1;
484*1c60b9acSAndroid Build Coastguard Worker
485*1c60b9acSAndroid Build Coastguard Worker dmp = lws_metrics_policy_get_dyn(mt->ctx, po);
486*1c60b9acSAndroid Build Coastguard Worker if (!dmp)
487*1c60b9acSAndroid Build Coastguard Worker return 1;
488*1c60b9acSAndroid Build Coastguard Worker
489*1c60b9acSAndroid Build Coastguard Worker lws_dll2_remove(&mt->list);
490*1c60b9acSAndroid Build Coastguard Worker lws_dll2_add_tail(&mt->list, &dmp->owner);
491*1c60b9acSAndroid Build Coastguard Worker
492*1c60b9acSAndroid Build Coastguard Worker return 0;
493*1c60b9acSAndroid Build Coastguard Worker }
494*1c60b9acSAndroid Build Coastguard Worker
495*1c60b9acSAndroid Build Coastguard Worker /*
496*1c60b9acSAndroid Build Coastguard Worker * If keep is set, don't destroy existing metrics objects, just detach them
497*1c60b9acSAndroid Build Coastguard Worker * from the policy being deleted and keep track of them on ctx->
498*1c60b9acSAndroid Build Coastguard Worker * owner_mtr_no_pol
499*1c60b9acSAndroid Build Coastguard Worker */
500*1c60b9acSAndroid Build Coastguard Worker
501*1c60b9acSAndroid Build Coastguard Worker void
lws_metric_policy_dyn_destroy(lws_metric_policy_dyn_t * dm,int keep)502*1c60b9acSAndroid Build Coastguard Worker lws_metric_policy_dyn_destroy(lws_metric_policy_dyn_t *dm, int keep)
503*1c60b9acSAndroid Build Coastguard Worker {
504*1c60b9acSAndroid Build Coastguard Worker lws_sul_cancel(&dm->sul);
505*1c60b9acSAndroid Build Coastguard Worker
506*1c60b9acSAndroid Build Coastguard Worker lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1, dm->owner.head) {
507*1c60b9acSAndroid Build Coastguard Worker lws_metric_t *m = lws_container_of(d, lws_metric_t, list);
508*1c60b9acSAndroid Build Coastguard Worker
509*1c60b9acSAndroid Build Coastguard Worker lws_metric_destroy(&m, keep);
510*1c60b9acSAndroid Build Coastguard Worker
511*1c60b9acSAndroid Build Coastguard Worker } lws_end_foreach_dll_safe(d, d1);
512*1c60b9acSAndroid Build Coastguard Worker
513*1c60b9acSAndroid Build Coastguard Worker lws_sul_cancel(&dm->sul);
514*1c60b9acSAndroid Build Coastguard Worker
515*1c60b9acSAndroid Build Coastguard Worker lws_dll2_remove(&dm->list);
516*1c60b9acSAndroid Build Coastguard Worker lws_free(dm);
517*1c60b9acSAndroid Build Coastguard Worker }
518*1c60b9acSAndroid Build Coastguard Worker
519*1c60b9acSAndroid Build Coastguard Worker /*
520*1c60b9acSAndroid Build Coastguard Worker * Destroy all dynamic metrics policies, deinit any metrics still using them
521*1c60b9acSAndroid Build Coastguard Worker */
522*1c60b9acSAndroid Build Coastguard Worker
523*1c60b9acSAndroid Build Coastguard Worker void
lws_metrics_destroy(struct lws_context * ctx)524*1c60b9acSAndroid Build Coastguard Worker lws_metrics_destroy(struct lws_context *ctx)
525*1c60b9acSAndroid Build Coastguard Worker {
526*1c60b9acSAndroid Build Coastguard Worker lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1,
527*1c60b9acSAndroid Build Coastguard Worker ctx->owner_mtr_dynpol.head) {
528*1c60b9acSAndroid Build Coastguard Worker lws_metric_policy_dyn_t *dm =
529*1c60b9acSAndroid Build Coastguard Worker lws_container_of(d, lws_metric_policy_dyn_t, list);
530*1c60b9acSAndroid Build Coastguard Worker
531*1c60b9acSAndroid Build Coastguard Worker lws_metric_policy_dyn_destroy(dm, 0); /* don't keep */
532*1c60b9acSAndroid Build Coastguard Worker
533*1c60b9acSAndroid Build Coastguard Worker } lws_end_foreach_dll_safe(d, d1);
534*1c60b9acSAndroid Build Coastguard Worker
535*1c60b9acSAndroid Build Coastguard Worker /* destroy metrics with no current policy too... */
536*1c60b9acSAndroid Build Coastguard Worker
537*1c60b9acSAndroid Build Coastguard Worker lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1,
538*1c60b9acSAndroid Build Coastguard Worker ctx->owner_mtr_no_pol.head) {
539*1c60b9acSAndroid Build Coastguard Worker lws_metric_t *mt = lws_container_of(d, lws_metric_t, list);
540*1c60b9acSAndroid Build Coastguard Worker
541*1c60b9acSAndroid Build Coastguard Worker lws_metric_destroy(&mt, 0); /* don't keep */
542*1c60b9acSAndroid Build Coastguard Worker
543*1c60b9acSAndroid Build Coastguard Worker } lws_end_foreach_dll_safe(d, d1);
544*1c60b9acSAndroid Build Coastguard Worker
545*1c60b9acSAndroid Build Coastguard Worker /* ... that's the whole allocated metrics footprint gone... */
546*1c60b9acSAndroid Build Coastguard Worker }
547*1c60b9acSAndroid Build Coastguard Worker
548*1c60b9acSAndroid Build Coastguard Worker int
lws_metrics_hist_bump_(lws_metric_pub_t * pub,const char * name)549*1c60b9acSAndroid Build Coastguard Worker lws_metrics_hist_bump_(lws_metric_pub_t *pub, const char *name)
550*1c60b9acSAndroid Build Coastguard Worker {
551*1c60b9acSAndroid Build Coastguard Worker lws_metric_bucket_t *buck = pub->u.hist.head;
552*1c60b9acSAndroid Build Coastguard Worker size_t nl = strlen(name);
553*1c60b9acSAndroid Build Coastguard Worker char *nm;
554*1c60b9acSAndroid Build Coastguard Worker
555*1c60b9acSAndroid Build Coastguard Worker if (!(pub->flags & LWSMTFL_REPORT_HIST)) {
556*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: %s not histogram: flags %d\n", __func__,
557*1c60b9acSAndroid Build Coastguard Worker pub->name, pub->flags);
558*1c60b9acSAndroid Build Coastguard Worker assert(0);
559*1c60b9acSAndroid Build Coastguard Worker }
560*1c60b9acSAndroid Build Coastguard Worker assert(nl < 255);
561*1c60b9acSAndroid Build Coastguard Worker
562*1c60b9acSAndroid Build Coastguard Worker pub->us_last = lws_now_usecs();
563*1c60b9acSAndroid Build Coastguard Worker if (!pub->us_first)
564*1c60b9acSAndroid Build Coastguard Worker pub->us_first = pub->us_last;
565*1c60b9acSAndroid Build Coastguard Worker
566*1c60b9acSAndroid Build Coastguard Worker while (buck) {
567*1c60b9acSAndroid Build Coastguard Worker if (lws_metric_bucket_name_len(buck) == nl &&
568*1c60b9acSAndroid Build Coastguard Worker !strcmp(name, lws_metric_bucket_name(buck))) {
569*1c60b9acSAndroid Build Coastguard Worker buck->count++;
570*1c60b9acSAndroid Build Coastguard Worker goto happy;
571*1c60b9acSAndroid Build Coastguard Worker }
572*1c60b9acSAndroid Build Coastguard Worker buck = buck->next;
573*1c60b9acSAndroid Build Coastguard Worker }
574*1c60b9acSAndroid Build Coastguard Worker
575*1c60b9acSAndroid Build Coastguard Worker buck = lws_malloc(sizeof(*buck) + nl + 2, __func__);
576*1c60b9acSAndroid Build Coastguard Worker if (!buck)
577*1c60b9acSAndroid Build Coastguard Worker return 1;
578*1c60b9acSAndroid Build Coastguard Worker
579*1c60b9acSAndroid Build Coastguard Worker nm = (char *)buck + sizeof(*buck);
580*1c60b9acSAndroid Build Coastguard Worker /* length byte at beginning of name, avoid struct alignment overhead */
581*1c60b9acSAndroid Build Coastguard Worker *nm = (char)nl;
582*1c60b9acSAndroid Build Coastguard Worker memcpy(nm + 1, name, nl + 1);
583*1c60b9acSAndroid Build Coastguard Worker
584*1c60b9acSAndroid Build Coastguard Worker buck->next = pub->u.hist.head;
585*1c60b9acSAndroid Build Coastguard Worker pub->u.hist.head = buck;
586*1c60b9acSAndroid Build Coastguard Worker buck->count = 1;
587*1c60b9acSAndroid Build Coastguard Worker pub->u.hist.list_size++;
588*1c60b9acSAndroid Build Coastguard Worker
589*1c60b9acSAndroid Build Coastguard Worker happy:
590*1c60b9acSAndroid Build Coastguard Worker pub->u.hist.total_count++;
591*1c60b9acSAndroid Build Coastguard Worker
592*1c60b9acSAndroid Build Coastguard Worker return 0;
593*1c60b9acSAndroid Build Coastguard Worker }
594*1c60b9acSAndroid Build Coastguard Worker
595*1c60b9acSAndroid Build Coastguard Worker int
lws_metrics_hist_bump_describe_wsi(struct lws * wsi,lws_metric_pub_t * pub,const char * name)596*1c60b9acSAndroid Build Coastguard Worker lws_metrics_hist_bump_describe_wsi(struct lws *wsi, lws_metric_pub_t *pub,
597*1c60b9acSAndroid Build Coastguard Worker const char *name)
598*1c60b9acSAndroid Build Coastguard Worker {
599*1c60b9acSAndroid Build Coastguard Worker char desc[192], d1[48], *p = desc, *end = desc + sizeof(desc);
600*1c60b9acSAndroid Build Coastguard Worker
601*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SECURE_STREAMS)
602*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SECURE_STREAMS_PROXY_API)
603*1c60b9acSAndroid Build Coastguard Worker if (wsi->client_bound_sspc) {
604*1c60b9acSAndroid Build Coastguard Worker lws_sspc_handle_t *h = (lws_sspc_handle_t *)wsi->a.opaque_user_data;
605*1c60b9acSAndroid Build Coastguard Worker if (h)
606*1c60b9acSAndroid Build Coastguard Worker p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "ss=\"%s\",",
607*1c60b9acSAndroid Build Coastguard Worker h->ssi.streamtype);
608*1c60b9acSAndroid Build Coastguard Worker } else
609*1c60b9acSAndroid Build Coastguard Worker if (wsi->client_proxy_onward) {
610*1c60b9acSAndroid Build Coastguard Worker lws_ss_handle_t *h = (lws_ss_handle_t *)wsi->a.opaque_user_data;
611*1c60b9acSAndroid Build Coastguard Worker struct conn *conn = h->conn_if_sspc_onw;
612*1c60b9acSAndroid Build Coastguard Worker
613*1c60b9acSAndroid Build Coastguard Worker if (conn && conn->ss)
614*1c60b9acSAndroid Build Coastguard Worker p += lws_snprintf(p, lws_ptr_diff_size_t(end, p),
615*1c60b9acSAndroid Build Coastguard Worker "ss=\"%s\",",
616*1c60b9acSAndroid Build Coastguard Worker conn->ss->info.streamtype);
617*1c60b9acSAndroid Build Coastguard Worker } else
618*1c60b9acSAndroid Build Coastguard Worker #endif
619*1c60b9acSAndroid Build Coastguard Worker if (wsi->for_ss) {
620*1c60b9acSAndroid Build Coastguard Worker lws_ss_handle_t *h = (lws_ss_handle_t *)wsi->a.opaque_user_data;
621*1c60b9acSAndroid Build Coastguard Worker if (h)
622*1c60b9acSAndroid Build Coastguard Worker p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "ss=\"%s\",",
623*1c60b9acSAndroid Build Coastguard Worker h->info.streamtype);
624*1c60b9acSAndroid Build Coastguard Worker }
625*1c60b9acSAndroid Build Coastguard Worker #endif
626*1c60b9acSAndroid Build Coastguard Worker
627*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
628*1c60b9acSAndroid Build Coastguard Worker if (wsi->stash && wsi->stash->cis[CIS_HOST])
629*1c60b9acSAndroid Build Coastguard Worker p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "hostname=\"%s\",",
630*1c60b9acSAndroid Build Coastguard Worker wsi->stash->cis[CIS_HOST]);
631*1c60b9acSAndroid Build Coastguard Worker #endif
632*1c60b9acSAndroid Build Coastguard Worker
633*1c60b9acSAndroid Build Coastguard Worker lws_sa46_write_numeric_address(&wsi->sa46_peer, d1, sizeof(d1));
634*1c60b9acSAndroid Build Coastguard Worker p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "peer=\"%s\",", d1);
635*1c60b9acSAndroid Build Coastguard Worker
636*1c60b9acSAndroid Build Coastguard Worker p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "%s", name);
637*1c60b9acSAndroid Build Coastguard Worker
638*1c60b9acSAndroid Build Coastguard Worker lws_metrics_hist_bump_(pub, desc);
639*1c60b9acSAndroid Build Coastguard Worker
640*1c60b9acSAndroid Build Coastguard Worker return 0;
641*1c60b9acSAndroid Build Coastguard Worker }
642*1c60b9acSAndroid Build Coastguard Worker
643*1c60b9acSAndroid Build Coastguard Worker int
lws_metrics_foreach(struct lws_context * ctx,void * user,int (* cb)(lws_metric_pub_t * pub,void * user))644*1c60b9acSAndroid Build Coastguard Worker lws_metrics_foreach(struct lws_context *ctx, void *user,
645*1c60b9acSAndroid Build Coastguard Worker int (*cb)(lws_metric_pub_t *pub, void *user))
646*1c60b9acSAndroid Build Coastguard Worker {
647*1c60b9acSAndroid Build Coastguard Worker int n;
648*1c60b9acSAndroid Build Coastguard Worker
649*1c60b9acSAndroid Build Coastguard Worker lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1,
650*1c60b9acSAndroid Build Coastguard Worker ctx->owner_mtr_no_pol.head) {
651*1c60b9acSAndroid Build Coastguard Worker lws_metric_t *mt = lws_container_of(d, lws_metric_t, list);
652*1c60b9acSAndroid Build Coastguard Worker
653*1c60b9acSAndroid Build Coastguard Worker n = cb(lws_metrics_priv_to_pub(mt), user);
654*1c60b9acSAndroid Build Coastguard Worker if (n)
655*1c60b9acSAndroid Build Coastguard Worker return n;
656*1c60b9acSAndroid Build Coastguard Worker
657*1c60b9acSAndroid Build Coastguard Worker } lws_end_foreach_dll_safe(d, d1);
658*1c60b9acSAndroid Build Coastguard Worker
659*1c60b9acSAndroid Build Coastguard Worker lws_start_foreach_dll_safe(struct lws_dll2 *, d2, d3,
660*1c60b9acSAndroid Build Coastguard Worker ctx->owner_mtr_dynpol.head) {
661*1c60b9acSAndroid Build Coastguard Worker lws_metric_policy_dyn_t *dm =
662*1c60b9acSAndroid Build Coastguard Worker lws_container_of(d2, lws_metric_policy_dyn_t, list);
663*1c60b9acSAndroid Build Coastguard Worker
664*1c60b9acSAndroid Build Coastguard Worker lws_start_foreach_dll_safe(struct lws_dll2 *, e, e1,
665*1c60b9acSAndroid Build Coastguard Worker dm->owner.head) {
666*1c60b9acSAndroid Build Coastguard Worker
667*1c60b9acSAndroid Build Coastguard Worker lws_metric_t *mt = lws_container_of(e, lws_metric_t, list);
668*1c60b9acSAndroid Build Coastguard Worker
669*1c60b9acSAndroid Build Coastguard Worker n = cb(lws_metrics_priv_to_pub(mt), user);
670*1c60b9acSAndroid Build Coastguard Worker if (n)
671*1c60b9acSAndroid Build Coastguard Worker return n;
672*1c60b9acSAndroid Build Coastguard Worker
673*1c60b9acSAndroid Build Coastguard Worker } lws_end_foreach_dll_safe(e, e1);
674*1c60b9acSAndroid Build Coastguard Worker
675*1c60b9acSAndroid Build Coastguard Worker } lws_end_foreach_dll_safe(d2, d3);
676*1c60b9acSAndroid Build Coastguard Worker
677*1c60b9acSAndroid Build Coastguard Worker return 0;
678*1c60b9acSAndroid Build Coastguard Worker }
679*1c60b9acSAndroid Build Coastguard Worker
680*1c60b9acSAndroid Build Coastguard Worker static int
lws_metrics_dump_cb(lws_metric_pub_t * pub,void * user)681*1c60b9acSAndroid Build Coastguard Worker lws_metrics_dump_cb(lws_metric_pub_t *pub, void *user)
682*1c60b9acSAndroid Build Coastguard Worker {
683*1c60b9acSAndroid Build Coastguard Worker struct lws_context *ctx = (struct lws_context *)user;
684*1c60b9acSAndroid Build Coastguard Worker int n;
685*1c60b9acSAndroid Build Coastguard Worker
686*1c60b9acSAndroid Build Coastguard Worker if (!ctx->system_ops || !ctx->system_ops->metric_report)
687*1c60b9acSAndroid Build Coastguard Worker return 0;
688*1c60b9acSAndroid Build Coastguard Worker
689*1c60b9acSAndroid Build Coastguard Worker /*
690*1c60b9acSAndroid Build Coastguard Worker * return nonzero to reset stats
691*1c60b9acSAndroid Build Coastguard Worker */
692*1c60b9acSAndroid Build Coastguard Worker
693*1c60b9acSAndroid Build Coastguard Worker n = ctx->system_ops->metric_report(pub);
694*1c60b9acSAndroid Build Coastguard Worker
695*1c60b9acSAndroid Build Coastguard Worker /* track when we dumped it... */
696*1c60b9acSAndroid Build Coastguard Worker
697*1c60b9acSAndroid Build Coastguard Worker pub->us_first = pub->us_dumped = lws_now_usecs();
698*1c60b9acSAndroid Build Coastguard Worker pub->us_last = 0;
699*1c60b9acSAndroid Build Coastguard Worker
700*1c60b9acSAndroid Build Coastguard Worker if (!n)
701*1c60b9acSAndroid Build Coastguard Worker return 0;
702*1c60b9acSAndroid Build Coastguard Worker
703*1c60b9acSAndroid Build Coastguard Worker /* ... and clear it back to 0 */
704*1c60b9acSAndroid Build Coastguard Worker
705*1c60b9acSAndroid Build Coastguard Worker if (pub->flags & LWSMTFL_REPORT_HIST) {
706*1c60b9acSAndroid Build Coastguard Worker lws_metric_bucket_t *b = pub->u.hist.head, *b1;
707*1c60b9acSAndroid Build Coastguard Worker pub->u.hist.head = NULL;
708*1c60b9acSAndroid Build Coastguard Worker
709*1c60b9acSAndroid Build Coastguard Worker while (b) {
710*1c60b9acSAndroid Build Coastguard Worker b1 = b->next;
711*1c60b9acSAndroid Build Coastguard Worker lws_free(b);
712*1c60b9acSAndroid Build Coastguard Worker b = b1;
713*1c60b9acSAndroid Build Coastguard Worker }
714*1c60b9acSAndroid Build Coastguard Worker pub->u.hist.total_count = 0;
715*1c60b9acSAndroid Build Coastguard Worker pub->u.hist.list_size = 0;
716*1c60b9acSAndroid Build Coastguard Worker } else
717*1c60b9acSAndroid Build Coastguard Worker memset(&pub->u.agg, 0, sizeof(pub->u.agg));
718*1c60b9acSAndroid Build Coastguard Worker
719*1c60b9acSAndroid Build Coastguard Worker return 0;
720*1c60b9acSAndroid Build Coastguard Worker }
721*1c60b9acSAndroid Build Coastguard Worker
722*1c60b9acSAndroid Build Coastguard Worker void
lws_metrics_dump(struct lws_context * ctx)723*1c60b9acSAndroid Build Coastguard Worker lws_metrics_dump(struct lws_context *ctx)
724*1c60b9acSAndroid Build Coastguard Worker {
725*1c60b9acSAndroid Build Coastguard Worker lws_metrics_foreach(ctx, ctx, lws_metrics_dump_cb);
726*1c60b9acSAndroid Build Coastguard Worker }
727*1c60b9acSAndroid Build Coastguard Worker
728*1c60b9acSAndroid Build Coastguard Worker static int
_lws_metrics_format(lws_metric_pub_t * pub,lws_usec_t now,int gng,char * buf,size_t len)729*1c60b9acSAndroid Build Coastguard Worker _lws_metrics_format(lws_metric_pub_t *pub, lws_usec_t now, int gng,
730*1c60b9acSAndroid Build Coastguard Worker char *buf, size_t len)
731*1c60b9acSAndroid Build Coastguard Worker {
732*1c60b9acSAndroid Build Coastguard Worker const lws_humanize_unit_t *schema = humanize_schema_si;
733*1c60b9acSAndroid Build Coastguard Worker char *end = buf + len - 1, *obuf = buf;
734*1c60b9acSAndroid Build Coastguard Worker
735*1c60b9acSAndroid Build Coastguard Worker if (pub->flags & LWSMTFL_REPORT_DUTY_WALLCLOCK_US)
736*1c60b9acSAndroid Build Coastguard Worker schema = humanize_schema_us;
737*1c60b9acSAndroid Build Coastguard Worker
738*1c60b9acSAndroid Build Coastguard Worker if (!(pub->flags & LWSMTFL_REPORT_MEAN)) {
739*1c60b9acSAndroid Build Coastguard Worker /* only the sum is meaningful */
740*1c60b9acSAndroid Build Coastguard Worker if (pub->flags & LWSMTFL_REPORT_DUTY_WALLCLOCK_US) {
741*1c60b9acSAndroid Build Coastguard Worker
742*1c60b9acSAndroid Build Coastguard Worker buf += lws_snprintf(buf, lws_ptr_diff_size_t(end, buf), " %u, ",
743*1c60b9acSAndroid Build Coastguard Worker (unsigned int)pub->u.agg.count[gng]);
744*1c60b9acSAndroid Build Coastguard Worker
745*1c60b9acSAndroid Build Coastguard Worker buf += lws_humanize(buf, lws_ptr_diff_size_t(end, buf),
746*1c60b9acSAndroid Build Coastguard Worker (uint64_t)pub->u.agg.sum[gng],
747*1c60b9acSAndroid Build Coastguard Worker humanize_schema_us);
748*1c60b9acSAndroid Build Coastguard Worker
749*1c60b9acSAndroid Build Coastguard Worker buf += lws_snprintf(buf, lws_ptr_diff_size_t(end, buf), " / ");
750*1c60b9acSAndroid Build Coastguard Worker
751*1c60b9acSAndroid Build Coastguard Worker buf += lws_humanize(buf, lws_ptr_diff_size_t(end, buf),
752*1c60b9acSAndroid Build Coastguard Worker (uint64_t)(now - pub->us_first),
753*1c60b9acSAndroid Build Coastguard Worker humanize_schema_us);
754*1c60b9acSAndroid Build Coastguard Worker
755*1c60b9acSAndroid Build Coastguard Worker buf += lws_snprintf(buf, lws_ptr_diff_size_t(end, buf),
756*1c60b9acSAndroid Build Coastguard Worker " (%d%%)", (int)((100 * pub->u.agg.sum[gng]) /
757*1c60b9acSAndroid Build Coastguard Worker (unsigned long)(now - pub->us_first)));
758*1c60b9acSAndroid Build Coastguard Worker } else {
759*1c60b9acSAndroid Build Coastguard Worker /* it's a monotonic ordinal, like total tx */
760*1c60b9acSAndroid Build Coastguard Worker buf += lws_snprintf(buf, lws_ptr_diff_size_t(end, buf), "(%u) ",
761*1c60b9acSAndroid Build Coastguard Worker (unsigned int)pub->u.agg.count[gng]);
762*1c60b9acSAndroid Build Coastguard Worker buf += lws_humanize(buf, lws_ptr_diff_size_t(end, buf),
763*1c60b9acSAndroid Build Coastguard Worker (uint64_t)pub->u.agg.sum[gng],
764*1c60b9acSAndroid Build Coastguard Worker humanize_schema_si);
765*1c60b9acSAndroid Build Coastguard Worker }
766*1c60b9acSAndroid Build Coastguard Worker
767*1c60b9acSAndroid Build Coastguard Worker } else {
768*1c60b9acSAndroid Build Coastguard Worker buf += lws_snprintf(buf, lws_ptr_diff_size_t(end, buf), "%u, mean: ", (unsigned int)pub->u.agg.count[gng]);
769*1c60b9acSAndroid Build Coastguard Worker /* the average over the period is meaningful */
770*1c60b9acSAndroid Build Coastguard Worker buf += lws_humanize(buf, lws_ptr_diff_size_t(end, buf),
771*1c60b9acSAndroid Build Coastguard Worker (uint64_t)(pub->u.agg.count[gng] ?
772*1c60b9acSAndroid Build Coastguard Worker pub->u.agg.sum[gng] / pub->u.agg.count[gng] : 0),
773*1c60b9acSAndroid Build Coastguard Worker schema);
774*1c60b9acSAndroid Build Coastguard Worker }
775*1c60b9acSAndroid Build Coastguard Worker
776*1c60b9acSAndroid Build Coastguard Worker return lws_ptr_diff(buf, obuf);
777*1c60b9acSAndroid Build Coastguard Worker }
778*1c60b9acSAndroid Build Coastguard Worker
779*1c60b9acSAndroid Build Coastguard Worker int
lws_metrics_format(lws_metric_pub_t * pub,lws_metric_bucket_t ** sub,char * buf,size_t len)780*1c60b9acSAndroid Build Coastguard Worker lws_metrics_format(lws_metric_pub_t *pub, lws_metric_bucket_t **sub, char *buf, size_t len)
781*1c60b9acSAndroid Build Coastguard Worker {
782*1c60b9acSAndroid Build Coastguard Worker char *end = buf + len - 1, *obuf = buf;
783*1c60b9acSAndroid Build Coastguard Worker lws_usec_t t = lws_now_usecs();
784*1c60b9acSAndroid Build Coastguard Worker const lws_humanize_unit_t *schema = humanize_schema_si;
785*1c60b9acSAndroid Build Coastguard Worker
786*1c60b9acSAndroid Build Coastguard Worker if (pub->flags & LWSMTFL_REPORT_DUTY_WALLCLOCK_US)
787*1c60b9acSAndroid Build Coastguard Worker schema = humanize_schema_us;
788*1c60b9acSAndroid Build Coastguard Worker
789*1c60b9acSAndroid Build Coastguard Worker if (pub->flags & LWSMTFL_REPORT_HIST) {
790*1c60b9acSAndroid Build Coastguard Worker
791*1c60b9acSAndroid Build Coastguard Worker if (*sub == NULL)
792*1c60b9acSAndroid Build Coastguard Worker return 0;
793*1c60b9acSAndroid Build Coastguard Worker
794*1c60b9acSAndroid Build Coastguard Worker if (*sub) {
795*1c60b9acSAndroid Build Coastguard Worker buf += lws_snprintf(buf, lws_ptr_diff_size_t(end, buf),
796*1c60b9acSAndroid Build Coastguard Worker "%s{%s} %llu", pub->name,
797*1c60b9acSAndroid Build Coastguard Worker lws_metric_bucket_name(*sub),
798*1c60b9acSAndroid Build Coastguard Worker (unsigned long long)(*sub)->count);
799*1c60b9acSAndroid Build Coastguard Worker
800*1c60b9acSAndroid Build Coastguard Worker *sub = (*sub)->next;
801*1c60b9acSAndroid Build Coastguard Worker }
802*1c60b9acSAndroid Build Coastguard Worker
803*1c60b9acSAndroid Build Coastguard Worker goto happy;
804*1c60b9acSAndroid Build Coastguard Worker }
805*1c60b9acSAndroid Build Coastguard Worker
806*1c60b9acSAndroid Build Coastguard Worker buf += lws_snprintf(buf, lws_ptr_diff_size_t(end, buf), "%s: ",
807*1c60b9acSAndroid Build Coastguard Worker pub->name);
808*1c60b9acSAndroid Build Coastguard Worker
809*1c60b9acSAndroid Build Coastguard Worker if (!pub->u.agg.count[METRES_GO] && !pub->u.agg.count[METRES_NOGO])
810*1c60b9acSAndroid Build Coastguard Worker return 0;
811*1c60b9acSAndroid Build Coastguard Worker
812*1c60b9acSAndroid Build Coastguard Worker if (pub->u.agg.count[METRES_GO]) {
813*1c60b9acSAndroid Build Coastguard Worker if (!(pub->flags & LWSMTFL_REPORT_ONLY_GO))
814*1c60b9acSAndroid Build Coastguard Worker buf += lws_snprintf(buf, lws_ptr_diff_size_t(end, buf),
815*1c60b9acSAndroid Build Coastguard Worker "Go: ");
816*1c60b9acSAndroid Build Coastguard Worker buf += _lws_metrics_format(pub, t, METRES_GO, buf,
817*1c60b9acSAndroid Build Coastguard Worker lws_ptr_diff_size_t(end, buf));
818*1c60b9acSAndroid Build Coastguard Worker }
819*1c60b9acSAndroid Build Coastguard Worker
820*1c60b9acSAndroid Build Coastguard Worker if (!(pub->flags & LWSMTFL_REPORT_ONLY_GO) && pub->u.agg.count[METRES_NOGO]) {
821*1c60b9acSAndroid Build Coastguard Worker buf += lws_snprintf(buf, lws_ptr_diff_size_t(end, buf), ", NoGo: ");
822*1c60b9acSAndroid Build Coastguard Worker buf += _lws_metrics_format(pub, t, METRES_NOGO, buf,
823*1c60b9acSAndroid Build Coastguard Worker lws_ptr_diff_size_t(end, buf));
824*1c60b9acSAndroid Build Coastguard Worker }
825*1c60b9acSAndroid Build Coastguard Worker
826*1c60b9acSAndroid Build Coastguard Worker if (pub->flags & LWSMTFL_REPORT_MEAN) {
827*1c60b9acSAndroid Build Coastguard Worker buf += lws_snprintf(buf, lws_ptr_diff_size_t(end, buf), ", min: ");
828*1c60b9acSAndroid Build Coastguard Worker buf += lws_humanize(buf, lws_ptr_diff_size_t(end, buf), pub->u.agg.min,
829*1c60b9acSAndroid Build Coastguard Worker schema);
830*1c60b9acSAndroid Build Coastguard Worker buf += lws_snprintf(buf, lws_ptr_diff_size_t(end, buf), ", max: ");
831*1c60b9acSAndroid Build Coastguard Worker buf += lws_humanize(buf, lws_ptr_diff_size_t(end, buf), pub->u.agg.max,
832*1c60b9acSAndroid Build Coastguard Worker schema);
833*1c60b9acSAndroid Build Coastguard Worker }
834*1c60b9acSAndroid Build Coastguard Worker
835*1c60b9acSAndroid Build Coastguard Worker happy:
836*1c60b9acSAndroid Build Coastguard Worker if (pub->flags & LWSMTFL_REPORT_HIST)
837*1c60b9acSAndroid Build Coastguard Worker return 1;
838*1c60b9acSAndroid Build Coastguard Worker
839*1c60b9acSAndroid Build Coastguard Worker *sub = NULL;
840*1c60b9acSAndroid Build Coastguard Worker
841*1c60b9acSAndroid Build Coastguard Worker return lws_ptr_diff(buf, obuf);
842*1c60b9acSAndroid Build Coastguard Worker }
843*1c60b9acSAndroid Build Coastguard Worker
844*1c60b9acSAndroid Build Coastguard Worker /*
845*1c60b9acSAndroid Build Coastguard Worker * We want to, at least internally, record an event... depending on the policy,
846*1c60b9acSAndroid Build Coastguard Worker * that might cause us to call through to the lws_system apis, or just update
847*1c60b9acSAndroid Build Coastguard Worker * our local stats about it and dump at the next periodic chance (also set by
848*1c60b9acSAndroid Build Coastguard Worker * the policy)
849*1c60b9acSAndroid Build Coastguard Worker */
850*1c60b9acSAndroid Build Coastguard Worker
851*1c60b9acSAndroid Build Coastguard Worker void
lws_metric_event(lws_metric_t * mt,char go_nogo,u_mt_t val)852*1c60b9acSAndroid Build Coastguard Worker lws_metric_event(lws_metric_t *mt, char go_nogo, u_mt_t val)
853*1c60b9acSAndroid Build Coastguard Worker {
854*1c60b9acSAndroid Build Coastguard Worker lws_metric_pub_t *pub;
855*1c60b9acSAndroid Build Coastguard Worker
856*1c60b9acSAndroid Build Coastguard Worker assert((go_nogo & 0xfe) == 0);
857*1c60b9acSAndroid Build Coastguard Worker
858*1c60b9acSAndroid Build Coastguard Worker if (!mt)
859*1c60b9acSAndroid Build Coastguard Worker return;
860*1c60b9acSAndroid Build Coastguard Worker
861*1c60b9acSAndroid Build Coastguard Worker pub = lws_metrics_priv_to_pub(mt);
862*1c60b9acSAndroid Build Coastguard Worker assert(!(pub->flags & LWSMTFL_REPORT_HIST));
863*1c60b9acSAndroid Build Coastguard Worker
864*1c60b9acSAndroid Build Coastguard Worker pub->us_last = lws_now_usecs();
865*1c60b9acSAndroid Build Coastguard Worker if (!pub->us_first)
866*1c60b9acSAndroid Build Coastguard Worker pub->us_first = pub->us_last;
867*1c60b9acSAndroid Build Coastguard Worker pub->u.agg.count[(int)go_nogo]++;
868*1c60b9acSAndroid Build Coastguard Worker pub->u.agg.sum[(int)go_nogo] += val;
869*1c60b9acSAndroid Build Coastguard Worker if (val > pub->u.agg.max)
870*1c60b9acSAndroid Build Coastguard Worker pub->u.agg.max = val;
871*1c60b9acSAndroid Build Coastguard Worker if (val < pub->u.agg.min)
872*1c60b9acSAndroid Build Coastguard Worker pub->u.agg.min = val;
873*1c60b9acSAndroid Build Coastguard Worker
874*1c60b9acSAndroid Build Coastguard Worker if (pub->flags & LWSMTFL_REPORT_OOB)
875*1c60b9acSAndroid Build Coastguard Worker lws_metrics_report_and_maybe_clear(mt->ctx, pub);
876*1c60b9acSAndroid Build Coastguard Worker }
877*1c60b9acSAndroid Build Coastguard Worker
878*1c60b9acSAndroid Build Coastguard Worker
879*1c60b9acSAndroid Build Coastguard Worker void
lws_metrics_hist_bump_priv_tagged(lws_metric_pub_t * mt,lws_dll2_owner_t * tow,lws_dll2_owner_t * tow2)880*1c60b9acSAndroid Build Coastguard Worker lws_metrics_hist_bump_priv_tagged(lws_metric_pub_t *mt, lws_dll2_owner_t *tow,
881*1c60b9acSAndroid Build Coastguard Worker lws_dll2_owner_t *tow2)
882*1c60b9acSAndroid Build Coastguard Worker {
883*1c60b9acSAndroid Build Coastguard Worker char qual[192];
884*1c60b9acSAndroid Build Coastguard Worker size_t p;
885*1c60b9acSAndroid Build Coastguard Worker
886*1c60b9acSAndroid Build Coastguard Worker p = lws_metrics_tags_serialize(tow, qual, sizeof(qual));
887*1c60b9acSAndroid Build Coastguard Worker if (tow2)
888*1c60b9acSAndroid Build Coastguard Worker lws_metrics_tags_serialize(tow2, qual + p,
889*1c60b9acSAndroid Build Coastguard Worker sizeof(qual) - p);
890*1c60b9acSAndroid Build Coastguard Worker
891*1c60b9acSAndroid Build Coastguard Worker lws_metrics_hist_bump(mt, qual);
892*1c60b9acSAndroid Build Coastguard Worker }
893