From 9826df30e474858d29e51a96ae15a1492f94c095 Mon Sep 17 00:00:00 2001 From: Auri Munoz Date: Wed, 4 Oct 2023 17:21:33 +0200 Subject: [PATCH] Add doc for observability --- .../java/io/smallrye/stork/api/Service.java | 6 +- .../NoopObservationCollector.java | 4 +- .../observability/ObservationCollector.java | 2 +- .../api/observability/ObservationPoints.java | 0 .../api/observability/StorkEventHandler.java | 2 +- ...ationPoints.java => StorkObservation.java} | 8 +- .../stork/FakeObservationCollector.java | 9 +- .../io/smallrye/stork/ObservationTest.java | 33 ++--- .../docs/diagrams/observability_sequence.puml | 24 ++++ docs/docs/diagrams/observation_sequence.puml | 37 ++++++ docs/docs/observability.md | 122 ++++++++++++++++++ .../__pycache__/docissimo.cpython-310.pyc | Bin 0 -> 4075 bytes docs/mkdocs.yml | 1 + .../examples/AcmeObservationCollector.java | 36 ++++++ .../ObservableInitializationExample.java | 13 ++ .../snippets/examples/ObservationExample.java | 35 +++++ 16 files changed, 295 insertions(+), 37 deletions(-) delete mode 100644 api/src/main/java/io/smallrye/stork/api/observability/ObservationPoints.java rename api/src/main/java/io/smallrye/stork/api/observability/{StorkObservationPoints.java => StorkObservation.java} (93%) create mode 100644 docs/docs/diagrams/observability_sequence.puml create mode 100644 docs/docs/diagrams/observation_sequence.puml create mode 100644 docs/docs/observability.md create mode 100644 docs/mkdocs-customizations/macros/__pycache__/docissimo.cpython-310.pyc create mode 100644 docs/snippets/examples/AcmeObservationCollector.java create mode 100644 docs/snippets/examples/ObservableInitializationExample.java create mode 100644 docs/snippets/examples/ObservationExample.java diff --git a/api/src/main/java/io/smallrye/stork/api/Service.java b/api/src/main/java/io/smallrye/stork/api/Service.java index 92041d92..84f538e6 100644 --- a/api/src/main/java/io/smallrye/stork/api/Service.java +++ b/api/src/main/java/io/smallrye/stork/api/Service.java @@ -6,7 +6,7 @@ import io.smallrye.mutiny.Uni; import io.smallrye.stork.api.observability.ObservationCollector; -import io.smallrye.stork.api.observability.StorkObservationPoints; +import io.smallrye.stork.api.observability.StorkObservation; /** * Represents a Service. @@ -62,7 +62,7 @@ public Service(String serviceName, * a service instance capable of handling a call */ public Uni selectInstance() { - StorkObservationPoints observationPoints = observations.create(serviceName, serviceDiscoveryType, + StorkObservation observationPoints = observations.create(serviceName, serviceDiscoveryType, serviceSelectionType); return serviceDiscovery.getServiceInstances() .onItemOrFailure().invoke((list, failure) -> { @@ -109,7 +109,7 @@ public ServiceInstance selectInstance(Collection instances) { * @see LoadBalancer#requiresStrictRecording() */ public Uni selectInstanceAndRecordStart(boolean measureTime) { - StorkObservationPoints observationPoints = observations.create(serviceName, serviceDiscoveryType, + StorkObservation observationPoints = observations.create(serviceName, serviceDiscoveryType, serviceSelectionType); return serviceDiscovery.getServiceInstances().onItemOrFailure().invoke((list, failure) -> { if (failure != null) { diff --git a/api/src/main/java/io/smallrye/stork/api/observability/NoopObservationCollector.java b/api/src/main/java/io/smallrye/stork/api/observability/NoopObservationCollector.java index 24832f08..834e2cd1 100644 --- a/api/src/main/java/io/smallrye/stork/api/observability/NoopObservationCollector.java +++ b/api/src/main/java/io/smallrye/stork/api/observability/NoopObservationCollector.java @@ -10,7 +10,7 @@ public class NoopObservationCollector implements ObservationCollector { // NOOP }; - public static final StorkObservationPoints NOOP_STORK_EVENT = new StorkObservationPoints( + public static final StorkObservation NOOP_STORK_EVENT = new StorkObservation( null, null, null, NOOP_HANDLER) { @Override @@ -35,7 +35,7 @@ public void onServiceSelectionFailure(Throwable throwable) { }; @Override - public StorkObservationPoints create(String serviceName, String serviceDiscoveryType, + public StorkObservation create(String serviceName, String serviceDiscoveryType, String serviceSelectionType) { return NOOP_STORK_EVENT; } diff --git a/api/src/main/java/io/smallrye/stork/api/observability/ObservationCollector.java b/api/src/main/java/io/smallrye/stork/api/observability/ObservationCollector.java index f0e482b1..7b3b1223 100644 --- a/api/src/main/java/io/smallrye/stork/api/observability/ObservationCollector.java +++ b/api/src/main/java/io/smallrye/stork/api/observability/ObservationCollector.java @@ -2,6 +2,6 @@ public interface ObservationCollector { - StorkObservationPoints create(String serviceName, String serviceDiscoveryType, String serviceSelectionType); + StorkObservation create(String serviceName, String serviceDiscoveryType, String serviceSelectionType); } diff --git a/api/src/main/java/io/smallrye/stork/api/observability/ObservationPoints.java b/api/src/main/java/io/smallrye/stork/api/observability/ObservationPoints.java deleted file mode 100644 index e69de29b..00000000 diff --git a/api/src/main/java/io/smallrye/stork/api/observability/StorkEventHandler.java b/api/src/main/java/io/smallrye/stork/api/observability/StorkEventHandler.java index 54f42d76..2b6470a2 100644 --- a/api/src/main/java/io/smallrye/stork/api/observability/StorkEventHandler.java +++ b/api/src/main/java/io/smallrye/stork/api/observability/StorkEventHandler.java @@ -1,5 +1,5 @@ package io.smallrye.stork.api.observability; public interface StorkEventHandler { - void complete(StorkObservationPoints event); + void complete(StorkObservation event); } diff --git a/api/src/main/java/io/smallrye/stork/api/observability/StorkObservationPoints.java b/api/src/main/java/io/smallrye/stork/api/observability/StorkObservation.java similarity index 93% rename from api/src/main/java/io/smallrye/stork/api/observability/StorkObservationPoints.java rename to api/src/main/java/io/smallrye/stork/api/observability/StorkObservation.java index 9812b5a4..a0d0ac91 100644 --- a/api/src/main/java/io/smallrye/stork/api/observability/StorkObservationPoints.java +++ b/api/src/main/java/io/smallrye/stork/api/observability/StorkObservation.java @@ -5,7 +5,7 @@ import io.smallrye.stork.api.ServiceInstance; -public class StorkObservationPoints { +public class StorkObservation { // Handler / Reporter private final StorkEventHandler handler; @@ -30,7 +30,7 @@ public class StorkObservationPoints { private volatile boolean serviceDiscoverySuccessful = false; private volatile Throwable failure; - public StorkObservationPoints(String serviceName, String serviceDiscoveryType, String serviceSelectionType, + public StorkObservation(String serviceName, String serviceDiscoveryType, String serviceSelectionType, StorkEventHandler handler) { this.handler = handler; this.serviceName = serviceName; @@ -111,10 +111,6 @@ public Throwable failure() { return failure; } - public long getSelectedInstanceId() { - return selectedInstanceId; - } - public boolean isServiceDiscoverySuccessful() { return serviceDiscoverySuccessful; } diff --git a/core/src/test/java/io/smallrye/stork/FakeObservationCollector.java b/core/src/test/java/io/smallrye/stork/FakeObservationCollector.java index e12fd8f0..ec345571 100644 --- a/core/src/test/java/io/smallrye/stork/FakeObservationCollector.java +++ b/core/src/test/java/io/smallrye/stork/FakeObservationCollector.java @@ -2,19 +2,20 @@ import io.smallrye.stork.api.observability.ObservationCollector; import io.smallrye.stork.api.observability.StorkEventHandler; -import io.smallrye.stork.api.observability.StorkObservationPoints; +import io.smallrye.stork.api.observability.StorkObservation; public class FakeObservationCollector implements ObservationCollector { private static final StorkEventHandler FAKE_HANDLER = ev -> { // FAKE }; - public static StorkObservationPoints FAKE_STORK_EVENT; + + public static StorkObservation FAKE_STORK_EVENT; @Override - public StorkObservationPoints create(String serviceName, String serviceDiscoveryType, + public StorkObservation create(String serviceName, String serviceDiscoveryType, String serviceSelectionType) { - FAKE_STORK_EVENT = new StorkObservationPoints( + FAKE_STORK_EVENT = new StorkObservation( serviceName, serviceDiscoveryType, serviceSelectionType, FAKE_HANDLER); return FAKE_STORK_EVENT; diff --git a/core/src/test/java/io/smallrye/stork/ObservationTest.java b/core/src/test/java/io/smallrye/stork/ObservationTest.java index 24b37d0f..ade7e662 100644 --- a/core/src/test/java/io/smallrye/stork/ObservationTest.java +++ b/core/src/test/java/io/smallrye/stork/ObservationTest.java @@ -20,7 +20,7 @@ import io.smallrye.stork.api.NoServiceInstanceFoundException; import io.smallrye.stork.api.Service; import io.smallrye.stork.api.ServiceInstance; -import io.smallrye.stork.api.observability.StorkObservationPoints; +import io.smallrye.stork.api.observability.StorkObservation; import io.smallrye.stork.integration.ObservableStorkInfrastructure; import io.smallrye.stork.spi.config.ConfigProvider; @@ -60,12 +60,11 @@ void shouldGetMetricsWhenSelectingInstanceHappyPath() { //One instance is found and metrics are also gathered accordingly assertThat(service.getObservations()).isNotNull(); - StorkObservationPoints metrics = FakeObservationCollector.FAKE_STORK_EVENT; + StorkObservation metrics = FakeObservationCollector.FAKE_STORK_EVENT; assertThat(metrics.getServiceName()).isEqualTo("my-service"); assertThat(metrics.isDone()).isTrue(); assertThat(metrics.failure()).isNull(); assertThat(metrics.getDiscoveredInstancesCount()).isEqualTo(1); - assertThat(metrics.getSelectedInstanceId()).isNotNegative(); assertThat(metrics.isServiceDiscoverySuccessful()).isTrue(); assertThat(metrics.getServiceDiscoveryType()).isEqualTo("fake"); assertThat(metrics.getServiceSelectionType()).isEqualTo("round-robin"); @@ -74,7 +73,7 @@ void shouldGetMetricsWhenSelectingInstanceHappyPath() { } - private static void assertDurations(StorkObservationPoints metrics) { + private static void assertDurations(StorkObservation metrics) { Duration overallDuration = metrics.getOverallDuration(); Duration serviceDiscoveryDuration = metrics.getServiceDiscoveryDuration(); Duration serviceSelectionDuration = metrics.getServiceSelectionDuration(); @@ -108,12 +107,11 @@ void shouldGetMetricsAfterSelectingInstanceWhenServiceDiscoveryFails() { assertThat(exception.getMessage()).isEqualTo("Service Discovery induced failure"); assertThat(service.getObservations()).isNotNull(); - StorkObservationPoints metrics = FakeObservationCollector.FAKE_STORK_EVENT; + StorkObservation metrics = FakeObservationCollector.FAKE_STORK_EVENT; assertThat(metrics.getServiceName()).isEqualTo("my-service"); assertThat(metrics.isDone()).isTrue(); assertThat(metrics.failure()).isEqualTo(exception); assertThat(metrics.getDiscoveredInstancesCount()).isEqualTo(-1); - assertThat(metrics.getSelectedInstanceId()).isEqualTo(-1); assertThat(metrics.isServiceDiscoverySuccessful()).isFalse(); assertThat(metrics.getServiceDiscoveryType()).isEqualTo("mock"); assertThat(metrics.getServiceSelectionType()).isEqualTo("round-robin"); @@ -144,12 +142,11 @@ void shouldGetMetricsWhenSelectingInstanceFails() { assertThat(exception.getMessage()).isEqualTo("Load Balancer induced failure"); assertThat(service.getObservations()).isNotNull(); - StorkObservationPoints metrics = FakeObservationCollector.FAKE_STORK_EVENT; + StorkObservation metrics = FakeObservationCollector.FAKE_STORK_EVENT; assertThat(metrics.getServiceName()).isEqualTo("my-service"); assertThat(metrics.isDone()).isTrue(); assertThat(metrics.failure()).isEqualTo(exception); assertThat(metrics.getDiscoveredInstancesCount()).isEqualTo(1); - assertThat(metrics.getSelectedInstanceId()).isEqualTo(-1); assertThat(metrics.isServiceDiscoverySuccessful()).isTrue(); assertThat(metrics.getServiceDiscoveryType()).isEqualTo("fake"); assertThat(metrics.getServiceSelectionType()).isEqualTo("fake-selector"); @@ -158,7 +155,7 @@ void shouldGetMetricsWhenSelectingInstanceFails() { } @Test - void shouldGetMetricsAfterSelectingInstanceWhenWhenNoServicesDiscovered() { + void shouldGetMetricsAfterSelectingInstanceWhenNoServicesDiscovered() { TestEnv.configurations.add(new FakeServiceConfig("my-service", FAKE_SERVICE_DISCOVERY_CONFIG, null, null)); @@ -172,13 +169,12 @@ void shouldGetMetricsAfterSelectingInstanceWhenWhenNoServicesDiscovered() { assertThat(service.getObservations()).isNotNull(); - StorkObservationPoints metrics = FakeObservationCollector.FAKE_STORK_EVENT; + StorkObservation metrics = FakeObservationCollector.FAKE_STORK_EVENT; assertThat(metrics.getServiceName()).isEqualTo("my-service"); assertThat(metrics.isDone()).isTrue(); assertThat(metrics.failure()).isNotNull(); assertThat(metrics.failure()).isEqualTo(exception); assertThat(metrics.getDiscoveredInstancesCount()).isEqualTo(0); - assertThat(metrics.getSelectedInstanceId()).isEqualTo(-1); assertThat(metrics.isServiceDiscoverySuccessful()).isTrue(); assertThat(metrics.getServiceDiscoveryType()).isEqualTo("fake"); assertThat(metrics.getServiceSelectionType()).isEqualTo("round-robin"); @@ -201,13 +197,12 @@ void shouldGetMetricsWhenSelectingInstanceWithRecordAndStartHappyPath() { assertThat(service.selectInstanceAndRecordStart(true).await().indefinitely()).isEqualTo(instance); assertThat(service.getObservations()).isNotNull(); - StorkObservationPoints metrics = FakeObservationCollector.FAKE_STORK_EVENT; + StorkObservation metrics = FakeObservationCollector.FAKE_STORK_EVENT; assertThat(metrics.getServiceName()).isEqualTo("my-service"); assertThat(metrics.isDone()).isTrue(); assertThat(metrics.failure()).isNull(); assertThat(metrics.getOverallDuration()).isNotNull(); assertThat(metrics.getDiscoveredInstancesCount()).isEqualTo(1); - assertThat(metrics.getSelectedInstanceId()).isNotNegative(); assertThat(metrics.isServiceDiscoverySuccessful()).isTrue(); assertThat(metrics.getServiceDiscoveryType()).isEqualTo("fake"); assertThat(metrics.getServiceSelectionType()).isEqualTo("round-robin"); @@ -236,12 +231,11 @@ void shouldGetMetricsAfterSelectingInstanceWithMonitoringWhenServiceDiscoveryFai assertThat(exception.getMessage()).isEqualTo("Service Discovery induced failure"); assertThat(service.getObservations()).isNotNull(); - StorkObservationPoints metrics = FakeObservationCollector.FAKE_STORK_EVENT; + StorkObservation metrics = FakeObservationCollector.FAKE_STORK_EVENT; assertThat(metrics.getServiceName()).isEqualTo("my-service"); assertThat(metrics.isDone()).isTrue(); assertThat(metrics.failure()).isEqualTo(exception); assertThat(metrics.getDiscoveredInstancesCount()).isEqualTo(-1); - assertThat(metrics.getSelectedInstanceId()).isEqualTo(-1); assertThat(metrics.isServiceDiscoverySuccessful()).isFalse(); assertThat(metrics.getServiceDiscoveryType()).isEqualTo("mock"); assertThat(metrics.getServiceSelectionType()).isEqualTo("round-robin"); @@ -272,12 +266,11 @@ void shouldGetMetricsWhenSelectingInstanceWithMonitoringFails() { assertThat(exception.getMessage()).isEqualTo("Load Balancer induced failure"); assertThat(service.getObservations()).isNotNull(); - StorkObservationPoints metrics = FakeObservationCollector.FAKE_STORK_EVENT; + StorkObservation metrics = FakeObservationCollector.FAKE_STORK_EVENT; assertThat(metrics.getServiceName()).isEqualTo("my-service"); assertThat(metrics.isDone()).isTrue(); assertThat(metrics.failure()).isEqualTo(exception); assertThat(metrics.getDiscoveredInstancesCount()).isEqualTo(1); - assertThat(metrics.getSelectedInstanceId()).isEqualTo(-1); assertThat(metrics.isServiceDiscoverySuccessful()).isTrue(); assertThat(metrics.getServiceDiscoveryType()).isEqualTo("fake"); assertThat(metrics.getServiceSelectionType()).isEqualTo("fake-selector"); @@ -300,13 +293,12 @@ void shouldGetMetricsAfterSelectingInstanceWithMonitoringWhenWhenNoServicesDisco assertThat(service.getObservations()).isNotNull(); - StorkObservationPoints metrics = FakeObservationCollector.FAKE_STORK_EVENT; + StorkObservation metrics = FakeObservationCollector.FAKE_STORK_EVENT; assertThat(metrics.getServiceName()).isEqualTo("my-service"); assertThat(metrics.isDone()).isTrue(); assertThat(metrics.failure()).isNotNull(); assertThat(metrics.failure()).isEqualTo(exception); assertThat(metrics.getDiscoveredInstancesCount()).isEqualTo(0); - assertThat(metrics.getSelectedInstanceId()).isEqualTo(-1); assertThat(metrics.isServiceDiscoverySuccessful()).isTrue(); assertThat(metrics.getServiceDiscoveryType()).isEqualTo("fake"); assertThat(metrics.getServiceSelectionType()).isEqualTo("round-robin"); @@ -315,7 +307,8 @@ void shouldGetMetricsAfterSelectingInstanceWithMonitoringWhenWhenNoServicesDisco } private static Stork getNewObservableStork() { - return new Stork(new ObservableStorkInfrastructure(new FakeObservationCollector())); + Stork.initialize(new ObservableStorkInfrastructure(new FakeObservationCollector())); + return Stork.getInstance(); } } diff --git a/docs/docs/diagrams/observability_sequence.puml b/docs/docs/diagrams/observability_sequence.puml new file mode 100644 index 00000000..43b65234 --- /dev/null +++ b/docs/docs/diagrams/observability_sequence.puml @@ -0,0 +1,24 @@ +@startuml + +!include diagrams/includes/themes/light.puml + +skinparam sequenceMessageAlign center +autonumber "(0)" + + +participant Application +participant ObservableStorkInfrastructure +participant ObservationCollector +participant Stork +participant Service + +Application -> ObservableStorkInfrastructure : instantiates +ObservableStorkInfrastructure -> ObservationCollector : instantiates +ObservationCollector -> ObservableStorkInfrastructure: ObservationCollector +ObservableStorkInfrastructure -> Application: ObservableStorkInfrastructure + +... ... + +Application -> Stork : initialize(observableInfrastructure) +Stork -> Service : instantiates (..., ObservationCollector, ...) +@enduml \ No newline at end of file diff --git a/docs/docs/diagrams/observation_sequence.puml b/docs/docs/diagrams/observation_sequence.puml new file mode 100644 index 00000000..18257e3c --- /dev/null +++ b/docs/docs/diagrams/observation_sequence.puml @@ -0,0 +1,37 @@ +@startuml + +!include diagrams/includes/themes/light.puml + +skinparam sequenceMessageAlign center +autonumber "(0)" + + +participant Service +participant ObservationCollector +participant StorkObservation +participant StorkEventHandler + +Service -> ObservationCollector : create("serviceName", sd type, ss type) +ObservationCollector -> StorkObservation : instantiates +StorkObservation -> StorkObservation: Registers start time +ObservationCollector -> Service : StorkObservation + +... ... + +Service -> StorkObservation : onServiceDiscoverySuccess(List) +StorkObservation -> StorkObservation : Registers end service\ndiscovery time.\nRegisters instances count\n +... ... + +Service -> StorkObservation : onServiceDiscoveryFailure(Throwable) +StorkObservation -> StorkObservation : Registers end service\ndiscovery time.\nRegisters failure cause\n +... ... + +Service -> StorkObservation : onServiceSelectionSuccess(instanceId) +StorkObservation -> StorkObservation : Registers end service\nselection time.\nRegisters instance id\nRegisters overall duration\n +StorkObservation -> StorkEventHandler: complete(this) +... ... + +Service -> StorkObservation : onServiceSelectionFailure(Throwable)) +StorkObservation -> StorkObservation : Registers overall duration.\nRegisters failure cause\n +StorkObservation -> StorkEventHandler: complete(this) +@enduml \ No newline at end of file diff --git a/docs/docs/observability.md b/docs/docs/observability.md new file mode 100644 index 00000000..98498d07 --- /dev/null +++ b/docs/docs/observability.md @@ -0,0 +1,122 @@ +# Stork Observability API + +Stork proposes an observability API that automatically observes some parameters to show how the Stork service discovery and selection are behaving. + +For any _observation_ to happen, you need to provide your own implementation of an `ObservationCollector.` By default, Stork provides a no-op implementation. + +The `ObservationCollector` is responsible for instantiating the `StorkObservation`. + +The `StorkObservation` reacts to Stork events thanks to a `StorkEventHandler`. + +You can extend the metrics collection by extending the `StorkEventHandler` interface. + +The following sequence diagram shows how the observability is initialized : + + +![observability initialization](target/observability_sequence.svg#only-light) +![observability initialization](target/observability_sequence_dark.svg#only-dark) + + + +The `StorkObservation` registers times, number of discovered instances, the selected instance and failures by reacting to the lifecycle of a Stork event such as: + +- start : Observation has been started. +The beginning time is registered. +It happens when the `ObservationCollector#create()` method gets called. +- service discovery success: a collection of instances has been successfully discovered for a service. +The end discovery time and number of instances are recorded. +It happens when the `StorkObservation#onServiceDiscoverySuccess` gets called. +- service discovery error: an error occurs when discovering a service. +The end discovery time and failure cause are captured. +It happens when the `StorkObservation#onServiceDiscoveryFailure` gets called. +- service selection success: an instance has been successfully selected from the collection. +The end selection time and selected instance ID are registered. +It happens when the `StorkObservation#onServiceSelectionSuccess` gets called. +- service selection error: an error occurred during selecting the instance. +End selection time and failure cause are registered. +It happens when the `StorkObservation#onServiceSelectionFailure` gets called. +- end: Observation has finished. Overall duration is registered. +It happens when the `StorkObservation#onServiceSelectionSuccess` gets called. + +The following sequence diagram represents the described observation process above: + + + ![observation_process](target/observation_sequence.svg#only-light) + ![observation_process](target/observation_sequence_dark.svg#only-dark) + + + +## Implementing an observation collector + +An `ObservationCollector` implementation must override the `create` method to provide an instance of StorkObservation. +In addition, the user can access and enrich the observation data through the `StorkEventHandler`. + +A custom observation collector class should look as follows: + +```java linenums="1" +{{ insert('examples/AcmeObservationCollector.java') }} +``` + +The next step is to initialize Stork with an `ObservableStorkInfrastructure`, taking an instance of your `ObservationCollector` as parameter. + +```java linenums="1" +{{ insert('examples/ObservableInitializationExample.java') }} +``` + +Then, Stork uses your implementation to register metrics. + + +## Observing service discovery and selection behaviours + +To access metrics registered by `StorkObservation`, use the following code: + +```java linenums="1" +{{ insert('examples/ObservationExample.java') }} +``` + +# Stork Observability with Quarkus + +Stork metrics are automatically enabled when using Stork together with the Micrometer extension in a Quarkus application. + +Micrometer collects the metrics of the rest and grpc client using Stork, as well as when using the Stork API. + +As an example, if you export the metrics to Prometheus, you will get: + +````text +# HELP stork_load_balancer_failures_total The number of failures during service selection. +# TYPE stork_load_balancer_failures_total counter +stork_load_balancer_failures_total{service_name="hello-service",} 0.0 +# HELP stork_service_selection_duration_seconds The duration of the selection operation +# TYPE stork_service_selection_duration_seconds summary +stork_service_selection_duration_seconds_count{service_name="hello-service",} 13.0 +stork_service_selection_duration_seconds_sum{service_name="hello-service",} 0.001049291 +# HELP stork_service_selection_duration_seconds_max The duration of the selection operation +# TYPE stork_service_selection_duration_seconds_max gauge +stork_service_selection_duration_seconds_max{service_name="hello-service",} 0.0 +# HELP stork_overall_duration_seconds_max The total duration of the Stork service discovery and selection operations +# TYPE stork_overall_duration_seconds_max gauge +stork_overall_duration_seconds_max{service_name="hello-service",} 0.0 +# HELP stork_overall_duration_seconds The total duration of the Stork service discovery and selection operations +# TYPE stork_overall_duration_seconds summary +stork_overall_duration_seconds_count{service_name="hello-service",} 13.0 +stork_overall_duration_seconds_sum{service_name="hello-service",} 0.001049291 +# HELP stork_service_discovery_failures_total The number of failures during service discovery +# TYPE stork_service_discovery_failures_total counter +stork_service_discovery_failures_total{service_name="hello-service",} 0.0 +# HELP stork_service_discovery_duration_seconds_max The duration of the discovery operation +# TYPE stork_service_discovery_duration_seconds_max gauge +stork_service_discovery_duration_seconds_max{service_name="hello-service",} 0.0 +# HELP stork_service_discovery_duration_seconds The duration of the discovery operation +# TYPE stork_service_discovery_duration_seconds summary +stork_service_discovery_duration_seconds_count{service_name="hello-service",} 13.0 +stork_service_discovery_duration_seconds_sum{service_name="hello-service",} 6.585046209 +# HELP stork_instances_count_total The number of service instances discovered +# TYPE stork_instances_count_total counter +stork_instances_count_total{service_name="hello-service",} 26.0 +```` + + + + + + diff --git a/docs/mkdocs-customizations/macros/__pycache__/docissimo.cpython-310.pyc b/docs/mkdocs-customizations/macros/__pycache__/docissimo.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..01bd9a7a1d838833a3d9f9cf2d6f9a07654aabee GIT binary patch literal 4075 zcmb7HTW{OQ6(%W?lIdK$X?D}JMKEyCl?B99k`0=|QH(COF&0JR2J38rDo8Dw9NA2G z(awyVNS4|~lSTKX?*)n!@#FrCzV;^&eJfBPe<2UuerHHawl`=|+A~AWoO5R8obOze zpFQgtc>eMGzlDE2Zy5iikK>PpkDsB*pQ4M5t`V7$m6%;qk5<>xW35}$quq6)T4cX8 zx^Cn|F2;IfZ5ge4@Gr+OynBJ<kR8{!Pq4 zT~BzZRx3GctO@2@{`J+Z&5s{!efq11O%Ta6ND?vPt2jzO-aSTq)4%OsZ|ZY-zsZL< zK*oYF$6gmQbTp?r22eHZU~Im1)cLO5FLQH0hPfCp1=y=g*Z0NY8T%Y!3n~ z6Od&)9j(q6G!{y=0B8>aq2i!|P@ILyFyg161_kHOB+fyLq_F{b2RIsVfTlUY0%aHVM~UP%EZWczs>!P(<% zWee_|?LK-Oh+Ww_(4^!nTO+A>>gPk{4?v)jY-M?r=X-g++`6Nwrn9YQn)1A37p1TQ zLm^(_FoGx8cON$?y=pT_4g0Tni@8QF#vXLiaEZ*+KMqkJfiG+8=qDe}Jp;(vqT4HAX18JaXykByPq zCus6ZbQ9wV63JyFvMw1@Gpga++&9E~G)A?{m{Zo1+G~4a9-87O%9)ri%&Dc^C-n*S zjmZ9!HLXpo*9(V+X-sO7F*L<3jLv0}ZAMN9$!beCipQlBlrr0nZAX@=sw?CM>*-VUkn_aKa>)yl^ynTXs=HVi64} zwXg}9MGd0AF~s*U^Y+*6&yfj{u7)CRf09SMJqzk2cXcO7f-K~sUB)t#B9 z3>egEXz~F%WqhrT^EDaI`=im<^~K8tnBCNKx~d=$=&wah;YM{$QNx@SHKK)=kTJE% z@U1hOA(bvi59!B6Bdy54qXUaZ;M9t=NTBb$7Ht82ma-;RRJ#N$5oUli69_ZJ%B1$X zc4$m(j5Z-pIj`M`eP{w{_SA`-sXM9t+<1ItTAw)b?i_cMI^=hv#?<-3j~0&5sAoSV z&M*9lJE`9`rY_zp*%Md(R@EbKV*bU57AFS!Gq0Q%<{wPGt9xi-Hy2kuyD8|Z-Nj=O z;H}x-D2%se=dHQ^aBOwj^3RDG~b%dRzr|Q1Zhc7O<3512az~O zuMLGX_)G+Y!i{)@3Z_`N_dMhSD&fHR9?{ew5j=UW3bS9>#L+z;XP@yf7nIxX1Ac`W z0@27d-FHX?h7i^T4hQE40R(nsf61f?ab0WdZ2W?ME!8^E$n>&qq6H9f4^<_8#U zbNmD3e8}B~Gx#0Kfr(uAOOYplK$@zfZP7m8M;Dn|wU$;h3=K8guj){%vpK%kDJz9C zG2LCB`M@zXYz2uXfsV-jgTQE2xInwJlm!8A==#tAv;4 zncK*TQzY%*k?IH*mSw@eb+a1(9$$W^35a7OBu77b2w@9o+84)oAzy^sBOg#q*Pcec zi0nYVII-mW3f@S_pVZ`K_zUvIYsC7yzM!x;cKkh+CT}Pw0#reTr{)Yq$MIC{-eh}%_wP3Mlp4sjcDtJP4;DaOxdEp8e%Xj&Mde-V&ON{)##N;k)c#ai56(qy{>z_Q4ByfzgaZ z`eljVmR}+L!!Wfm`;61+IBH?3OF6beKe2`={6vT!lC8}*-{L`PcJv%x%;%>O3sq<# zf2Pxu?_a3B`NRC*QvWjomQAuosMSS zTo;e9Ea{erRu-by6)4Zec;TEWZezODDC*nWgrDugPEiMlMH2WUblrL`eJTwEg)E&$ hHOsME&JES*q { + //This is the terminal event. Put here your custom logic to extend the metrics collection. + + //E.g. Expose metrics to Micrometer, additional logs.... + LOGGER.info( "Service discovery took " + event.getServiceDiscoveryDuration() + "."); + LOGGER.info( event.getDiscoveredInstancesCount() + " have been discovered for " + event.getServiceName() + "."); + LOGGER.info( "Service selection took " + event.getServiceSelectionDuration() + "."); + + // ... + + }; + + public static StorkObservation ACME_STORK_EVENT; + + @Override + public StorkObservation create(String serviceName, String serviceDiscoveryType, + String serviceSelectionType) { + ACME_STORK_EVENT = new StorkObservation( + serviceName, serviceDiscoveryType, serviceSelectionType, + ACME_HANDLER); + return ACME_STORK_EVENT; + } +} diff --git a/docs/snippets/examples/ObservableInitializationExample.java b/docs/snippets/examples/ObservableInitializationExample.java new file mode 100644 index 00000000..d1885429 --- /dev/null +++ b/docs/snippets/examples/ObservableInitializationExample.java @@ -0,0 +1,13 @@ +package examples; + +import io.smallrye.stork.Stork; +import io.smallrye.stork.integration.ObservableStorkInfrastructure; + +public class ObservableInitializationExample { + + public static void main(String[] args) { + Stork.initialize(new ObservableStorkInfrastructure(new AcmeObservationCollector())); + Stork stork = Stork.getInstance(); + // ... + } +} diff --git a/docs/snippets/examples/ObservationExample.java b/docs/snippets/examples/ObservationExample.java new file mode 100644 index 00000000..299fc5b4 --- /dev/null +++ b/docs/snippets/examples/ObservationExample.java @@ -0,0 +1,35 @@ +package examples; + +import io.smallrye.mutiny.Uni; +import io.smallrye.stork.Stork; +import io.smallrye.stork.api.Service; +import io.smallrye.stork.api.ServiceInstance; +import io.smallrye.stork.api.observability.ObservationCollector; +import io.smallrye.stork.api.observability.StorkObservation; + +import java.time.Duration; +import java.util.List; +import java.util.Map; + +import static examples.AcmeObservationCollector.*; + +public class ObservationExample { + + public static void example(Stork stork) { + Service service = stork.getService("my-service"); + + ObservationCollector observations = service.getObservations(); + + // Gets the time spent in service discovery and service selection even if any error happens + Duration overallDuration = ACME_STORK_EVENT.getOverallDuration(); + + // Gets the total number of instances discovered + int discoveredInstancesCount = ACME_STORK_EVENT.getDiscoveredInstancesCount(); + + // Gets the error raised during the process + Throwable failure = ACME_STORK_EVENT.failure(); + + // ... + + } +}