Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
marcingrzejszczak committed Aug 17, 2023
1 parent ae43f56 commit 2a62e83
Show file tree
Hide file tree
Showing 94 changed files with 3,700 additions and 0 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
101 changes: 101 additions & 0 deletions docs/modules/ROOT/pages/contextpropagation.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@

[[context-propagation-support]]
= Context Propagation support

[[context-propagation-purpose]]
== Purpose

https://github.com/micrometer-metrics/context-propagation[A library] that assists with context propagation across different types of context
mechanisms such as `ThreadLocal`, Reactor https://projectreactor.io/docs/core/release/reference/#context[Context]
and others.

Abstractions:

* `ThreadLocalAccessor` - contract to assist with access to a `ThreadLocal` value.
* `ContextAccessor` - contract to assist with access to a `Map`-like context.
* `ContextRegistry` - registry for instances of `ThreadLocalAccessor` and `ContextAccessor`.
* `ContextSnapshot` - holder of contextual values, that provides methods to capture and to propagate.

Example Scenarios:

* In imperative code, e.g. Spring MVC controller, capture `ThreadLocal` values into a
`ContextSnapshot`. After that use the snapshot to populate a Reactor `Context` with the
captured values, or to wrap a task (e.g. `Runnable`, `Callable`, etc) or an `Executor`
with a decorator that restores `ThreadLocal` values when the task executes.
* In reactive code, e.g. Spring WebFlux controller, create a `ContextSnapshot` from
Reactor `Context` values. After that use the snapshot to restore `ThreadLocal` values
within a specific stage (operator) of the reactive chain.

Context values can originate from any context mechanism and propagate to any other, any
number of times. For example, a value in a `Reactor` context may originate as a
`ThreadLocal`, and may yet become a `ThreadLocal` again, and so on.

Generally, imperative code should interact with `ThreadLocal` values as usual, and
likewise Reactor code should interact with the Reactor `Context` as usual. The Context
Propagation library is not intended to replace those, but to assist with propagation when
crossing from one type of context to another, e.g. when imperative code invokes a Reactor
chain, or when a Reactor chain invokes an imperative component that expects
`ThreadLocal` values.

The library is not limited to context propagation from imperative to reactive. It can
assist in asynchronous scenarios to propagate `ThreadLocal` values from one thread to
another. It can also propagate to any other type of context for which there is a
registered `ContextAccesor` instance.

== Installing

Snapshots are published to https://repo.spring.io/snapshot for every successful build on the `main` branch and maintenance branches.

Milestone releases are published to https://repo.spring.io/milestone. Include that as a Maven repository in your build
configuration to use milestone releases. Note that milestone releases are for testing purposes and are not intended for
production use.

The following example shows the required dependency in Gradle:

[source,groovy,subs=+attributes]
----
implementation 'io.micrometer:context-propagation:latest.integration'
----

The following example shows the required dependency in Maven:

[source,xml,subs=+attributes]
----
<dependencies>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>context-propagation</artifactId>
<version>${micrometer-context-propagation.version}</version>
</dependency>
</dependencies>
----

[[context-propagation-usage-examples]]
== Usage Examples

[[context-propagation-usage-examples-thread-local]]
=== `ThreadLocal` Population

Below you can find a holder for `ThreadLocal` values.

.ObservationThreadLocalHolder
[source,java,subs=+attributes]
-----
include::{include-java}/context/ObservationThreadLocalHolder.java[tags=holder,indent=0]
-----

Below you can find a `ThreadLocalAccessor` that interacts with the holder.

.ObservationThreadLocalAccessor
[source,java,subs=+attributes]
-----
include::{include-java}/context/ObservationThreadLocalAccessor.java[tags=accessor,indent=0]
-----

Below you can find an example of how to store and restore thread local values via `ThreadLocalAccessor`, `ContextSnapshot` and `ContextRegistry`.

[source,java,subs=+attributes]
-----
include::{include-java}/context/DefaultContextSnapshotTests.java[tags=simple,indent=0]
-----

4 changes: 4 additions & 0 deletions docs/modules/ROOT/pages/guides.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[[guides]]
== Guides

