Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Background and Motivations
Given that there are a number of breaking changes around context propagation in Kamon and we will have to release a non backwards compatible Kamon 2.0 version, it seemed like a great opportunity to spread some love through the entire code base, so the work on this PR started. There are a number of issues that sparked interesting on reworking the metrics API, most notably #546, although there are plenty more on the related issues section bellow.
Goals
Changes in this PR
Metrics and Instruments
Even though we did have different concepts for metrics and instruments and there isn't much of a big change there, now it is clearer that a metric is a group of instruments and all instruments for a given metric share the same settings. Furthermore, the settings are available through the
.settings
member on the metric and all instruments have a reference to the metric they belong to.Metrics with Descriptions
We believe that having a proper description of what is being tracked by a metric can be of great help and furthermore, many of today's systems support showing a description for the metrics so we are allowing to provide a description for metrics. We will always expose a description, even if no description is provided by you when creating a metric.
Tagging instead of "refining"
We changed
.refine(...)
to.withTag(...)
variants. At the time we thought that the word "refine" was a much better way to explain what we are doing but if we are using tags everywhere and this function is actually returning a new instrument with more tags, just calling it.withTag(...)
seems like something way easier explain and to understand by users.Also, now it is possible to apply tags directly on an instrument, which will add to/replace the tags on the instrument and return it, rather than having to go all the way to the base metric in order to get a particular instrument. A relatively common pattern on instrumentation was having a set of common tags for a metric that should be applied to all instruments and then "refine" for a particular case, which forced us to keep references to the maps used for tags because the only way to remove an instrument was going back to the base metric and calling
.remove(...)
with all the tags as shown bellow:Since this PR, instruments know how to remove themselves from the registry and there is no need to reference the base metric at all:
Finally, one thing that we had in the past was the ability to record values directly on a metric instance without refining, which would result in writing data on an instrument that has no tags. This allowed people to do things like this:
We had this because it seemed like many users would want to do that themselves and there was a considerable amount of boilerplate on the metrics implementation to allow it, but now that we are introducing a much clearer separation between metrics and instruments it didn't make sense to allow instrument operations on a metric so the "base" instruments (without tags) has to be requested explicitly now:
Gauges use Double instead of Long
Using
Double
instead ofLong
on gauges was a long standing issue (no pun intended) with the metrics API and we finally made the change. Even though we really don't recommend people using gauges, every now and then they are useful and when they are, having the ability to use floating points can come in handy (think of some ratio metrics or load average if it was being tracked with a gauge).Auto-update all the Things
There was a request to allow providing a function that will automatically update a gauge, which was a clear need since long time ago but while implementing it, we realized that there are a few patterns that we use quite often like using a histogram as some sort of "sampler" so we periodically take samples of a value and store it in a Histogram (e.g. storing CPU usage on the system metrics module), or wanting to update a counter with a value coming from a cumulative counter from somewhere else on the JVM. Even we do auto-update internally with the range samplers so, instead of making auto update something specific to Guages we added it to all instruments, starting from this PR users can schedule auto-update actions on any instrument.
Furthermore, for the particular case of cumulative counters we added
Counter.delta(...)
function that makes it easier to create a producer of values for the auto-update action:Fluent APIs
Instruments return themselves or new instruments with calling most of their APIs so actions can be chained.
Metric and Instrument Inspection for Testing
We rewrote the previous inspection utilities and separated them into
MetricInspection
andInstrumentInspection
with easy access via static members for Java users and implicit extensions for Scala users. From Java, trying to get the distribution of values in an instrument can look like this now:PeriodSnapshot changed
The
PeriodSnapshot
object which is sent to the metric reporters has been updated to reflect the changes in the structure. Also, there have been a number of updates to the PeriodSnapshot accumulator which now can expire entries after they have not been updated for more than a certain period of time.Docs Docs Docs
We put some extra effort to make sure that all public APIs have a decent scaladoc that can help users discover how to use metrics and instruments.
Related Issues:
These are some of the issues that we expect to be solving with this PR: