Skip to content
67 changes: 67 additions & 0 deletions docs/spectator/lang/cpp/meters/age-gauge.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
The value is the time in seconds since the epoch at which an event has successfully occurred, or
`0` to use the current time in epoch seconds. After an Age Gauge has been set, it will continue
reporting the number of seconds since the last time recorded, for as long as the SpectatorD
process runs. The purpose of this metric type is to enable users to more easily implement the
Time Since Last Success alerting pattern.

To set a specific time as the last success:

```cpp
#include <registry.h>

int main()
{
auto config = Config(WriterConfig(WriterTypes::UDP));
auto r = Registry(config);

// Option 1: Directly create an Age Gauge
auto successAgeGauge = r.CreateAgeGauge("time.sinceLastSuccess");
successAgeGauge.Set(1611081000);

// Option 2: Create an Age Gauge from a MeterID
auto successMeter = r.CreateNewId("time.sinceLastSuccess");
r.CreateAgeGauge(successMeter).Set(1611081000);
}
```

To set `Now()` as the last success:

```cpp
#include <registry.h>

int main()
{
auto config = Config(WriterConfig(WriterTypes::UDP));
auto r = Registry(config);

// Option 1: Directly create an Age Gauge
auto successAgeGauge = r.CreateAgeGauge("time.sinceLastSuccess");
successAgeGauge.Now();

// Option 2: Create an Age Gauge from a MeterID
auto successMeter = r.CreateNewId("time.sinceLastSuccess");
r.CreateAgeGauge(successMeter).Now();
}
```

By default, a maximum of `1000` Age Gauges are allowed per `spectatord` process, because there is no
mechanism for cleaning them up. This value may be tuned with the `--age_gauge_limit` flag on the
`spectatord` binary.

Since Age Gauges are long-lived entities that reside in the memory of the SpectatorD process, if
you need to delete and re-create them for any reason, then you can use the [SpectatorD admin server]
to accomplish this task. You can delete all Age Gauges or a single Age Gauge.

**Example:**

```
curl -X DELETE \
http://localhost:1234/metrics/A
```

```
curl -X DELETE \
http://localhost:1234/metrics/A/fooIsTheName,some.tag=val1,some.otherTag=val2
```

[SpectatorD admin server]: ../../../agent/usage.md#admin-server
46 changes: 46 additions & 0 deletions docs/spectator/lang/cpp/meters/counter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
A Counter is used to measure the rate at which an event is occurring. Considering an API endpoint,
a Counter could be used to measure the rate at which it is being accessed.

Counters are reported to the backend as a rate-per-second. In Atlas, the `:per-step` operator can
be used to convert them back into a value-per-step on a graph.

Call `Increment()` when an event occurs:

```cpp
#include <registry.h>

int main()
{
auto config = Config(WriterConfig(WriterTypes::UDP));
auto r = Registry(config);

// Option 1: Directly create a Counter
auto serverRequestCounter = r.CreateCounter("server.numRequests");
serverRequestCounter.Increment();

// Option 2: Create a Counter from a MeterID
auto serverRequestMeter = r.CreateNewId("server.numRequests");
r.CreateCounter(serverRequestMeter).Increment();
}
```

You can also pass a value to `Increment()`. This is useful when a collection of events happens
together:

```cpp
#include <registry.h>

int main()
{
auto config = Config(WriterConfig(WriterTypes::UDP));
auto r = Registry(config);

// Option 1: Directly create a Counter
auto serverRequestCounter = r.CreateCounter("server.numRequests");
serverRequestCounter.Increment(10);

// Option 2: Create a Counter from a MeterID
auto serverRequestMeter = r.CreateNewId("server.numRequests");
r.CreateCounter(serverRequestMeter).Increment(10);
}
```
29 changes: 29 additions & 0 deletions docs/spectator/lang/cpp/meters/dist-summary.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
A Distribution Summary is used to track the distribution of events. It is similar to a Timer, but
more general, in that the size does not have to be a period of time. For example, a Distribution
Summary could be used to measure the payload sizes of requests hitting a server. Note that the C++
implementation of Distribution Summary allows for the recording of floating point values, which the
other thin clients do not allow.

Always use base units when recording data, to ensure that the tick labels presented on Atlas graphs
are readable. If you are measuring payload size, then use bytes, not kilobytes (or some other unit).
This means that a `4K` tick label will represent 4 kilobytes, rather than 4 kilo-kilobytes.

Call `Record()` with a value:

```cpp
#include <registry.h>

int main()
{
auto config = Config(WriterConfig(WriterTypes::UDP));
auto r = Registry(config);

// Option 1: Directly create a Distribution Summary
auto serverRequestSize = r.CreateDistributionSummary("server.requestSize");
serverRequestSize.Record(42);

// Option 2: Create a Distribution Summary from a MeterID
auto serverRequestMeter = r.CreateNewId("server.requestSize");
r.CreateDistributionSummary(serverRequestMeter).Record(42);
}
```
49 changes: 49 additions & 0 deletions docs/spectator/lang/cpp/meters/gauge.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
A gauge is a value that is sampled at some point in time. Typical examples for gauges would be
the size of a queue or number of threads in a running state. Since gauges are not updated inline
when a state change occurs, there is no information about what might have occurred between samples.

Consider monitoring the behavior of a queue of tasks. If the data is being collected once a minute,
then a gauge for the size will show the size when it was sampled. The size may have been much
higher or lower at some point during interval, but that is not known.

Call `Set()` with a value:

```cpp
#include <registry.h>

int main()
{
auto config = Config(WriterConfig(WriterTypes::UDP));
auto r = Registry(config);

// Option 1: Directly create a Gauge
auto serverQueueSize = r.CreateGauge("server.queueSize");
serverQueueSize.Set(10);

// Option 2: Create a Gauge from a MeterID
auto serverQueueMeter = r.CreateNewId("server.queueSize");
r.CreateGauge(serverQueueMeter).Set(10);
}
```

Gauges will report the last set value for 15 minutes. This done so that updates to the values do
not need to be collected on a tight 1-minute schedule to ensure that Atlas shows unbroken lines in
graphs. A custom TTL may be configured for gauges. SpectatorD enforces a minimum TTL of 5 seconds.

```cpp
#include <registry.h>

int main()
{
auto config = Config(WriterConfig(WriterTypes::UDP));
auto r = Registry(config);

// Option 1: Directly create a Gauge
auto serverQueueSize = r.CreateGauge("server.queueSize", {}, 120);
serverQueueSize.Set(10);

// Option 2: Create a Gauge from a MeterID
auto serverQueueMeter = r.CreateNewId("server.queueSize");
r.CreateGauge(serverQueueMeter, 120).Set(10);
}
```
24 changes: 24 additions & 0 deletions docs/spectator/lang/cpp/meters/max-gauge.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
The value is a number that is sampled at a point in time, but it is reported as a maximum Gauge
value to the backend. This ensures that only the maximum value observed during a reporting interval
is sent to the backend, thus over-riding the last-write-wins semantics of standard Gauges. Unlike
standard Gauges, Max Gauges do not continue to report to the backend, and there is no TTL.

Call `Set()` with a value:

```cpp
#include <registry.h>

int main()
{
auto config = Config(WriterConfig(WriterTypes::UDP));
auto r = Registry(config);

// Option 1: Directly create a Max Gauge
auto serverQueueSize = r.CreateMaxGauge("server.queueSize");
serverQueueSize.Set(10);

// Option 2: Create a Gauge from a MeterID
auto serverQueueMeter = r.CreateNewId("server.queueSize");
r.CreateMaxGauge(serverQueueMeter).Set(10);
}
```
25 changes: 25 additions & 0 deletions docs/spectator/lang/cpp/meters/monotonic-counter-uint.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
A Monotonic Counter (uint64) is used to measure the rate at which an event is occurring, when the
source data is a monotonically increasing number. A minimum of two samples must be sent, in order to
calculate a delta value and report it to the backend as a rate-per-second. A variety of networking
metrics may be reported monotonically, and this metric type provides a convenient means of recording
these values, at the expense of a slower time-to-first metric.

Call `Set()` when an event occurs:

```cpp
#include <registry.h>

int main()
{
auto config = Config(WriterConfig(WriterTypes::UDP));
auto r = Registry(config);

// Option 1: Directly create a Monotonic Counter uint64_t
auto interfaceBytes = r.CreateMonotonicCounterUint("iface.bytes");
interfaceBytes.Set(10);

// Option 2: Create a Monotonic Counter uint64_t from a MeterID
auto interfaceBytesMeter = r.CreateNewId("iface.bytes");
r.CreateMonotonicCounterUint(interfaceBytesMeter).Set(10);
}
```
25 changes: 25 additions & 0 deletions docs/spectator/lang/cpp/meters/monotonic-counter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
A Monotonic Counter (float) is used to measure the rate at which an event is occurring, when the
source data is a monotonically increasing number. A minimum of two samples must be sent, in order to
calculate a delta value and report it to the backend as a rate-per-second. A variety of networking
metrics may be reported monotonically, and this metric type provides a convenient means of recording
these values, at the expense of a slower time-to-first metric.

Call `Set()` when an event occurs:

```cpp
#include <registry.h>

int main()
{
auto config = Config(WriterConfig(WriterTypes::UDP));
auto r = Registry(config);

// Option 1: Directly create a Monotonic Counter
auto interfaceBytes = r.CreateMonotonicCounter("iface.bytes");
interfaceBytes.Set(10);

// Option 2: Create a Monotonic Counter from a MeterID
auto interfaceBytesMeter = r.CreateNewId("iface.bytes");
r.CreateMonotonicCounter(interfaceBytesMeter).Set(10);
}
```
31 changes: 31 additions & 0 deletions docs/spectator/lang/cpp/meters/percentile-dist-summary.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
The value tracks the distribution of events, with percentile estimates. It is similar to a
`PercentileTimer`, but more general, because the size does not have to be a period of time.