In this section you can find guides on how to perform certain uncommon actions with Micrometer.
90 changes: 90 additions & 0 deletions docs/modules/ROOT/pages/guides/console-reporter.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
= Passing through to Dropwizard's Console Reporter

This guide shows how to plug in less commonly used Dropwizard `Reporter` implementations -- in this case, the `ConsoleReporter`.

[source,java]
----
@Bean
public MetricRegistry dropwizardRegistry() {
return new MetricRegistry();
}
@Bean
public ConsoleReporter consoleReporter(MetricRegistry dropwizardRegistry) {
ConsoleReporter reporter = ConsoleReporter.forRegistry(dropwizardRegistry)
.convertRatesTo(TimeUnit.SECONDS)
.convertDurationsTo(TimeUnit.MILLISECONDS)
.build();
reporter.start(1, TimeUnit.SECONDS);
return reporter;
}
@Bean
public MeterRegistry consoleLoggingRegistry(MetricRegistry dropwizardRegistry) {
DropwizardConfig consoleConfig = new DropwizardConfig() {
@Override
public String prefix() {
return "console";
}
@Override
public String get(String key) {
return null;
}
};
return new DropwizardMeterRegistry(consoleConfig, dropwizardRegistry, HierarchicalNameMapper.DEFAULT, Clock.SYSTEM) {
@Override
protected Double nullGaugeValue() {
return null;
}
};
}
----

Note that, in a Spring environment, this registry is added to other implementations in a composite and is used for all metrics, both custom and
auto-configured.

[source,java]
----
class MyComponent {
private final MeterRegistry registry;
public MyComponent(MeterRegistry registry) {
this.registry = registry;
}
public void doSomeWork(String lowCardinalityInput) {
registry.timer("my.latency", "input", lowCardinalityInput).record(() -> {
// do work
});
}
}
----

The following listing shows typical output for this custom timer:

[source,txt]
----
3/2/18 10:14:27 AM =============================================================
-- Timers ----------------------------------------------------------------------
myLatency.lowCardinalityInput.INPUT
count = 1
mean rate = 1.02 calls/second
1-minute rate = 0.00 calls/second
5-minute rate = 0.00 calls/second
15-minute rate = 0.00 calls/second
min = 100.00 milliseconds
max = 100.00 milliseconds
mean = 100.00 milliseconds
stddev = 0.00 milliseconds
median = 100.00 milliseconds
75% <= 100.00 milliseconds
95% <= 100.00 milliseconds
98% <= 100.00 milliseconds
99% <= 100.00 milliseconds
99.9% <= 100.00 milliseconds
----
72 changes: 72 additions & 0 deletions docs/modules/ROOT/pages/guides/custom-meter-registry.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
= Custom Meter Registry

Micrometer supports popular meter registries out of the box, so you should check those first.
For an existing meter registry, if you think that your requirements are generally useful, consider creating an issue or PR against the Micrometer issue tracker.
For a non-existent meter registry, if it is widely-used, consider creating an issue or PR for it.

If you need to create your own custom meter registry, you can create it by extending one of the base classes for meter registries: `MeterRegistry`, `PushMeterRegistry`, or `StepMeterRegistry`.

The most common way is to extend `StepMeterRegistry`.
You can create your own custom `StepMeterRegistry`.

First, define your own meter registry configuration by extending `StepRegistryConfig`, as follows:

[source,java]
----
public interface CustomRegistryConfig extends StepRegistryConfig {
CustomRegistryConfig DEFAULT = k -> null;
@Override
default String prefix() {
return "custom";
}
}
----

Second, define your own meter registry by extending `StepMeterRegistry`, as follows:

[source,java]
----
public class CustomMeterRegistry extends StepMeterRegistry {
public CustomMeterRegistry(CustomRegistryConfig config, Clock clock) {
super(config, clock);
start(new NamedThreadFactory("custom-metrics-publisher"));
}
@Override
protected void publish() {
getMeters().stream().forEach(meter -> System.out.println("Publishing " + meter.getId()));
}
@Override
protected TimeUnit getBaseTimeUnit() {
return TimeUnit.MILLISECONDS;
}
}
----

