[metrics] Introduce metrics API (#39202)
See the [design
doc](https://github.com/systemd/systemd/issues/38023#issue-
3192567450)
by @ikruglov
This PR introduces the metrics API framework, adds some basic system
wide/per unit/service metrics, and a basic CLI. The PR is broken into
two commits as described below.
### Deviations from the original design
- Introduced top level field "object" for ease of filtering. Instead of
having `fields: { unit: "foo", unit_type: "service" }`, we now have
`object: foo.service` as the top level field.
### First commit
The first commit includes:
- Metrics API definitions
- Code to set up the varlink server
- The describe method which shows all the metrics families
- The list method which lists all the metrics
- Type definitions related to MetricFamily
- Common code to build json objects
### Second commit
The second commit adds some basic metrics, a basic CLI (systemd-report)
which
lists the metrics, and integration tests.
**System wide metrics:**
- units_by_type_total
- units_by_state_total
**Two per unit metrics:**
- unit_active_state
- unit_load_state
**A service state metric:**
- nrestarts
### Sample outputs
**units_by_type_total**:
```
{
"name" : "io.systemd.Manager.units_by_type_total",
"value" : 52,
"fields" : {
"type" : "target"
}
}
{
"name" : "io.systemd.Manager.units_by_type_total",
"value" : 82,
"fields" : {
"type" : "device"
}
}
{
"name" : "io.systemd.Manager.units_by_type_total",
"value" : 2,
"fields" : {
"type" : "automount"
}
}
```
**units_by_state_total**:
```
{
"name" : "io.systemd.Manager.units_by_state_total",
"value" : 216,
"fields" : {
"state" : "active"
}
}
{
"name" : "io.systemd.Manager.units_by_state_total",
"value" : 0,
"fields" : {
"state" : "reloading"
}
}
{
"name" : "io.systemd.Manager.units_by_state_total",
"value" : 120,
"fields" : {
"state" : "inactive"
}
}
```
**unit_active_state**:
```
{
"name" : "io.systemd.Manager.unit_active_state",
"object" : "multi-user.target",
"value" : "active"
}
{
"name" : "io.systemd.Manager.unit_active_state",
"object" : "systemd-sysusers.service",
"value" : "inactive"
}
```
**unit_load_state**:
```
{
"name" : "io.systemd.Manager.unit_load_state",
"object" : "multi-user.target",
"value" : "loaded"
}
```
**nrestarts**:
```
{
"name" : "io.systemd.Manager.nrestarts",
"object" : "user@0.service",
"value" : 0
}
{
"name" : "io.systemd.Manager.nrestarts",
"object" : "user-runtime-dir@0.service",
"value" : 0
}
```