For example, it can be used to measure the payload sizes of requests hitting a server or the
number of records returned from a query. Note that the C++ implementation of Percentile Distribution
Summary allows for the recording of floating point values, which the other thin clients do not
allow.

In order to maintain the data distribution, they have a higher storage cost, with a worst-case of
up to 300X that of a standard Distribution Summary. Be diligent about any additional dimensions
added to Percentile Distribution Summaries and ensure that they have a small bounded cardinality.

Call `Record()` with a value:

```cpp
#include <registry.h>

int main()
{
auto config = Config(WriterConfig(WriterTypes::UDP));
auto r = Registry(config);

// Option 1: Directly create a Percentile Distribution Summary
auto serverSize = r.CreatePercentDistributionSummary("server.requestSize");
serverSize.Record(10);

// Option 2: Create a Percentile Distribution Summary from a MeterID
auto requestSizeMeter = r.CreateNewId("server.requestSize");
r.CreatePercentDistributionSummary(requestSizeMeter).Record(10);
}
```
29 changes: 29 additions & 0 deletions docs/spectator/lang/cpp/meters/percentile-timer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
The value is the number of seconds that have elapsed for an event, with percentile estimates.

This metric type will track the data distribution by maintaining a set of Counters. The
distribution can then be used on the server side to estimate percentiles, while still
allowing for arbitrary slicing and dicing based on dimensions.

In order to maintain the data distribution, they have a higher storage cost, with a worst-case of
up to 300X that of a standard Timer. Be diligent about any additional dimensions added to Percentile
Timers and ensure that they have a small bounded cardinality.

Call `Record()` with a value:

```cpp
#include <registry.h>

int main()
{
auto config = Config(WriterConfig(WriterTypes::UDP));
auto r = Registry(config);

// Option 1: Directly create a Percentile Timer
auto serverLatency = r.CreatePercentTimer("server.requestLatency");
serverLatency.Record(10);

// Option 2: Create a Percentile Timer from a MeterID
auto requestLatencyMeter = r.CreateNewId("server.requestLatency");
r.CreatePercentTimer(requestLatencyMeter).Record(10);
}
```
21 changes: 21 additions & 0 deletions docs/spectator/lang/cpp/meters/timer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
A Timer is used to measure how long (in seconds) some event is taking.

Call `Record()` with a value:

```cpp
#include <registry.h>

int main()
{
auto config = Config(WriterConfig(WriterTypes::UDP));
auto r = Registry(config);

// Option 1: Directly create a Timer
auto serverLatency = r.CreateTimer("server.requestLatency");
serverLatency.Record(10);

// Option 2: Create a Timer from a MeterID
auto requestLatencyMeter = r.CreateNewId("server.requestLatency");
r.CreateTimer(requestLatencyMeter).Record(10);
}
```
42 changes: 42 additions & 0 deletions docs/spectator/lang/cpp/migrations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
## Migrating to 2.X

Version 2.X consists of a major rewrite that greatly simplifies spectator-cpp and the process in
which it sends metrics to SpectatorD.

### New

#### Writers

`spectator.Registry` now supports 3 different writers. The WriterType is specified through a WriterConfig object.

See [Usage > Output Location](usage.md#output-location) for more details.

#### Common Tags

A few local environment common tags are now automatically added to all Meters. Their values are read
from the environment variables.

| Tag | Environment Variable |
|--------------|----------------------|
| nf.container | TITUS_CONTAINER_NAME |
| nf.process | NETFLIX_PROCESS_NAME |

Tags from environment variables take precedence over tags passed on code when creating the `Config`.

Note that common tags sourced by [spectatord](https://github.com/Netflix-Skunkworks/spectatord) can't be overwritten.

#### Registry, Config, and Writer Config

* `Config` is now created through a constructor which throws an error, if the passed in parameters are not valid.
* `WriterConfig` now specifies which writer type the thin client uses.
* `WriterConfig` allows line buffering for all writer types.
* `Registry` is instantiated by passing only a `Config` object to it.

### Migration Steps

1. Remove old references to the old spectator library implementation.
2. Utilize the `Config` & `WriterConfig` to initialize the `Registry`.
3. Currently there is no support for collecting runtime metrics, using the spectator-cpp library.
4. If you need to configure a `Registry` that doesn't emit metrics, for testing purposes, you can
use the `WriterConfig` to configure a `MemoryWriter`. This will emit metrics to a vector, so make
sure to clear the vector every so often.
Loading