Finally, create the meter registry configuration and the meter registry.
If you use Spring Boot, you can do so as follows:

[source,java]
----
@Configuration
public class MetricsConfig {
@Bean
public CustomRegistryConfig customRegistryConfig() {
return CustomRegistryConfig.DEFAULT;
}
@Bean
public CustomMeterRegistry customMeterRegistry(CustomRegistryConfig customRegistryConfig, Clock clock) {
return new CustomMeterRegistry(customRegistryConfig, clock);
}
}
----
39 changes: 39 additions & 0 deletions docs/modules/ROOT/pages/guides/http-sender-resilience4j-retry.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
= HttpSender with Resilience4j Retry

`HttpSender` is an interface for HTTP clients that are used in meter registries for HTTP-based metrics publication. There
are two implementations:

* `HttpUrlConnectionSender`: `HttpURLConnection`-based `HttpSender`
* `OkHttpSender`: OkHttp-based `HttpSender`
There is no out-of-the-box support for retry, but you can decorate it with Resilience4j retry, as follows:

[source,java]
----
@Bean
public DatadogMeterRegistry datadogMeterRegistry(DatadogConfig datadogConfig, Clock clock) {
return DatadogMeterRegistry.builder(datadogConfig)
.clock(clock)
.httpClient(new RetryHttpClient())
.build();
}
private static class RetryHttpClient extends HttpUrlConnectionSender {
private final RetryConfig retryConfig = RetryConfig.custom()
.maxAttempts(2)
.waitDuration(Duration.ofSeconds(5))
.build();
private final Retry retry = Retry.of("datadog-metrics", this.retryConfig);
@Override
public Response send(Request request) {
CheckedFunction0<Response> retryableSupplier = Retry.decorateCheckedSupplier(
this.retry,
() -> super.send(request));
return Try.of(retryableSupplier).get();
}
}
----
4 changes: 4 additions & 0 deletions docs/modules/ROOT/pages/implementations.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[[implementations-setup]]
== Setup

Instructions for how to configure Micrometer for use with different monitoring systems. As a facade over multiple monitoring systems, the point of Micrometer is to allow you to instrument your code in the same way and be able to visualize the results in your monitoring system of choice.
63 changes: 63 additions & 0 deletions docs/modules/ROOT/pages/implementations/appOptics.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
= Micrometer AppOptics
:toc:
:sectnums:
:system: appoptics

AppOptics is a dimensional time-series SaaS with built-in dashboarding.

include::install.adoc[]

== Configuring

The following example configures an AppOptics instance:

[source,java]
----
AppOpticsConfig appopticsConfig = new AppOpticsConfig() {
@Override
public String apiToken() {
return MY_TOKEN;
}
@Override
@Nullable
public String get(String k) {
return null;
}
};
MeterRegistry registry = new AppOpticsMeterRegistry(appopticsConfig, Clock.SYSTEM);
----

`AppOpticsConfig` is an interface with a set of default methods. If, in the implementation of `get(String k)`, rather than returning `null`, you instead bind it to a property source, you can override the default configuration. For example, Micrometer's Spring Boot support binds properties that are prefixed with `management.metrics.export.appoptics` directly to the `AppOpticsConfig`:

[source,yml]
----
management.metrics.export.appoptics:
api-token: YOURKEY
# You will probably want disable AppOptics publishing in a local development profile.
enabled: true
# The interval at which metrics are sent to AppOptics. The default is 1 minute.
step: 1m
----

== Graphing

This section serves as a quick start to rendering useful representations in AppOptics for metrics that originate in Micrometer.

=== Timers

The AppOptics implementation of `Timer` produces three fields in AppOptics:

* `sum`: Rate of calls per second.
* `count`: Rate of total time per second.
* `max`: A sliding window maximum amount recorded.

.Dimensionally aggregable average in AppOptics.
image::implementations/appoptics-timer-average.png[AppOptics timer average]

AppOptics performs the `sum/count` division dimensionally to generate aggregable averages on your behalf.

.Timer over a simulated service.
image::implementations/appoptics-timer.png[AppOptics-rendered timer]
Loading

0 comments on commit 2a62e83

Please sign in to comment.