mirror of
https://github.com/nostr-protocol/nips.git
synced 2024-12-23 00:45:53 -05:00
reorganize kinds to be more intuitive
This commit is contained in:
parent
b8b07a2659
commit
26ef08c90b
196
66.md
196
66.md
|
@ -1,89 +1,32 @@
|
||||||
# NIP-66: Relay Monitoring System
|
# NIP-66: Relay Meta and Monitoring System
|
||||||
|
|
||||||
`draft` `optional`
|
`draft` `optional`
|
||||||
|
|
||||||
This NIP defines four event kinds, `10066`, `30066`, `10166` and `1066`.
|
This NIP defines four event kinds, `10066`, `30066`, `10166` and `1066`.
|
||||||
|
|
||||||
## `10066`: "Relay Monitor" Events
|
|
||||||
|
## `10066`: "Self-Reported Relay Meta"
|
||||||
|
|
||||||
### Summary
|
### Summary
|
||||||
`10066` is a replacable event herein referred to as "Relay Monitor" events. These events contain information about a publisher's intent to monitor and/or aggregate relays and publish data as `30066` events.
|
An event that contains data about a relay. These events are self-reported by relays from the `owner` pubkey defined in their Information Document (`NIP-11`). Hereinafter referred to as "Relay Meta" events
|
||||||
|
|
||||||
### Purpose
|
### Purpose
|
||||||
To provide a directory of monitors, their intent to publish, their criteria and parameters of monitoring activities.
|
An event that makes relays discoverable.
|
||||||
|
|
||||||
### Schema
|
## Schema
|
||||||
`10066` events have no required tags.
|
|
||||||
|
|
||||||
- `"url" == tagUrl[0]` A URL with human readable information about the monitor's activities. If not included, it is assumed these details are included in the monitor's kind 0 for the pubkey that signed the `10066` event.
|
|
||||||
|
|
||||||
- `"timeout" == tagTimeout[0]` The timeout values for various tests. `tagTimeout[1]` is the monitor's timeout in milliseconds. `tagTimeout[2]` describes what test the timeout is used for, for example `open`, `read`, `write`, `info`, etc. If no `tagTimeout[2]` is provided, it is inferred that the timeout provided applies to all tests.
|
|
||||||
```
|
|
||||||
[ "timeout", "2000", "open" ]
|
|
||||||
[ "timeout", "2000", "read" ]
|
|
||||||
[ "timeout", "3000", "write" ]
|
|
||||||
[ "timeout", "2000", "info" ]
|
|
||||||
```
|
|
||||||
|
|
||||||
- `"kind === tagKind[0]"` The kind(s) this monitor publishes.
|
|
||||||
```
|
|
||||||
[ "kind", "30066" ]
|
|
||||||
[ "kind", "1066" ]
|
|
||||||
```
|
|
||||||
|
|
||||||
- `"frequency" == tagFrequency[0]` The frequency at which the monitor publishes events. A string-integer at `tagFrequency[1]` represents the frequency a event kind is published. The string-integer at `tagFrequency[2]` represents the kind bound to the frequency. If `tagFrequency[2]` is undefined, it is inferred the timeout applies to all events published by the monitor. A frequency **should not** be created for this kind [`1006`]. If a kind is referenced in `tagFrequency` that is not set in `tagKind` it should be disregarded.
|
|
||||||
```
|
|
||||||
[ "frequency", "3600", "30066" ]
|
|
||||||
[ "frequency", "3600", "1066" ]
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Label Tags <sup>NIP-32</sup>
|
|
||||||
|
|
||||||
- `checks` **should** be a lowercase string describing the check(s) conducted by a monitor. Some examples are: `websocket`, `nip11`, `ssl`, `dns`, `geo`
|
|
||||||
|
|
||||||
```
|
|
||||||
[ "L", "checks" ]
|
|
||||||
[ "l", "websocket", "checks" ]
|
|
||||||
[ "l", "nip11", "checks" ]
|
|
||||||
[ "l", "ssl", "checks" ]
|
|
||||||
[ "l", "dns", "checks" ]
|
|
||||||
[ "l", "geo", "checks" ]
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Geo tags <sup>NIP-YAGT</sup>
|
|
||||||
- `NIP-66` leverages a draft NIP for geo tags, see [YAGT](https://github.com/nostr-protocol/nips/pull/952)
|
|
||||||
|
|
||||||
### Other Requirements
|
|
||||||
- Monitors **should** have a published `10002` event that defines the relays the monitor publishes to.
|
|
||||||
|
|
||||||
## `30066`: "Relay Status" Events
|
|
||||||
|
|
||||||
### Summary
|
|
||||||
`30066` is a parameterized replaceable event [NIP-33], referred to as a "Relay" event. These events store the existence and optionally some data relating to the relay.
|
|
||||||
|
|
||||||
### Purpose
|
|
||||||
To store useful, computationally expensive relay meta-data about relays. `30066` should be used to give a canonical reference to the last known functional state of a relay, to be evaluated subjectively by a client and/or user to derive conclusions from.
|
|
||||||
|
|
||||||
### NIPs Used
|
|
||||||
- `NIP-32` Labels
|
|
||||||
- `NIP-33` Parameterized Replacable Events
|
|
||||||
- `NIP-40` Expirable Events
|
|
||||||
- [YAGT](https://github.com/nostr-protocol/nips/pull/952) _draft_
|
|
||||||
|
|
||||||
### Schema
|
|
||||||
|
|
||||||
#### `event.content`
|
#### `event.content`
|
||||||
**Should** be empty.
|
**Should** be empty.
|
||||||
|
|
||||||
#### `event.tags`
|
#### `event.tags`
|
||||||
Relay status events have **one** (1) required tag.
|
"Relay Meta" events have **one** (1) required tag.
|
||||||
|
|
||||||
Relay status events have **two** (2) non-standard, NIP-66 specific indexable tags.
|
"Relay Meta" events have **two** (2) non-standard, NIP-66 specific indexable tags.
|
||||||
|
|
||||||
Tags should be used to represent the Relay's abilities and meta at any given point in time. The "tags schema" is expressed using pseudo-types for reasons of communication and brevity, for example `tagDescriptor[]`. This NIP utilizes `NIP-32` to expose indexable values.
|
Tags should be used to represent the Relay's abilities and meta at any given point in time. The "tags schema" is expressed using pseudo-types for reasons of communication and brevity, for example `tagDescriptor[]`. This NIP utilizes `NIP-32` to expose indexable values.
|
||||||
|
|
||||||
#### Tags
|
#### Tags
|
||||||
- `"d" == tagId[0]` The relay URL. The `#d` tag **must** be included in the `event.tags[]` array. `tagId[1]` **must** be the relay websocket URL. The URL **should** be [normalized](https://datatracker.ietf.org/doc/html/rfc3986#section-6)
|
- `"r" == tagId[0]` The relay URL. The `#d` tag **must** be included in the `event.tags[]` array. `tagId[1]` **must** be the relay websocket URL. The URL **should** be [normalized](https://datatracker.ietf.org/doc/html/rfc3986#section-6)
|
||||||
```
|
```
|
||||||
["d", "wss://history.nostr.watch/"] //tagId[]
|
["d", "wss://history.nostr.watch/"] //tagId[]
|
||||||
```
|
```
|
||||||
|
@ -93,6 +36,11 @@ Tags should be used to represent the Relay's abilities and meta at any given poi
|
||||||
[ "n", "clearnet" ]
|
[ "n", "clearnet" ]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- `desc == tagDesc[0]` The description from nip11.
|
||||||
|
```
|
||||||
|
[ "desc", "A nostr relay" ]
|
||||||
|
```
|
||||||
|
|
||||||
- `N`: Supported NIPs _in the context of **NIP-66 only**_
|
- `N`: Supported NIPs _in the context of **NIP-66 only**_
|
||||||
```
|
```
|
||||||
[ "N", "1" ]
|
[ "N", "1" ]
|
||||||
|
@ -100,12 +48,6 @@ Tags should be used to represent the Relay's abilities and meta at any given poi
|
||||||
[ "N", "33" ]
|
[ "N", "33" ]
|
||||||
```
|
```
|
||||||
|
|
||||||
- `"rtt" == tagRtt[0]` Round-trip time of websocket ping/pong in milliseconds. Example values for `tagRtt[1]` are `open`, `read` and `write`. Where `open` represents the round-trip time forWebsocket to open, `read` represents the round-trip time of a Websocket `REQ` (subscription) message's response, and `write` represents the round-trip time of a Websocket `EVENT` (publish) message and subsequent `ok` message. `tagRtt[2...]` are strings with the millisecond values. At a minimum `tagRtt[2]` **should** be set. When more than one value is provided, values **may** be treated as an array to find `min`, `max`, `average` and `median` values. There **may** be zero `rtt` tags.
|
|
||||||
```
|
|
||||||
["rtt", "open", "201", "190", "540"],
|
|
||||||
["rtt", "read", "35", "60", "46"],
|
|
||||||
["rtt", "write", "701", "497", "508"]
|
|
||||||
```
|
|
||||||
- `"count" == tagCount[0]` Meta values for arbitrary counts related to a relay. `tagCount[1]` is the value expressed as the string representation of an integer or float. `tagCount[2]` is the key and describes the count, such as `total_users` or `total_events`. Counts **should** only be included when representing unique or computationally expensive counts, not ones that can be easily achieved via `NIP-45` counts. There **may** be zero (0) to many count tags.
|
- `"count" == tagCount[0]` Meta values for arbitrary counts related to a relay. `tagCount[1]` is the value expressed as the string representation of an integer or float. `tagCount[2]` is the key and describes the count, such as `total_users` or `total_events`. Counts **should** only be included when representing unique or computationally expensive counts, not ones that can be easily achieved via `NIP-45` counts. There **may** be zero (0) to many count tags.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -120,10 +62,6 @@ Tags should be used to represent the Relay's abilities and meta at any given poi
|
||||||
[ "infohash", "fj89as0n3inmcd89nefkdlsky2mfkdlsfds" ]
|
[ "infohash", "fj89as0n3inmcd89nefkdlsky2mfkdlsfds" ]
|
||||||
```
|
```
|
||||||
|
|
||||||
- `"e" === tagE[0]` An association to another standard nostr event (`0/1/2/4-9999` kind-range). An example would be an event containing the most recent check log or an archival event representing the check. Such a reference may contain duplicate or ommitted tags from a `30066` event.
|
|
||||||
|
|
||||||
- `"a" === tagE[0]` An association to another replaceable nostr event. An example would be an event containing the most recent check log or an archival event representing the check. Such a reference may contain duplicate or ommitted tags from a `30066` event.
|
|
||||||
|
|
||||||
#### Label Tags <sup>NIP-32</sup>
|
#### Label Tags <sup>NIP-32</sup>
|
||||||
- `relay_type`, for example `proxy`, `bridge` and `public` for example. There **may** be more than one type. There have not been efforts to atomize relay types at the time of writing this NIPs, so these values cannot be enumerated at this time.
|
- `relay_type`, for example `proxy`, `bridge` and `public` for example. There **may** be more than one type. There have not been efforts to atomize relay types at the time of writing this NIPs, so these values cannot be enumerated at this time.
|
||||||
```
|
```
|
||||||
|
@ -156,7 +94,6 @@ Tags should be used to represent the Relay's abilities and meta at any given poi
|
||||||
[ "L", "nip11.language_tags" ]
|
[ "L", "nip11.language_tags" ]
|
||||||
[ "l", "en", "nip11.language_tags" ]
|
[ "l", "en", "nip11.language_tags" ]
|
||||||
[ "l", "en-419", "nip11.language_tags" ]
|
[ "l", "en-419", "nip11.language_tags" ]
|
||||||
[ "L", "nip11.limitations" ]
|
|
||||||
```
|
```
|
||||||
|
|
||||||
- Boolean values from `NIP-11`, for example
|
- Boolean values from `NIP-11`, for example
|
||||||
|
@ -194,12 +131,48 @@ Tags should be used to represent the Relay's abilities and meta at any given poi
|
||||||
["t", "meme", "69", "3600"]
|
["t", "meme", "69", "3600"]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## `30066`: "Relay Status" Events
|
||||||
|
|
||||||
|
### Summary
|
||||||
|
`30066` is a parameterized replaceable event [NIP-33], referred to as a "Relay Status" event. These events store the existence and optionally some data relating to the relay.
|
||||||
|
|
||||||
|
### Purpose
|
||||||
|
To store useful, computationally expensive relay meta-data about relays. `30066` should be used to give a canonical reference to the last known functional state of a relay, to be evaluated subjectively by a client and/or user to derive conclusions from.
|
||||||
|
|
||||||
|
### NIPs Used
|
||||||
|
- `NIP-32` Labels
|
||||||
|
- `NIP-33` Parameterized Replacable Events
|
||||||
|
- `NIP-40` Expirable Events
|
||||||
|
- [YAGT](https://github.com/nostr-protocol/nips/pull/952) _draft_
|
||||||
|
|
||||||
|
### Schema
|
||||||
|
`30066` events are almost identical to `10066` except a few key differences.
|
||||||
|
|
||||||
|
_**Different referencial tag**_
|
||||||
|
|
||||||
|
- `30066` uses a `d` tag instead of an `r` tag for the normalized relay URL since it is a Parameterized-Replaceable Event
|
||||||
|
|
||||||
|
_**It adds some additional tags**_
|
||||||
|
|
||||||
|
- `"rtt" == tagRtt[0]` Round-trip time of websocket ping/pong in milliseconds. Example values for `tagRtt[1]` are `open`, `read` and `write`. Where `open` represents the round-trip time forWebsocket to open, `read` represents the round-trip time of a Websocket `REQ` (subscription) message's response, and `write` represents the round-trip time of a Websocket `EVENT` (publish) message and subsequent `ok` message. `tagRtt[2...]` are strings with the millisecond values. At a minimum `tagRtt[2]` **should** be set. When more than one value is provided, values **may** be treated as an array to find `min`, `max`, `average` and `median` values. There **may** be zero `rtt` tags.
|
||||||
|
|
||||||
|
```
|
||||||
|
["rtt", "open", "201", "190", "540"],
|
||||||
|
["rtt", "read", "35", "60", "46"],
|
||||||
|
["rtt", "write", "701", "497", "508"]
|
||||||
|
```
|
||||||
|
|
||||||
|
- `"e" === tagE[0]` An association to another standard nostr event (`0/1/2/4-9999` kind-range). An example would be an event containing the most recent check log or an archival event representing the check. Such a reference may contain duplicate or ommitted tags from a `30066` event.
|
||||||
|
|
||||||
|
- `"a" === tagE[0]` An association to another replaceable nostr event. An example would be an event containing the most recent check log or an archival event representing the check. Such a reference may contain duplicate or ommitted tags from a `30066` event.
|
||||||
|
|
||||||
|
|
||||||
#### Methodology
|
#### Methodology
|
||||||
A Checking Monitor publishes 30066 events exclusively when a relay is operational. This approach ensures that the last known active state of the relay is maintained and recorded. Based on this data, several inferences can be drawn about the relay's status and characteristics
|
A Relay Monitor publishes `30066`` events exclusively when a relay is operational. This approach ensures that the last known active state of the relay is maintained and recorded. Based on this data, several inferences can be drawn about the relay's status and characteristics
|
||||||
|
|
||||||
1. Clients and/or users can set a custom threshold to establish a cutoff timestamp for filtering events using `since`. This timestamp helps in identifying which relays are currently online. Selecting a lower threshold value results in a stricter criterion for relay uptime, making the filter more sensitive to brief downtimes. Conversely, choosing a higher threshold value creates a more lenient filter, allowing relays with longer downtimes to still be considered as online.
|
1. Clients and/or users can set a custom threshold to establish a cutoff timestamp for filtering events using `since`. This timestamp helps in identifying which relays are currently online. Selecting a lower threshold value results in a stricter criterion for relay uptime, making the filter more sensitive to brief downtimes. Conversely, choosing a higher threshold value creates a more lenient filter, allowing relays with longer downtimes to still be considered as online.
|
||||||
|
|
||||||
2. In determining whether a relay is 'dead,' the decision is solely at the discretion of the client or user. The are responsible for setting and applying arbitrary thresholds using `until` filters to make this determination. This approach underscores that the classification of a relay as 'dead' is a subjective decision, varying according to each client's or user's assessment criteria, rather than a fixed status provided by the monitor.
|
2. In determining whether a relay is 'dead,' the decision is solely at the discretion of the client or user. The are responsible for setting and applying arbitrary thresholds using `until` filters or post-processing to make this determination. This approach underscores that the classification of a relay as 'dead' is a subjective decision, varying according to each client's or user's assessment criteria, rather than a fixed status provided by the monitor.
|
||||||
|
|
||||||
3. For relay status events that have become outdated, the retained data points remain valuable. They offer insights and information about the relay's characteristics and performance, which might not be currently accessible due to the relay being offline.
|
3. For relay status events that have become outdated, the retained data points remain valuable. They offer insights and information about the relay's characteristics and performance, which might not be currently accessible due to the relay being offline.
|
||||||
|
|
||||||
|
@ -233,6 +206,8 @@ A Checking Monitor publishes 30066 events exclusively when a relay is operationa
|
||||||
"content": "{}",
|
"content": "{}",
|
||||||
"tags": [
|
"tags": [
|
||||||
["d","wss://some.relay/"],
|
["d","wss://some.relay/"],
|
||||||
|
["N", "1"],
|
||||||
|
["N", "7"],
|
||||||
["rtt", "open", "201", "190", "540"],
|
["rtt", "open", "201", "190", "540"],
|
||||||
["rtt", "read", "35", "60", "46"],
|
["rtt", "read", "35", "60", "46"],
|
||||||
["rtt", "write", "701", "497", "508"],
|
["rtt", "write", "701", "497", "508"],
|
||||||
|
@ -246,9 +221,7 @@ A Checking Monitor publishes 30066 events exclusively when a relay is operationa
|
||||||
["L", "ipv4"],
|
["L", "ipv4"],
|
||||||
["l", "1.1.1.1""ipv4" ],
|
["l", "1.1.1.1""ipv4" ],
|
||||||
["L", "ipv6"],
|
["L", "ipv6"],
|
||||||
["l", "2001:db8:3333:4444:5555:6666:7777:8888","ipv6"],
|
["l", "2001:db8:3333:4444:5555:6666:7777:8888", "ipv6"]
|
||||||
["t", "nip-1"],
|
|
||||||
["t", "nip-7"]
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -283,18 +256,67 @@ Any test results that cannot be expressed through `NIP-66` **should** be ammende
|
||||||
|
|
||||||
10. **Data-Driven Relay Selection**: Make informed choices about which relays to connect to, based on comprehensive metadata including user counts, event frequencies, network types and more.
|
10. **Data-Driven Relay Selection**: Make informed choices about which relays to connect to, based on comprehensive metadata including user counts, event frequencies, network types and more.
|
||||||
|
|
||||||
## `10166`: "Self-Reported Relay Statuses"
|
## `10166`: "Relay Monitor" Events
|
||||||
|
|
||||||
### Summary
|
### Summary
|
||||||
A `30066` event with an `r` tag instead of a `d` tag.
|
`10166` is a replacable event herein referred to as "Relay Monitor" events. These events contain information about a publisher's intent to monitor and/or aggregate relays and publish data as `30066` events.
|
||||||
|
|
||||||
### Purpose
|
### Purpose
|
||||||
For relays to self-report
|
To provide a directory of monitors, their intent to publish, their criteria and parameters of monitoring activities.
|
||||||
|
|
||||||
|
### Schema
|
||||||
|
`10166` events have no required tags.
|
||||||
|
|
||||||
|
- `"url" == tagUrl[0]` A URL with human readable information about the monitor's activities. If not included, it is assumed these details are included in the monitor's kind 0 for the pubkey that signed the `10066` event.
|
||||||
|
|
||||||
|
- `"timeout" == tagTimeout[0]` The timeout values for various tests. `tagTimeout[1]` is the monitor's timeout in milliseconds. `tagTimeout[2]` describes what test the timeout is used for, for example `open`, `read`, `write`, `info`, etc. If no `tagTimeout[2]` is provided, it is inferred that the timeout provided applies to all tests.
|
||||||
|
```
|
||||||
|
[ "timeout", "2000", "open" ]
|
||||||
|
[ "timeout", "2000", "read" ]
|
||||||
|
[ "timeout", "3000", "write" ]
|
||||||
|
[ "timeout", "2000", "info" ]
|
||||||
|
```
|
||||||
|
|
||||||
|
- `"ssl" == tagSsl[0]` SSL certificate check. `tag[1]` is either `valid` or `invalid`. `tag[2]` is the validate start date. `tag[3]` is the validity end date. Can include reference via `e` or `a` to raw SSL data for indepdent validation.
|
||||||
|
```
|
||||||
|
["ssl", "valid", "timestamp", "timestamp"],
|
||||||
|
```
|
||||||
|
|
||||||
|
- `"kind === tagKind[0]"` The kind(s) this monitor publishes.
|
||||||
|
```
|
||||||
|
[ "kind", "30066" ]
|
||||||
|
[ "kind", "1066" ]
|
||||||
|
```
|
||||||
|
|
||||||
|
- `"frequency" == tagFrequency[0]` The frequency at which the monitor publishes events. A string-integer at `tagFrequency[1]` represents the frequency a event kind is published. The string-integer at `tagFrequency[2]` represents the kind bound to the frequency. If `tagFrequency[2]` is undefined, it is inferred the timeout applies to all events published by the monitor. A frequency **should not** be created for this kind [`1006`]. If a kind is referenced in `tagFrequency` that is not set in `tagKind` it should be disregarded.
|
||||||
|
```
|
||||||
|
[ "frequency", "3600", "30066" ]
|
||||||
|
[ "frequency", "3600", "1066" ]
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Label Tags <sup>NIP-32</sup>
|
||||||
|
|
||||||
|
- `checks` **should** be a lowercase string describing the check(s) conducted by a monitor. Some examples are: `websocket`, `nip11`, `ssl`, `dns`, `geo`
|
||||||
|
|
||||||
|
```
|
||||||
|
[ "L", "checks" ]
|
||||||
|
[ "l", "websocket", "checks" ]
|
||||||
|
[ "l", "nip11", "checks" ]
|
||||||
|
[ "l", "ssl", "checks" ]
|
||||||
|
[ "l", "dns", "checks" ]
|
||||||
|
[ "l", "geo", "checks" ]
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Geo tags <sup>NIP-YAGT</sup>
|
||||||
|
- `NIP-66` leverages a draft NIP for geo tags, see [YAGT](https://github.com/nostr-protocol/nips/pull/952)
|
||||||
|
|
||||||
|
### Other Requirements
|
||||||
|
- Monitors **should** have a published `10002` event that defines the relays the monitor publishes to.
|
||||||
|
|
||||||
## `1066`: "Relay Status History" Events
|
## `1066`: "Relay Status History" Events
|
||||||
|
|
||||||
### Summary
|
### Summary
|
||||||
`1066` is a standard nostr event, referred to as a "Relay Status History" event. These events store the history of a relay at a periodic interval (defined in `10066`).
|
`1066` is a standard nostr event, referred to as a "Relay Status History" event. These events store the history of a relay at a periodic interval (defined in `10166`).
|
||||||
|
|
||||||
#### Schema
|
#### Schema
|
||||||
Relay History events can contain any of the tags defined for kind `30066` (Including the `d` tag which is used to filter these events by relay). There is one new indexable tag
|
Relay History events can contain any of the tags defined for kind `30066` (Including the `d` tag which is used to filter these events by relay). There is one new indexable tag
|
||||||
|
@ -306,5 +328,5 @@ Relay History events can contain any of the tags defined for kind `30066` (Inclu
|
||||||
Tags representing less-volatile values, for instance `nip11.software` vs `rtt`, contained with this event should only be included when their respectiive values have changed compared to the last Relay History event of the same `d` tag. If there have been no changes, then the event should not be published.
|
Tags representing less-volatile values, for instance `nip11.software` vs `rtt`, contained with this event should only be included when their respectiive values have changed compared to the last Relay History event of the same `d` tag. If there have been no changes, then the event should not be published.
|
||||||
|
|
||||||
##### Use Cases
|
##### Use Cases
|
||||||
- Generate a time series from one or many data-point(s) for a specific relay.
|
- Generate a time series from one or data-point(s) for a specific relay.
|
||||||
- Generate network-wide aggregated statistics
|
- Generate network-wide aggregated statistics
|
Loading…
Reference in New Issue
Block a user