1*1c60b9acSAndroid Build Coastguard Worker## `lws_metrics` 2*1c60b9acSAndroid Build Coastguard Worker 3*1c60b9acSAndroid Build Coastguard Worker### Introduction 4*1c60b9acSAndroid Build Coastguard Worker 5*1c60b9acSAndroid Build Coastguard Worker`lws_metrics` records and aggregates **events** at all lws layers. 6*1c60b9acSAndroid Build Coastguard Worker 7*1c60b9acSAndroid Build Coastguard WorkerThere are three distinct parts: 8*1c60b9acSAndroid Build Coastguard Worker 9*1c60b9acSAndroid Build Coastguard Worker - the architecture inside lws for collecting and aggregating / decimating the 10*1c60b9acSAndroid Build Coastguard Worker events and maintaining statistics about them, these are lws_metric objects 11*1c60b9acSAndroid Build Coastguard Worker 12*1c60b9acSAndroid Build Coastguard Worker - an external handler for forwarding aggregated metrics. An lws_system ops 13*1c60b9acSAndroid Build Coastguard Worker interface to pass on the aggregated metrics to an external backend. lws 14*1c60b9acSAndroid Build Coastguard Worker presents its own public metrics objects and leaves it to the external 15*1c60b9acSAndroid Build Coastguard Worker code to have a shim to marry the lws metrics up to whatever is needed in the 16*1c60b9acSAndroid Build Coastguard Worker metrics backend 17*1c60b9acSAndroid Build Coastguard Worker 18*1c60b9acSAndroid Build Coastguard Worker - a policy for when to emit each type of aggregated information to the external 19*1c60b9acSAndroid Build Coastguard Worker handler. This can be specified in the generic Secure Streams policy, or 20*1c60b9acSAndroid Build Coastguard Worker a linked-list of lws_metric_policy_t object passed it at context creation in 21*1c60b9acSAndroid Build Coastguard Worker `info.metrics_policies`. 22*1c60b9acSAndroid Build Coastguard Worker 23*1c60b9acSAndroid Build Coastguard WorkerThe external backend interface code may itself make use of lws connectivity apis 24*1c60b9acSAndroid Build Coastguard Workerincluding Secure Streams itself, and lws metrics are available on that too. 25*1c60b9acSAndroid Build Coastguard Worker 26*1c60b9acSAndroid Build Coastguard Worker### `lws_metrics` policy-based reporting 27*1c60b9acSAndroid Build Coastguard Worker 28*1c60b9acSAndroid Build Coastguard WorkerNormally metrics implementations are fixed at build-time and cannot change 29*1c60b9acSAndroid Build Coastguard Workerwithout a coordinated reflash of devices along with a change of backend schema. 30*1c60b9acSAndroid Build Coastguard Worker 31*1c60b9acSAndroid Build Coastguard Worker`lws_metrics` separates out the objects and code necessary to collect and 32*1c60b9acSAndroid Build Coastguard Workeraggregate the data cheaply, and the reporting policy that controls if, or how 33*1c60b9acSAndroid Build Coastguard Workeroften, the results are reported to the external handler. 34*1c60b9acSAndroid Build Coastguard Worker 35*1c60b9acSAndroid Build Coastguard Worker 36*1c60b9acSAndroid Build Coastguard Worker 37*1c60b9acSAndroid Build Coastguard WorkerMetrics are created with a namespace name and the policy applies itself to those 38*1c60b9acSAndroid Build Coastguard Workerby listing the names, with wildcards allowed, the policy applies to, eg if 39*1c60b9acSAndroid Build Coastguard Workerspecified in the Secure Streams JSON policy 40*1c60b9acSAndroid Build Coastguard Worker 41*1c60b9acSAndroid Build Coastguard Worker``` 42*1c60b9acSAndroid Build Coastguard Worker ... 43*1c60b9acSAndroid Build Coastguard Worker "metrics": [ 44*1c60b9acSAndroid Build Coastguard Worker { 45*1c60b9acSAndroid Build Coastguard Worker "name": "tensecs", 46*1c60b9acSAndroid Build Coastguard Worker "us_schedule": 10000000, 47*1c60b9acSAndroid Build Coastguard Worker "report": "cpu.*" 48*1c60b9acSAndroid Build Coastguard Worker }, { 49*1c60b9acSAndroid Build Coastguard Worker "name": "30secs", 50*1c60b9acSAndroid Build Coastguard Worker "us_schedule": 30000000, 51*1c60b9acSAndroid Build Coastguard Worker "report": "n.cn.*, n.http.*, n.ss.*, vh.*" 52*1c60b9acSAndroid Build Coastguard Worker } 53*1c60b9acSAndroid Build Coastguard Worker ], 54*1c60b9acSAndroid Build Coastguard Worker ... 55*1c60b9acSAndroid Build Coastguard Worker``` 56*1c60b9acSAndroid Build Coastguard Worker 57*1c60b9acSAndroid Build Coastguard WorkerMetrics that do not have a reporting policy do not report, but continue to 58*1c60b9acSAndroid Build Coastguard Workeraggregate measurements in case they are bound to a policy dynamically later. 59*1c60b9acSAndroid Build Coastguard Worker 60*1c60b9acSAndroid Build Coastguard Worker### Freeform metrics naming 61*1c60b9acSAndroid Build Coastguard Worker 62*1c60b9acSAndroid Build Coastguard WorkerThere is no predefined metrics schema, metrics objects, including those created 63*1c60b9acSAndroid Build Coastguard Workerby applications, can independently choose their own name in a namespace like 64*1c60b9acSAndroid Build Coastguard Worker"cpu.srv" or "n.cn.dns", and can set a prefix for all metrics names created in a 65*1c60b9acSAndroid Build Coastguard Workercontext (by setting `info.metrics_prefix` at context creation time). 66*1c60b9acSAndroid Build Coastguard Worker 67*1c60b9acSAndroid Build Coastguard WorkerThis allows multiple processes in a single device to expose copies of the same 68*1c60b9acSAndroid Build Coastguard Workermetrics in an individually addressable way, eg, if the UI process specifies the 69*1c60b9acSAndroid Build Coastguard Workerprefix "ui", then its lws metrics like "cpu.srv" will actually be created as 70*1c60b9acSAndroid Build Coastguard Worker"ui.cpu.srv". 71*1c60b9acSAndroid Build Coastguard Worker 72*1c60b9acSAndroid Build Coastguard WorkerApplications can freely define their own `lws_metrics` measurements with their 73*1c60b9acSAndroid Build Coastguard Workerown names in the namespace too, without central registration, and refer to those 74*1c60b9acSAndroid Build Coastguard Workernames in the reporting policy same as any other metric names. 75*1c60b9acSAndroid Build Coastguard Worker 76*1c60b9acSAndroid Build Coastguard WorkerIf the metrics backend requires a fixed schema, the mapping between the 77*1c60b9acSAndroid Build Coastguard Worker`lws_metrics` names and the backend schema indexes will be done in the 78*1c60b9acSAndroid Build Coastguard Worker`lws_system` external reporting api implementation alone. Metrics objects 79*1c60b9acSAndroid Build Coastguard Workercontain a `void * backend_opaque` that is ignored by lws and can be set and 80*1c60b9acSAndroid Build Coastguard Workerread by the external reporting handler implementation to facilitate that. 81*1c60b9acSAndroid Build Coastguard Worker 82*1c60b9acSAndroid Build Coastguard Worker### Histogram metrics tagging 83*1c60b9acSAndroid Build Coastguard Worker 84*1c60b9acSAndroid Build Coastguard WorkerHistogram metrics track differently-qualified results in the same metric, for 85*1c60b9acSAndroid Build Coastguard Workerexample the metric `n.cn.failures` maintains separate result counts for all 86*1c60b9acSAndroid Build Coastguard Workervariations and kinds of failure. 87*1c60b9acSAndroid Build Coastguard Worker 88*1c60b9acSAndroid Build Coastguard Worker``` 89*1c60b9acSAndroid Build Coastguard Worker[2021/03/01 06:34:05:6570] U: my_metric_report: ssproxy.n.cn.failures{ss="badcert_selfsigned",hostname="invalidca.badcert.warmcat.com",peer="46.105.127.147",tls="invalidca"} 2 90*1c60b9acSAndroid Build Coastguard Worker[2021/03/01 06:34:05:6573] U: my_metric_report: ssproxy.n.cn.failures{hostname="invalidca.badcert.warmcat.com",peer="46.105.127.147",tls="invalidca"} 1 91*1c60b9acSAndroid Build Coastguard Worker[2021/03/01 06:34:05:6576] U: my_metric_report: ssproxy.n.cn.failures{ss="badcert_expired",hostname="warmcat.com",peer="46.105.127.147",tls="expired"} 2 92*1c60b9acSAndroid Build Coastguard Worker[2021/03/01 06:34:05:6578] U: my_metric_report: ssproxy.n.cn.failures{hostname="warmcat.com",peer="46.105.127.147",tls="expired"} 1 93*1c60b9acSAndroid Build Coastguard Worker[2021/03/01 06:34:05:6580] U: my_metric_report: ssproxy.n.cn.failures{ss="badcert_hostname",hostname="hostname.badcert.warmcat.com",peer="46.105.127.147",tls="hostname"} 2 94*1c60b9acSAndroid Build Coastguard Worker[2021/03/01 06:34:05:6583] U: my_metric_report: ssproxy.n.cn.failures{hostname="hostname.badcert.warmcat.com",peer="46.105.127.147",tls="hostname"} 1 95*1c60b9acSAndroid Build Coastguard Worker[2021/03/01 06:34:05:6585] U: my_metric_report: ssproxy.n.cn.failures{dns="nores -2"} 8 96*1c60b9acSAndroid Build Coastguard Worker``` 97*1c60b9acSAndroid Build Coastguard Worker 98*1c60b9acSAndroid Build Coastguard WorkerThe user handler for metrics is expected to iterate these, in the provided 99*1c60b9acSAndroid Build Coastguard Workerexamples (eg, minimal-secure-streams-testsfail) 100*1c60b9acSAndroid Build Coastguard Worker 101*1c60b9acSAndroid Build Coastguard Worker``` 102*1c60b9acSAndroid Build Coastguard Worker#if defined(LWS_WITH_SYS_METRICS) 103*1c60b9acSAndroid Build Coastguard Workerstatic int 104*1c60b9acSAndroid Build Coastguard Workermy_metric_report(lws_metric_pub_t *mp) 105*1c60b9acSAndroid Build Coastguard Worker{ 106*1c60b9acSAndroid Build Coastguard Worker lws_metric_bucket_t *sub = mp->u.hist.head; 107*1c60b9acSAndroid Build Coastguard Worker char buf[192]; 108*1c60b9acSAndroid Build Coastguard Worker 109*1c60b9acSAndroid Build Coastguard Worker do { 110*1c60b9acSAndroid Build Coastguard Worker if (lws_metrics_format(mp, &sub, buf, sizeof(buf))) 111*1c60b9acSAndroid Build Coastguard Worker lwsl_user("%s: %s\n", __func__, buf); 112*1c60b9acSAndroid Build Coastguard Worker } while ((mp->flags & LWSMTFL_REPORT_HIST) && sub); 113*1c60b9acSAndroid Build Coastguard Worker 114*1c60b9acSAndroid Build Coastguard Worker /* 0 = leave metric to accumulate, 1 = reset the metric */ 115*1c60b9acSAndroid Build Coastguard Worker 116*1c60b9acSAndroid Build Coastguard Worker return 1; 117*1c60b9acSAndroid Build Coastguard Worker} 118*1c60b9acSAndroid Build Coastguard Worker 119*1c60b9acSAndroid Build Coastguard Workerstatic const lws_system_ops_t system_ops = { 120*1c60b9acSAndroid Build Coastguard Worker .metric_report = my_metric_report, 121*1c60b9acSAndroid Build Coastguard Worker}; 122*1c60b9acSAndroid Build Coastguard Worker 123*1c60b9acSAndroid Build Coastguard Worker#endif 124*1c60b9acSAndroid Build Coastguard Worker``` 125*1c60b9acSAndroid Build Coastguard Worker 126*1c60b9acSAndroid Build Coastguard Worker### `lws_metrics` decimation 127*1c60b9acSAndroid Build Coastguard Worker 128*1c60b9acSAndroid Build Coastguard WorkerEvent information can easily be produced faster than it can be transmitted, or 129*1c60b9acSAndroid Build Coastguard Workeris useful to record if everything is working. In the case that things are not 130*1c60b9acSAndroid Build Coastguard Workerworking, then eventually the number of events that are unable to be forwarded 131*1c60b9acSAndroid Build Coastguard Workerto the backend would overwhelm the local storage. 132*1c60b9acSAndroid Build Coastguard Worker 133*1c60b9acSAndroid Build Coastguard WorkerFor that reason, the metrics objects are designed to absorb and summarize a 134*1c60b9acSAndroid Build Coastguard Workerpotentially large number of events cheaply by aggregating them, so even extreme 135*1c60b9acSAndroid Build Coastguard Workersituations can be tracked meaningfully inbetween dumps to the backend. 136*1c60b9acSAndroid Build Coastguard Worker 137*1c60b9acSAndroid Build Coastguard WorkerThere are two approaches: 138*1c60b9acSAndroid Build Coastguard Worker 139*1c60b9acSAndroid Build Coastguard Worker - "aggregation": decimate keeping a uint64 mean + sum, along with a max and min 140*1c60b9acSAndroid Build Coastguard Worker 141*1c60b9acSAndroid Build Coastguard Worker - "histogram": keep a linked-list of different named buckets, with a 64-bit 142*1c60b9acSAndroid Build Coastguard Worker counter for the number of times an event in each bucket was observed 143*1c60b9acSAndroid Build Coastguard Worker 144*1c60b9acSAndroid Build Coastguard WorkerA single metric aggregation object has separate "go / no-go" counters, since 145*1c60b9acSAndroid Build Coastguard Workermost operations can fail, and failing operations act differently. 146*1c60b9acSAndroid Build Coastguard Worker 147*1c60b9acSAndroid Build Coastguard Worker`lws_metrics` 'aggregation' supports decimation by 148*1c60b9acSAndroid Build Coastguard Worker 149*1c60b9acSAndroid Build Coastguard Worker - a mean of a 64-bit event metric, separate for go and no-go events 150*1c60b9acSAndroid Build Coastguard Worker - counters of go and no-go events 151*1c60b9acSAndroid Build Coastguard Worker - a min and max of the metric 152*1c60b9acSAndroid Build Coastguard Worker - keeping track of when the sample period started 153*1c60b9acSAndroid Build Coastguard Worker 154*1c60b9acSAndroid Build Coastguard Worker 155*1c60b9acSAndroid Build Coastguard Worker 156*1c60b9acSAndroid Build Coastguard WorkerIn addition, the policy defines a percentage variance from the mean that 157*1c60b9acSAndroid Build Coastguard Workeroptionally qualifies events to be reported individually. 158*1c60b9acSAndroid Build Coastguard Worker 159*1c60b9acSAndroid Build Coastguard WorkerThe `lws_metrics` 'histogram' allows monitoring of different outcomes to 160*1c60b9acSAndroid Build Coastguard Workerproduce counts of each outcome in the "bucket". 161*1c60b9acSAndroid Build Coastguard Worker 162*1c60b9acSAndroid Build Coastguard Worker### `lws_metrics` flags 163*1c60b9acSAndroid Build Coastguard Worker 164*1c60b9acSAndroid Build Coastguard WorkerWhen the metrics object is created, flags are used to control how it will be 165*1c60b9acSAndroid Build Coastguard Workerused and consumed. 166*1c60b9acSAndroid Build Coastguard Worker 167*1c60b9acSAndroid Build Coastguard WorkerFor example to create a histogram metrics object rather than the default 168*1c60b9acSAndroid Build Coastguard Workeraggregation type, you would give the flag `LWSMTFL_REPORT_HIST` at creation 169*1c60b9acSAndroid Build Coastguard Workertime. 170*1c60b9acSAndroid Build Coastguard Worker 171*1c60b9acSAndroid Build Coastguard Worker|Flag|Meaning| 172*1c60b9acSAndroid Build Coastguard Worker|---|---| 173*1c60b9acSAndroid Build Coastguard Worker|`LWSMTFL_REPORT_OUTLIERS`|track outliers and report them internally| 174*1c60b9acSAndroid Build Coastguard Worker|`LWSMTFL_REPORT_OUTLIERS_OOB`|report each outlier externally as they happen| 175*1c60b9acSAndroid Build Coastguard Worker|`LWSMTFL_REPORT_INACTIVITY_AT_PERIODIC`|explicitly externally report no activity at periodic cb, by default no events in the period is just not reported| 176*1c60b9acSAndroid Build Coastguard Worker|`LWSMTFL_REPORT_MEAN`|the mean is interesting for this metric| 177*1c60b9acSAndroid Build Coastguard Worker|`LWSMTFL_REPORT_ONLY_GO`|no-go pieces invalid and should be ignored, used for simple counters| 178*1c60b9acSAndroid Build Coastguard Worker|`LWSMTFL_REPORT_DUTY_WALLCLOCK_US`|the aggregated sum or mean can be compared to wallclock time| 179*1c60b9acSAndroid Build Coastguard Worker|`LWSMTFL_REPORT_HIST`|object is a histogram (else aggregator)| 180*1c60b9acSAndroid Build Coastguard Worker 181*1c60b9acSAndroid Build Coastguard Worker### Built-in lws-layer metrics 182*1c60b9acSAndroid Build Coastguard Worker 183*1c60b9acSAndroid Build Coastguard Workerlws creates and maintains various well-known metrics when you enable build 184*1c60b9acSAndroid Build Coastguard Workerwith cmake `-DLWS_WITH_SYS_METRICS=1`: 185*1c60b9acSAndroid Build Coastguard Worker 186*1c60b9acSAndroid Build Coastguard Worker#### Aggregation metrics 187*1c60b9acSAndroid Build Coastguard Worker|metric name|scope|type|meaning| 188*1c60b9acSAndroid Build Coastguard Worker---|---|---|---| 189*1c60b9acSAndroid Build Coastguard Worker`cpu.svc`|context|monotonic over time|time spent servicing, outside of event loop wait| 190*1c60b9acSAndroid Build Coastguard Worker`n.cn.dns`|context|go/no-go mean|duration of blocking libc DNS lookup| 191*1c60b9acSAndroid Build Coastguard Worker`n.cn.adns`|context|go/no-go mean|duration of SYS_ASYNC_DNS lws DNS lookup| 192*1c60b9acSAndroid Build Coastguard Worker`n.cn.tcp`|context|go/no-go mean|duration of tcp connection until accept| 193*1c60b9acSAndroid Build Coastguard Worker`n.cn.tls`|context|go/no-go mean|duration of tls connection until accept| 194*1c60b9acSAndroid Build Coastguard Worker`n.http.txn`|context|go (2xx)/no-go mean|duration of lws http transaction| 195*1c60b9acSAndroid Build Coastguard Worker`n.ss.conn`|context|go/no-go mean|duration of Secure Stream transaction| 196*1c60b9acSAndroid Build Coastguard Worker`n.ss.cliprox.conn`|context|go/no-go mean|time taken for client -> proxy connection| 197*1c60b9acSAndroid Build Coastguard Worker`vh.[vh-name].rx`|vhost|go/no-go sum|received data on the vhost| 198*1c60b9acSAndroid Build Coastguard Worker`vh.[vh-name].tx`|vhost|go/no-go sum|transmitted data on the vhost| 199*1c60b9acSAndroid Build Coastguard Worker 200*1c60b9acSAndroid Build Coastguard Worker#### Histogram metrics 201*1c60b9acSAndroid Build Coastguard Worker|metric name|scope|type|meaning| 202*1c60b9acSAndroid Build Coastguard Worker|---|---|---|---| 203*1c60b9acSAndroid Build Coastguard Worker`n.cn.failures`|context|histogram|Histogram of connection attempt failure reasons| 204*1c60b9acSAndroid Build Coastguard Worker 205*1c60b9acSAndroid Build Coastguard Worker#### Connection failure histogram buckets 206*1c60b9acSAndroid Build Coastguard Worker|Bucket name|Meaning| 207*1c60b9acSAndroid Build Coastguard Worker|---|---| 208*1c60b9acSAndroid Build Coastguard Worker`tls/invalidca`|Peer certificate CA signature missing or not trusted| 209*1c60b9acSAndroid Build Coastguard Worker`tls/hostname`|Peer certificate CN or SAN doesn't match the endpoint we asked for| 210*1c60b9acSAndroid Build Coastguard Worker`tls/notyetvalid`|Peer certificate start date is in the future (time wrong?)| 211*1c60b9acSAndroid Build Coastguard Worker`tls/expired`|Peer certificate is expiry date is in the past| 212*1c60b9acSAndroid Build Coastguard Worker`dns/badsrv`|No DNS result because couldn't talk to the server| 213*1c60b9acSAndroid Build Coastguard Worker`dns/nxdomain`|No DNS result because server says no result| 214*1c60b9acSAndroid Build Coastguard Worker 215*1c60b9acSAndroid Build Coastguard WorkerThe `lws-minimal-secure-streams` example is able to report the aggregated 216*1c60b9acSAndroid Build Coastguard Workermetrics at the end of execution, eg 217*1c60b9acSAndroid Build Coastguard Worker 218*1c60b9acSAndroid Build Coastguard Worker``` 219*1c60b9acSAndroid Build Coastguard Worker[2021/01/13 11:47:19:9145] U: my_metric_report: cpu.svc: 137.045ms / 884.563ms (15%) 220*1c60b9acSAndroid Build Coastguard Worker[2021/01/13 11:47:19:9145] U: my_metric_report: n.cn.dns: Go: 4, mean: 3.792ms, min: 2.470ms, max: 5.426ms 221*1c60b9acSAndroid Build Coastguard Worker[2021/01/13 11:47:19:9145] U: my_metric_report: n.cn.tcp: Go: 4, mean: 40.633ms, min: 17.107ms, max: 94.560ms 222*1c60b9acSAndroid Build Coastguard Worker[2021/01/13 11:47:19:9145] U: my_metric_report: n.cn.tls: Go: 3, mean: 91.232ms, min: 30.322ms, max: 204.635ms 223*1c60b9acSAndroid Build Coastguard Worker[2021/01/13 11:47:19:9145] U: my_metric_report: n.http.txn: Go: 4, mean: 63.089ms, min: 20.184ms, max: 125.474ms 224*1c60b9acSAndroid Build Coastguard Worker[2021/01/13 11:47:19:9145] U: my_metric_report: n.ss.conn: Go: 4, mean: 161.740ms, min: 42.937ms, max: 429.510ms 225*1c60b9acSAndroid Build Coastguard Worker[2021/01/13 11:47:19:9145] U: my_metric_report: vh._ss_default.rx: Go: (1) 102, NoGo: (1) 0 226*1c60b9acSAndroid Build Coastguard Worker[2021/01/13 11:47:19:9145] U: my_metric_report: vh.le_via_dst.rx: Go: (22) 28.165Ki 227*1c60b9acSAndroid Build Coastguard Worker[2021/01/13 11:47:19:9145] U: my_metric_report: vh.le_via_dst.tx: Go: (1) 267 228*1c60b9acSAndroid Build Coastguard Worker[2021/01/13 11:47:19:9145] U: my_metric_report: vh.api_amazon_com.rx: Go: (1) 1.611Ki, NoGo: (1) 0 229*1c60b9acSAndroid Build Coastguard Worker[2021/01/13 11:47:19:9145] U: my_metric_report: vh.api_amazon_com.tx: Go: (3) 1.505Ki 230*1c60b9acSAndroid Build Coastguard Worker``` 231*1c60b9acSAndroid Build Coastguard Worker 232*1c60b9acSAndroid Build Coastguard Workerlws-minimal-secure-stream-testsfail which tests various kinds of connection failure 233*1c60b9acSAndroid Build Coastguard Workerreports histogram results like this 234*1c60b9acSAndroid Build Coastguard Worker 235*1c60b9acSAndroid Build Coastguard Worker``` 236*1c60b9acSAndroid Build Coastguard Worker[2021/01/15 13:10:16:0933] U: my_metric_report: n.cn.failures: tot: 36, [ tls/invalidca: 5, tls/expired: 5, tls/hostname: 5, dns/nxdomain: 21 ] 237*1c60b9acSAndroid Build Coastguard Worker``` 238*1c60b9acSAndroid Build Coastguard Worker 239*1c60b9acSAndroid Build Coastguard Worker## Support for openmetrics 240*1c60b9acSAndroid Build Coastguard Worker 241*1c60b9acSAndroid Build Coastguard WorkerOpenmetrics https://tools.ietf.org/html/draft-richih-opsawg-openmetrics-00 242*1c60b9acSAndroid Build Coastguard Workerdefines a textual metrics export format comaptible with Prometheus. Lws 243*1c60b9acSAndroid Build Coastguard Workerprovides a protocol plugin in `./plugins/protocol_lws_openmetrics_export` 244*1c60b9acSAndroid Build Coastguard Workerthat enables direct export for prometheus scraping, and also protocols to 245*1c60b9acSAndroid Build Coastguard Workerproxy openmetrics export for unreachable servers. 246