Skip to content

Commit

Permalink
Editing pass
Browse files Browse the repository at this point in the history
for consistency and readability.
  • Loading branch information
Jay Bryant committed Sep 15, 2023
1 parent a93271d commit 764cfb9
Show file tree
Hide file tree
Showing 52 changed files with 302 additions and 293 deletions.
6 changes: 3 additions & 3 deletions src/docs/cache/index.adoc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Micrometer supports binding metrics to a variety of different popular caching libraries. Each implementation supports basic features, such as cache hits versus misses, from which you can derive basic information about the cache hit ratio over a period of time. Micrometer uses a function tracking counter to monitor such things as hits and misses, giving you a notion not only of hits and misses over the total life of the cache (the basic metric exposed from Guava's `CacheStats`, for example) but hits and misses inside a given interval.
Micrometer supports binding metrics to a variety of popular caching libraries. Each implementation supports basic features, such as cache hits versus misses, from which you can derive basic information about the cache hit ratio over a period of time. Micrometer uses a function-tracking counter to monitor such things as hits and misses, giving you a notion not only of hits and misses over the total life of the cache (the basic metric exposed from Guava's `CacheStats`, for example) but hits and misses inside a given interval.

To demonstrate the features of cache monitoring, we start with a simple program that uses `reactor-netty` to read the entirety of Mary Shelley's _Frankenstein_ and put each word in the cache if it has not yet been seen:

Expand Down Expand Up @@ -28,7 +28,7 @@ image::img/prometheus-guava-cache.png[Hits vs. misses,width=800]
rate(book_guava_requests_total[10s])
```

By dividing the hits by the sum of all `get` operations (regardless of whether or not each one was a hit or a miss), we can arrive at a notion of the upper bound for the hit ratio for reading Frankenstein with only 10,000 words:
By dividing the hits by the sum of all `get` operations (regardless of whether or not each one was a hit or a miss), we can arrive at a notion of the upper bound for the hit ratio for reading _Frankenstein_ with only 10,000 words:

.Hit ratio, viewed by Prometheus
image::img/prometheus-guava-cache-ratio.png[Hit ratio,width=800]
Expand All @@ -37,7 +37,7 @@ image::img/prometheus-guava-cache-ratio.png[Hit ratio,width=800]
sum(rate(book_guava_requests_total{result="hit"}[1m])) / sum(rate(book_guava_requests_total[1m]))
```

In a real-world scenario, we tune caches according to how we evaluate the tradeoff between storage and load efficiency. You could create an alert based on some upper bound for the rate at which misses occur or on a lower bound for the hit ratio. Setting an upper bound on miss ratio is better than a lower bound on hit ratio. For both ratios, an absence of any activity drops the value to 0.
In a real-world scenario, we tune caches according to how we evaluate the tradeoff between storage and load efficiency. You could create an alert based on some upper bound for the rate at which misses occur or on a lower bound for the hit ratio. Setting an upper bound on the miss ratio is better than a lower bound on the hit ratio. For both ratios, an absence of any activity drops the value to 0.
The following image shows the miss ratio when it exceeds 10%:

.Alerting when the miss ratio exceeds 10%
Expand Down
4 changes: 2 additions & 2 deletions src/docs/concepts/counters.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ registry.more().counter("evictions", tags, cache, c -> c.stats().evictionCount()

The function-tracking counter, in concert with the monitoring system's rate normalizing functionality (whether this is an artifact of the query language or the way data is pushed to the system), adds a layer of richness on top of the cumulative value of the function itself. You can reason about the _rate_ at which the value is increasing, whether that rate is within an acceptable bound, is increasing or decreasing over time, and so on.

WARNING: Micrometer cannot guarantee the monotonicity of the function for you. By using this signature, you are asserting its monotonicity based on what you know about its definition.
WARNING: Micrometer cannot guarantee the monotonicity of the function for you. By using this signature, you assert its monotonicity based on what you know about its definition.

A fluent builder for function counters on the `FunctionCounter` interface itself provides access to less frequently used options, such as base units and description. You can register the counter as the last step of its construction by calling `register(MeterRegistry)`.
A fluent builder for function counters on the `FunctionCounter` interface itself provides access to less frequently used options, such as base units and description. You can register the counter as the last step of its construction by calling `register(MeterRegistry)`:

[source, java]
----
Expand Down
2 changes: 1 addition & 1 deletion src/docs/concepts/distribution-summaries.adoc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
A distribution summary tracks the distribution of events. It is similar to a timer structurally, but records values that do not represent a unit of time. For example, you could use a distribution summary to measure the payload sizes of requests hitting a server.
A distribution summary tracks the distribution of events. It is structurally similar to a timer but records values that do not represent a unit of time. For example, you could use a distribution summary to measure the payload sizes of requests hitting a server.

The following example creates a distribution summary:

Expand Down
6 changes: 3 additions & 3 deletions src/docs/concepts/gauges.adoc
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
A gauge is a handle to get the current value. Typical examples for gauges would be the size of a collection or map or number of threads in a running state.
A gauge is a handle to get the current value. Typical examples for gauges would be the size of a collection or map or the number of threads in a running state.

TIP: Gauges are useful for monitoring things with natural upper bounds. We do not recommend using a gauge to monitor things like request count, as they can grow without bound for the duration of an application instance's life.

TIP: Never gauge something you can count with a `Counter`!

Micrometer takes the stance that gauges should be sampled and not be set, so there is no information about what might have occurred between samples. Any intermediate values set on a gauge are lost by the time the gauge value is reported to a metrics backend, so there is little value in setting those intermediate values in the first place.

Think of a `Gauge` as a "`heisen-gauge`": a meter that changes only when it is observed. Every other meter type accumulates intermediate counts toward the point where the data is sent to the metrics backend.
Think of a `Gauge` as a "`heisenberg-gauge`": a meter that changes only when it is observed. Every other meter type accumulates intermediate counts toward the point where the data is sent to the metrics backend.

The `MeterRegistry` interface contains methods for building gauges to observe numeric values, functions, collections, and maps:

Expand Down Expand Up @@ -35,7 +35,7 @@ myGauge.set(27);
myGauge.set(11);
----

Note that, in this form, unlike other meter types, you do not get a reference to the `Gauge` when creating one. Rather, you get a reference to the thing being observed. This is because of the "`heisen-gauge`" principal: The gauge is self-sufficient once created, so you should never need to interact with it. This lets us give you back only the instrumented object, which allows for quick one-liners that both create the object to be observed and set up metrics around it.
Note that, in this form, unlike other meter types, you do not get a reference to the `Gauge` when creating one. Rather, you get a reference to the thing being observed. This is because of the "`heisenberg-gauge`" principal: The gauge is self-sufficient once created, so you should never need to interact with it. This lets us give you back only the instrumented object, which allows for quick one-liners that both create the object to be observed and set up metrics around it.

This pattern should be less common than the `DoubleFunction` form. Remember that frequent setting of the observed `Number` results in a lot of intermediate values that never get published. Only the _instantaneous value_ of the gauge at publish time is ever sent to the monitoring system.

Expand Down
4 changes: 3 additions & 1 deletion src/docs/concepts/implementations.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ Micrometer contains a core module with an instrumentation https://en.wikipedia.o
|Server-side

|AppOptics, Atlas, Azure Monitor, Datadog, Dynatrace, Elastic, Graphite, Ganglia, Humio, Influx, JMX, Kairos, New Relic, all StatsD flavors, SignalFx
|Prometheus, Wavefront footnote:[As of 1.2.0, Micrometer sends cumulative values to Wavefront.]
|Prometheus, Wavefront
|===

NOTE: As of 1.2.0, Micrometer sends cumulative values to Wavefront.

* *Publishing*. Some systems expect to poll applications for metrics at their leisure, while others expect metrics to be pushed to them on a regular interval.
[cols=2*,options="header"]
Expand Down
10 changes: 5 additions & 5 deletions src/docs/concepts/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,18 @@

Micrometer is a metrics instrumentation library for JVM-based applications. It provides a simple facade over the instrumentation clients for the most popular monitoring systems, letting you instrument your JVM-based application code without vendor lock-in. It is designed to add little to no overhead to your metrics collection activity while maximizing the portability of your metrics effort.

Starting from Micrometer 1.10, Micrometer provides the link:../docs/observation[Observation API] and a plugin mechanism that allows you to add capabilities including the tracing features. You can read more about this in the link:../docs/tracing[Micrometer Tracing documentation].
Starting from Micrometer 1.10, Micrometer provides the link:../docs/observation[Observation API] and a plugin mechanism that lets you add capabilities, including the tracing features. You can read more about this in the link:../docs/tracing[Micrometer Tracing documentation].

For better understanding the differences among these different types of systems (Metrics, Distributed Tracing, and Logging) we recommend Adrian Cole's talk, titled https://www.dotconferences.com/2017/04/adrian-cole-observability-3-ways-logging-metrics-tracing[Observability
3 Ways]. To learn more about Micrometer Observation API we recommend Tommy Ludwig's and Marcin Grzejszczak's talk, titled https://www.youtube.com/watch?v=fh3VbrPvAjg[Observability of Your Application].
For better understanding of the differences among these different types of systems (Metrics, Distributed Tracing, and Logging) we recommend Adrian Cole's talk, titled https://www.dotconferences.com/2017/04/adrian-cole-observability-3-ways-logging-metrics-tracing[Observability
3 Ways]. To learn more about Micrometer Observation API, we recommend Tommy Ludwig's and Marcin Grzejszczak's talk, titled https://www.youtube.com/watch?v=fh3VbrPvAjg[Observability of Your Application].

== Dependencies

The `micrometer-core` module aims to have minimal dependencies. It does not require any third-party (non-Micrometer) dependencies on the classpath at compile time for applications using Micrometer.
The `micrometer-core` module aims to have minimal dependencies. It does not require any third-party (non-Micrometer) dependencies on the classpath at compile time for applications that use Micrometer.

Use of the link:#_pause_detection[pause detection] feature requires the https://github.com/LatencyUtils/LatencyUtils[LatencyUtils] dependency to be available on the classpath at runtime. If your application does not use the pause detection feature, you can exclude LatencyUtils from your runtime classpath.

https://github.com/HdrHistogram/HdrHistogram[HdrHistogram] is needed on the classpath at runtime if you use link:#_histograms_and_percentiles[client-side percentiles]. If you are not using client-side percentiles, you may exclude HdrHistogram from your application's runtime classpath.
If you use link:#_histograms_and_percentiles[client-side percentiles], you need the https://github.com/HdrHistogram/HdrHistogram[HdrHistogram] on the classpath at runtime. If you do not use client-side percentiles, you may exclude HdrHistogram from your application's runtime classpath.

== Supported Monitoring Systems

Expand Down
6 changes: 3 additions & 3 deletions src/docs/concepts/meter-filters.adoc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
You can configure each registry with meter filters, which give you greater control over how and when meters are registered and what kinds of statistics they emit. Meter filters serve three basic functions:

1. **Deny** (or **Accept**) meters being registered.
2. **Transform** meter IDs (for example, changing the name, adding or removing tags, and changing description or base units).
2. **Transform** meter IDs (for example, changing the name, adding or removing tags, and changing the description or base units).
3. **Configure** distribution statistics for some meter types.
Implementations of `MeterFilter` are added to the registry programmatically:
Expand Down Expand Up @@ -53,7 +53,7 @@ new MeterFilter() {
* `denyNameStartsWith(String)`: Deny every meter with a matching prefix. All `MeterBinder` implementations provided by Micrometer have names with common prefixes to allow for easy grouping visualization in UIs but also to make them easy to disable or enable as a group with a prefix. For example, you can deny all JVM metrics with `MeterFilter.denyNameStartsWith("jvm")`.
* `deny(Predicate<Meter.Id>)`: Deny any meter that matches the predicate.
* `maximumAllowableMetrics(int)`: Deny any meter after the registry has reached a certain number of meters.
* `maximumAllowableTags(String meterNamePrefix, String tagKey, int maximumTagValues, MeterFilter onMaxReached)`: Places an upper bound on the number of tags produced by matching series.
* `maximumAllowableTags(String meterNamePrefix, String tagKey, int maximumTagValues, MeterFilter onMaxReached)`: Places an upper bound on the number of tags produced by the matching series.

**Whitelisting** only a certain group of metrics is a particularly common case for monitoring systems that are _expensive_. This can be achieved with a static call:

Expand All @@ -74,7 +74,7 @@ registry.config()

This achieves another form of whitelisting by stacking two filters together. Only `http` metrics are allowed to exist in this registry.

== Transforming metrics
== Transforming Metrics

The following example shows a transform filter:

Expand Down
6 changes: 3 additions & 3 deletions src/docs/concepts/naming.adoc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Micrometer employs a naming convention that separates lowercase words with a `.` (dot) character. Different monitoring systems have different recommendations regarding naming convention, and some naming conventions may be incompatible between one system and another. Each Micrometer implementation for a monitoring system comes with a naming convention that transforms lowercase dot notation names to the monitoring system's recommended naming convention. Additionally, this naming convention implementation removes special characters that are disallowed by the monitoring system from the metric names and tags. You can override the default naming convention for a registry by implementing `NamingConvention` and setting it on the registry:
Micrometer employs a naming convention that separates lowercase words with a `.` (dot) character. Different monitoring systems have different recommendations regarding naming conventions, and some naming conventions may be incompatible between one system and another. Each Micrometer implementation for a monitoring system comes with a naming convention that transforms lowercase dot notation names to the monitoring system's recommended naming convention. Additionally, this naming convention implementation removes special characters that are disallowed by the monitoring system from the metric names and tags. You can override the default naming convention for a registry by implementing `NamingConvention` and setting it on the registry:

====
[source,java]
Expand Down Expand Up @@ -60,7 +60,7 @@ In this approach, if we select `calls`, we get a value that is an aggregate of t

== Common Tags

You can define common tags at the registry level and add them to every metric reported to the monitoring system. This is generally used for dimensional drill-down on the operating environment, such as host, instance, region, stack, and others:
You can define common tags at the registry level and add them to every metric reported to the monitoring system. This is generally used for dimensional drill-down on the operating environment, such as host, instance, region, stack, and others. The following lines set the same tag in two equivalent ways:

====
[source,java]
Expand All @@ -70,7 +70,7 @@ registry.config().commonTags(Arrays.asList(Tag.of("stack", "prod"), Tag.of("regi
----
====

Calls to `commonTags` append additional common tags.
Further calls to `commonTags` append additional common tags.

[IMPORTANT]
====
Expand Down
Loading

0 comments on commit 764cfb9

Please sign in to comment.