From bb446cb57972dc2770b8066dd19b6c8f3768bc88 Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Thu, 7 Jun 2018 11:57:55 -0400 Subject: [PATCH] Removes atlas starter and docs fixes gh-2997 --- .../main/asciidoc/spring-cloud-netflix.adoc | 279 ------------------ spring-cloud-netflix-dependencies/pom.xml | 5 - spring-cloud-starter-netflix/pom.xml | 1 - .../pom.xml | 35 --- .../resources/META-INF/spring.provides | 1 - 5 files changed, 321 deletions(-) delete mode 100644 spring-cloud-starter-netflix/spring-cloud-starter-netflix-atlas/pom.xml delete mode 100644 spring-cloud-starter-netflix/spring-cloud-starter-netflix-atlas/src/main/resources/resources/META-INF/spring.provides diff --git a/docs/src/main/asciidoc/spring-cloud-netflix.adoc b/docs/src/main/asciidoc/spring-cloud-netflix.adoc index 37a505e11..3cb32505f 100644 --- a/docs/src/main/asciidoc/spring-cloud-netflix.adoc +++ b/docs/src/main/asciidoc/spring-cloud-netflix.adoc @@ -1968,285 +1968,6 @@ info: url: https://github.com/spring-cloud-samples ---- -[[netflix-metrics]] -== Metrics: Spectator, Servo, and Atlas - -When used together, Spectator (or Servo) and Atlas provide a near real-time operational insight platform. -Spectator and Servo are Netflix's metrics collection libraries. -Atlas is a Netflix metrics backend that manages dimensional time-series data. - -Servo served Netflix for several years and is still usable but is gradually being phased out in favor of Spectator, which is designed to work only with Java 8. -Spring Cloud Netflix provides support for both, but Java 8-based applications are encouraged to use Spectator. - -=== Dimensional Versus Hierarchical Metrics - -Spring Boot Actuator metrics are hierarchical, and the metrics are separated only by name. -These names often follow a naming convention that embeds key/value attribute pairs (dimensions) into the name (separated by periods). -Consider the following metrics for two endpoints, `root` and `star-star`: - -[source,json] ----- -{ - "counter.status.200.root": 20, - "counter.status.400.root": 3, - "counter.status.200.star-star": 5, -} ----- - -The first metric gives us a normalized count of successful requests against the root endpoint per unit of time. -But what if the system has 20 endpoints and you want to get a count of successful requests against all the endpoints? -Some hierarchical metrics backends would let you specify a wildcard, such as `counter.status.200.\*`, that would read all 20 metrics and aggregate the results. -Alternatively, you could provide a `HandlerInterceptorAdapter` that intercepts and records a metric such as `counter.status.200.all` for all successful requests irrespective of the endpoint, but now you must write 20+1 different metrics. -Similarly, if you want to know the total number of successful requests for all endpoints in the service, you could specify a wildcard such as `counter.status.2*.*`. - -Even in the presence of wildcarding support on a hierarchical metrics backend, naming consistency can be difficult. -Specifically, the position of these tags in the name string can slip with time, breaking queries. -For example, suppose we add an additional dimension to the earlier hierarchical metrics for an HTTP method. -Then `counter.status.200.root` becomes `counter.status.200.method.get.root` (or `post` and so on). -Suddenly, Our `counter.status.200.*` no longer has the same semantic meaning. -Furthermore, if the new dimension is not applied uniformly across the codebase, certain queries may become impossible. -This can quickly get out of hand. - -Netflix metrics are tagged (in other words, they are dimensional). -Each metric has a name, but this single named metric can contain multiple statistics and 'tag' key/value pairs, which allows more querying flexibility. -In fact, the statistics themselves are recorded in a special tag. - -When recorded with Netflix Servo or Spectator, a timer for the root endpoint described earlier contains four statistics for each status code, where the count statistic is identical to Spring Boot Actuator's counter. -When we have encountered an HTTP 200 and 400 with the preceding examples, there are eight available data points, as shown in the following example: - -[source,json] ----- -{ - "root(status=200,stastic=count)": 20, - "root(status=200,stastic=max)": 0.7265630630000001, - "root(status=200,stastic=totalOfSquares)": 0.04759702862580789, - "root(status=200,stastic=totalTime)": 0.2093076914666667, - "root(status=400,stastic=count)": 1, - "root(status=400,stastic=max)": 0, - "root(status=400,stastic=totalOfSquares)": 0, - "root(status=400,stastic=totalTime)": 0, -} ----- - -=== Default Metrics Collection - -Without any additional dependencies or configuration, a Spring Cloud based service autoconfigures a Servo `MonitorRegistry` and begins collecting metrics on every Spring MVC request. -By default, a Servo timer with a name of `rest` is recorded for each MVC request, which is tagged with the following information: - -* HTTP method (`GET`, `POST`, and so on). -* HTTP status (`200`, `400`, `500`, and so on). -* URI (or `root` if the URI is empty), sanitized for Atlas. -* The exception class name, if the request handler threw an exception. -* The caller, if a request header with a key matching `netflix.metrics.rest.callerHeader` is set on the request. -There is no default key for `netflix.metrics.rest.callerHeader`. -You must add it to your application properties if you wish to collect caller information. - -Set the `netflix.metrics.rest.metricName` property to change the name of the metric from `rest` to the name you provide. - -If Spring AOP is enabled and `org.aspectj:aspectjweaver` is present on your runtime classpath, Spring Cloud also collects metrics on every client call made with `RestTemplate`. -A Servo timer with a name of `restclient` is recorded for each MVC request, which is tagged with the following information: - -* HTTP method ('GET', 'POST', and so on). -* HTTP status (`200`, `400`, `500`, and so on) and possibly `CLIENT_ERROR` if the response returned null or `IO_ERROR` if an `IOException` occurred during the execution of the `RestTemplate` method. -* URI, sanitized for Atlas. -* Client name. - -WARNING: Avoid using hard-coded URL parameters within `RestTemplate`. -When targeting dynamic endpoints, use URL variables. -Doing so avoids potential "`GC Overhead Limit Reached`" issues where `ServoMonitorCache` treats each URL as a unique key. -The following example shows both the recommended and the problematic ways to set URL parameters: - -[source,java,indent=0] ----- -// recommended -String orderid = "1"; -restTemplate.getForObject("http://testeurekabrixtonclient/orders/{orderid}", String.class, orderid) - -// avoid -restTemplate.getForObject("http://testeurekabrixtonclient/orders/1", String.class) ----- - -[[netflix-metrics-spectator]] -=== Metrics Collection: Spectator - -To enable Spectator metrics, include a dependency on `spring-boot-starter-spectator`, as follows: - -[source,xml] ----- - - org.springframework.cloud - spring-cloud-starter-netflix-spectator - ----- - -In Spectator parlance, a meter is a named, typed, and tagged configuration, while a metric represents the value of a given meter at a point in time. -Spectator meters are created and controlled by a registry, which currently has several different implementations. -Spectator provides four meter types: counter, timer, gauge, and distribution summary. - -Spring Cloud Spectator integration configures an injectable `com.netflix.spectator.api.Registry` instance for you. -Specifically, it configures a `ServoRegistry` instance in order to unify the collection of REST metrics and the exporting of metrics to the Atlas backend under a single Servo API. -Practically, this means that your code may use a mixture of Servo monitors and Spectator meters. -Spring Boot scoops up both Actuator `MetricReader` instances and ships them to the Atlas backend. - -==== Spectator Counter - -A counter measures the rate at which some event is occurring, as shown in the following example: - -[source,java] ----- -// create a counter with a name and a set of tags -Counter counter = registry.counter("counterName", "tagKey1", "tagValue1", ...); -counter.increment(); // increment when an event occurs -counter.increment(10); // increment by a discrete amount ----- - -The counter records a single time-normalized statistic. - -==== Spectator Timer - -A timer measures how long some event takes. -Spring Cloud automatically records timers for Spring MVC requests and, conditionally, `RestTemplate` requests, which can later be used to create dashboards for request related metrics like latency, as shown in the following example: - -.Request Latency -image::https://raw.githubusercontent.com/spring-cloud/spring-cloud-netflix/{branch}/docs/src/main/asciidoc/images/RequestLatency.png[] - -[source,java] ----- -// create a timer with a name and a set of tags -Timer timer = registry.timer("timerName", "tagKey1", "tagValue1", ...); - -// execute an operation and time it at the same time -T result = timer.record(() -> fooReturnsT()); - -// alternatively, if you must manually record the time -Long start = System.nanoTime(); -T result = fooReturnsT(); -timer.record(System.nanoTime() - start, TimeUnit.NANOSECONDS); ----- - -The timer simultaneously records four statistics: `count`, `max`, `totalOfSquares`, and `totalTime`. -The count statistic always matches the single normalized value provided by a counter as though you had called `increment()` once on the counter for each time you recorded a timing, so it is rarely necessary to count and time separately for a single operation. - -For link:https://github.com/Netflix/spectator/wiki/Timer-Usage#longtasktimer[long-running operations], Spectator provides a special `LongTaskTimer`. - -==== Spectator Gauge - -Gauges show some current value, such as the size of a queue or number of threads in a running state. -Since gauges are sampled, they provide no information about how these values fluctuate between samples. - -The normal use of a gauge involves registering the gauge once on initialization with an ID, a reference to the object to be sampled, and a function to get or compute a numeric value based on the object. -The reference to the object is passed in separately, and the Spectator registry keeps a weak reference to the object. -If the object is garbage collected, Spectator automatically drops the registration. -See link:https://github.com/Netflix/spectator/wiki/Gauge-Usage#using-lambda[the note] in Spectator's documentation about potential memory leaks if this API is misused. -The following listing shows how to automatically and manually sample a gauge: - -[source,java] ----- -// the registry automatically samples this gauge periodically -registry.gauge("gaugeName", pool, Pool::numberOfRunningThreads); - -// manually sample a value in code at periodic intervals -- last resort! -registry.gauge("gaugeName", Arrays.asList("tagKey1", "tagValue1", ...), 1000); ----- - -// TODO Why is the manual way a last resort? - -==== Spectator Distribution Summaries - -A distribution summary tracks 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. -The following example defines a distribution summary: - -[source,java] ----- -// the registry automatically samples this gauge periodically -DistributionSummary ds = registry.distributionSummary("dsName", "tagKey1", "tagValue1", ...); -ds.record(request.sizeInBytes()); ----- - -[[netflix-metrics-servo]] -=== Metrics Collection: Servo - -NOTE: If your code is compiled on Java 8, use Spectator instead of Servo, as Spectator is destined to replace Servo entirely. - -In Servo parlance, a monitor is a named, typed, and tagged configuration, and a metric represents the value of a given monitor at a point in time. -Servo monitors are logically equivalent to Spectator meters. -Servo monitors are created and controlled by a `MonitorRegistry`. -While it is still available, Servo has a link:https://github.com/Netflix/servo/wiki/Getting-Started[wider array] of monitor options than Spectator has meters. - -Spring Cloud integration configures an injectable `com.netflix.servo.MonitorRegistry` instance for you. -Once you have created the appropriate `Monitor` type in Servo, the process of recording data is similar to that of Spectator. - -==== Creating Servo Monitors - -If you use the Servo `MonitorRegistry` instance provided by Spring Cloud (specifically, an instance of `DefaultMonitorRegistry`), Servo provides convenience classes for retrieving link:https://github.com/Netflix/spectator/wiki/Servo-Comparison#dynamiccounter[counters] and link:https://github.com/Netflix/spectator/wiki/Servo-Comparison#dynamictimer[timers]. -These convenience classes ensure that only one `Monitor` is registered for each unique combination of name and tags. - -To manually create a Monitor type in Servo, especially for the more exotic monitor types for which convenience methods are not provided, instantiate the appropriate type by providing a `MonitorConfig` instance, as shown in the following example: - -[source,java] ----- -MonitorConfig config = MonitorConfig.builder("timerName").withTag("tagKey1", "tagValue1").build(); - -// somewhere we should cache this Monitor by MonitorConfig -Timer timer = new BasicTimer(config); -monitorRegistry.register(timer); ----- - -[[netflix-metrics-atlas]] -== Metrics Backend: Atlas - -Atlas was developed by Netflix to manage dimensional time-series data for near real-time operational insight. -Atlas features in-memory data storage, letting it gather and report large numbers of metrics quickly. - -Atlas captures operational intelligence. -Whereas business intelligence is data gathered for analyzing trends over time, operational intelligence provides a picture of what is currently happening within a system. - -Spring Cloud provides a `spring-cloud-starter-netflix-atlas` that has all the dependencies you need. -Then you can annotate your Spring Boot application with `@EnableAtlas` and provide a location for your running Atlas server by setting the `netflix.atlas.uri` property. - -=== Global Tags - -Spring Cloud lets you add tags to every metric sent to the Atlas backend. -Global tags can be used to separate metrics by application name, environment, region, and so on. - -Each bean implementing `AtlasTagProvider` contributes to the global tag list, as shown in the following example: - -[source,java] ----- -@Bean -AtlasTagProvider atlasCommonTags( - @Value("${spring.application.name}") String appName) { - return () -> Collections.singletonMap("app", appName); -} ----- - -==== Using Atlas - -To bootstrap an in-memory standalone Atlas instance, use the following commands: - -[source,bash] ----- -$ curl -LO https://github.com/Netflix/atlas/releases/download/v1.4.2/atlas-1.4.2-standalone.jar -$ java -jar atlas-1.4.2-standalone.jar ----- - -TIP: An Atlas standalone node running on an r3.2xlarge (61GB RAM) can handle roughly 2 million metrics per minute for a given six-hour window. - -Once the application is running and you have collected a handful of metrics, you can verify that your setup is correct by listing tags on the Atlas server, as shown in the following example: - -[source,bash] ----- -$ curl http://ATLAS/api/v1/tags ----- - -TIP: After running several requests against your service, you can gather some basic information on the request latency of every request by pasting the following URL in your browser: `http://ATLAS/api/v1/graph?q=name,rest,:eq,:avg` - -The Atlas wiki contains a link:https://github.com/Netflix/atlas/wiki/Single-Line[compilation of sample queries] for various scenarios. - -See the link:https://github.com/Netflix/atlas/wiki/Alerting-Philosophy[alerting philosophy] and docs on using link:https://github.com/Netflix/atlas/wiki/DES[double exponential smoothing] to generate dynamic alert thresholds. - [[retrying-failed-requests]] == Retrying Failed Requests diff --git a/spring-cloud-netflix-dependencies/pom.xml b/spring-cloud-netflix-dependencies/pom.xml index 946e5d6c8..a866e3937 100644 --- a/spring-cloud-netflix-dependencies/pom.xml +++ b/spring-cloud-netflix-dependencies/pom.xml @@ -89,11 +89,6 @@ spring-cloud-starter-netflix-zuul ${project.version} - - org.springframework.cloud - spring-cloud-starter-netflix-atlas - ${project.version} - org.springframework.cloud spring-cloud-netflix-core diff --git a/spring-cloud-starter-netflix/pom.xml b/spring-cloud-starter-netflix/pom.xml index af07a910a..eec13b480 100644 --- a/spring-cloud-starter-netflix/pom.xml +++ b/spring-cloud-starter-netflix/pom.xml @@ -13,7 +13,6 @@ Spring Cloud Netflix Starters spring-cloud-starter-netflix-archaius - spring-cloud-starter-netflix-atlas spring-cloud-starter-netflix-eureka-client spring-cloud-starter-netflix-eureka-server spring-cloud-starter-netflix-hystrix diff --git a/spring-cloud-starter-netflix/spring-cloud-starter-netflix-atlas/pom.xml b/spring-cloud-starter-netflix/spring-cloud-starter-netflix-atlas/pom.xml deleted file mode 100644 index ad358c77a..000000000 --- a/spring-cloud-starter-netflix/spring-cloud-starter-netflix-atlas/pom.xml +++ /dev/null @@ -1,35 +0,0 @@ - - 4.0.0 - - org.springframework.cloud - spring-cloud-starter-netflix - 2.0.0.BUILD-SNAPSHOT - - spring-cloud-starter-netflix-atlas - Spring Cloud Starter Netflix Atlas - Spring Cloud Starter Netflix Atlas - https://projects.spring.io/spring-cloud - - Pivotal Software, Inc. - https://www.spring.io - - - - org.springframework.cloud - spring-cloud-starter - - - org.springframework.cloud - spring-cloud-netflix-core - - - com.netflix.servo - servo-core - - - com.fasterxml.jackson.dataformat - jackson-dataformat-smile - - - \ No newline at end of file diff --git a/spring-cloud-starter-netflix/spring-cloud-starter-netflix-atlas/src/main/resources/resources/META-INF/spring.provides b/spring-cloud-starter-netflix/spring-cloud-starter-netflix-atlas/src/main/resources/resources/META-INF/spring.provides deleted file mode 100644 index ef7cba083..000000000 --- a/spring-cloud-starter-netflix/spring-cloud-starter-netflix-atlas/src/main/resources/resources/META-INF/spring.provides +++ /dev/null @@ -1 +0,0 @@ -provides: spring-cloud-starter, spring-cloud-netflix-core, servo-core, jackson-dataformat-smile \ No newline at end of file