From 5c7eaaf7733ff46b6ba3f531118098fcb3c79a78 Mon Sep 17 00:00:00 2001 From: Umair Khan Date: Thu, 29 Aug 2024 14:54:47 -0700 Subject: [PATCH 1/9] Add new IPC tags from IPC Metrics v2 spec --- .../spectator/ipc/IpcAttemptReason.java | 44 +++++++++ .../netflix/spectator/ipc/IpcLogEntry.java | 46 +++++++++ .../com/netflix/spectator/ipc/IpcMethod.java | 94 +++++++++++++++++++ .../com/netflix/spectator/ipc/IpcMetric.java | 5 + .../com/netflix/spectator/ipc/IpcTagKey.java | 28 +++++- .../spectator/ipc/IpcLogEntryTest.java | 51 ++++++++++ 6 files changed, 266 insertions(+), 2 deletions(-) create mode 100644 spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcAttemptReason.java create mode 100644 spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcMethod.java diff --git a/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcAttemptReason.java b/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcAttemptReason.java new file mode 100644 index 000000000..296817d35 --- /dev/null +++ b/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcAttemptReason.java @@ -0,0 +1,44 @@ +/** + * Copyright 2024 Netflix, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.netflix.spectator.ipc; + +import com.netflix.spectator.api.Tag; + +public enum IpcAttemptReason implements Tag { + + /** + * Represents the initial attempt for the request. + */ + initial, + + /** + * Represents a retry attempt for the request. + */ + retry, + + /** + * Represents a hedge attempt for the request. + */ + hedge; + + @Override public String key() { + return IpcTagKey.attemptFinal.key(); + } + + @Override public String value() { + return name(); + } +} diff --git a/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcLogEntry.java b/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcLogEntry.java index 2f843b6e6..e90af1db9 100644 --- a/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcLogEntry.java +++ b/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcLogEntry.java @@ -56,14 +56,17 @@ public final class IpcLogEntry { private String protocol; private IpcStatus status; + private String statusCode; private String statusDetail; private Throwable exception; private IpcAttempt attempt; + private String attemptReason; private IpcAttemptFinal attemptFinal; private String vip; private String endpoint; + private String method; private String clientRegion; private String clientZone; @@ -217,6 +220,14 @@ public IpcLogEntry withStatus(IpcStatus status) { return this; } + /** + * Set the implementation specific status code for the request. + */ + public IpcLogEntry withStatusCode(String statusCode) { + this.statusCode = statusCode; + return this; + } + /** * Set the detailed implementation specific status for the request. In most cases it * is preferable to use {@link #withException(Throwable)} or {@link #withHttpStatus(int)} @@ -282,6 +293,22 @@ public IpcLogEntry withAttempt(int attempt) { return withAttempt(IpcAttempt.forAttemptNumber(attempt)); } + /** + * Set the reason for the attempt for the request. + * See {@link IpcAttemptReason} for possible values. + */ + public IpcLogEntry withAttemptReason(IpcAttemptReason attemptReason) { + return withAttemptReason(attemptReason.value()); + } + + /** + * Set the reason for the attempt for the request. + */ + public IpcLogEntry withAttemptReason(String attemptReason) { + this.attemptReason = attemptReason; + return this; + } + /** * Set whether or not this is the final attempt for the request. */ @@ -307,6 +334,22 @@ public IpcLogEntry withEndpoint(String endpoint) { return this; } + /** + * Set the method used for this request. + * See {@link IpcMethod} for possible values. + */ + public IpcLogEntry withMethod(IpcMethod method) { + return withMethod(method.value()); + } + + /** + * Set the method used for this request. + */ + public IpcLogEntry withMethod(String method) { + this.method = method; + return this; + } + /** * Set the client region for the request. In the case of the server side this will be * automatically filled in if the {@link NetflixHeader#Zone} is specified on the client @@ -899,6 +942,7 @@ public String toString() { .addField("protocol", protocol) .addField("uri", uri) .addField("path", path) + .addField("method", method) .addField("endpoint", endpoint) .addField("vip", vip) .addField("clientRegion", clientRegion) @@ -916,9 +960,11 @@ public String toString() { .addField("remoteAddress", remoteAddress) .addField("remotePort", remotePort) .addField("attempt", attempt) + .addField("attemptReason", attemptReason) .addField("attemptFinal", attemptFinal) .addField("result", result) .addField("status", status) + .addField("statusCode", statusCode) .addField("statusDetail", statusDetail) .addField("exceptionClass", getExceptionClass()) .addField("exceptionMessage", getExceptionMessage()) diff --git a/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcMethod.java b/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcMethod.java new file mode 100644 index 000000000..a43613cbc --- /dev/null +++ b/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcMethod.java @@ -0,0 +1,94 @@ +/** + * Copyright 2024 Netflix, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.netflix.spectator.ipc; + +import com.netflix.spectator.api.Tag; + +public enum IpcMethod implements Tag { + + /** + * Represents a unary gRPC method. + */ + unary, + + /** + * Represents a client streaming gRPC method. + */ + client_streaming, + + /** + * Represents a server streaming gRPC method. + */ + server_streaming, + + /** + * Represents a bidirectional streaming gRPC method. + */ + bidi_streaming, + + /** + * Represents an HTTP GET request. + */ + get, + + /** + * Represents an HTTP POST request. + */ + post, + + /** + * Represents an HTTP PUT request. + */ + put, + + /** + * Represents an HTTP PATCH request. + */ + patch, + + /** + * Represents an HTTP DELETE request. + */ + delete, + + /** + * Represents an HTTP OPTIONS request. + */ + options, + + /** + * Represents a GraphQL query. + */ + query, + + /** + * Represents a GraphQL mutation. + */ + mutation, + + /** + * Represents a GraphQL subscription. + */ + subscription; + + @Override public String key() { + return IpcTagKey.method.key(); + } + + @Override public String value() { + return name(); + } +} diff --git a/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcMetric.java b/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcMetric.java index a3c1ee98f..1de35180d 100644 --- a/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcMetric.java +++ b/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcMetric.java @@ -49,7 +49,9 @@ public enum IpcMetric { IpcTagKey.status ), EnumSet.of( + IpcTagKey.attemptReason, IpcTagKey.endpoint, + IpcTagKey.method, IpcTagKey.failureInjected, IpcTagKey.httpMethod, IpcTagKey.httpStatus, @@ -58,6 +60,7 @@ public enum IpcMetric { IpcTagKey.serverApp, IpcTagKey.serverCluster, IpcTagKey.serverAsg, + IpcTagKey.statusCode, IpcTagKey.statusDetail, IpcTagKey.vip ) @@ -75,6 +78,7 @@ public enum IpcMetric { ), EnumSet.of( IpcTagKey.endpoint, + IpcTagKey.method, IpcTagKey.clientApp, IpcTagKey.clientCluster, IpcTagKey.clientAsg, @@ -83,6 +87,7 @@ public enum IpcMetric { IpcTagKey.httpStatus, IpcTagKey.id, IpcTagKey.protocol, + IpcTagKey.statusCode, IpcTagKey.statusDetail, IpcTagKey.vip ) diff --git a/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcTagKey.java b/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcTagKey.java index 08d2280fa..bbfbcd186 100644 --- a/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcTagKey.java +++ b/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcTagKey.java @@ -32,6 +32,12 @@ public enum IpcTagKey { */ result("ipc.result"), + /** + * Indicates where the result was ultimately sourced from such as cache, direct, + * proxy, fallback, etc. + */ + source("ipc.source"), + /** * Dimension indicating a high level status for the request. These values are the same * for all implementations to make it easier to query across services. See {@link IpcStatus} @@ -39,10 +45,18 @@ public enum IpcTagKey { */ status("ipc.status"), + /** + * Dimension indicating the transport-specific code that aligns to the IPC status. + * The values for this are implementation specific. For example with HTTP, + * the status code value would be used here. + */ + statusCode("ipc.status.code"), + /** * Optional dimension indicating a more detailed status. The values for this are - * implementation specific. For example with HTTP, the status code would be a likely - * value used here. + * implementation specific. For example, the {@link #status} may be + * {@code connection_error} and {@code statusDetail} would be {@code no_servers}, + * {@code connect_timeout}, {@code ssl_handshake_failure}, etc. */ statusDetail("ipc.status.detail"), @@ -72,6 +86,11 @@ public enum IpcTagKey { */ attempt("ipc.attempt"), + /** + * Indicates the reason for the attempt. See {@link IpcAttemptReason} for possible values. + */ + attemptReason("ipc.attempt.reason"), + /** * Indicates if this is the final attempt for the request. For example, if the client * is configured to allow 1 retry, then the second attempt would be final. Acceptable @@ -103,6 +122,11 @@ public enum IpcTagKey { */ protocol("ipc.protocol"), + /** + * Method used to make the IPC request. See {@link IpcMethod} for possible values. + */ + method("ipc.method"), + /** * Region where the client is located. * diff --git a/spectator-ext-ipc/src/test/java/com/netflix/spectator/ipc/IpcLogEntryTest.java b/spectator-ext-ipc/src/test/java/com/netflix/spectator/ipc/IpcLogEntryTest.java index 526e05356..9267df758 100644 --- a/spectator-ext-ipc/src/test/java/com/netflix/spectator/ipc/IpcLogEntryTest.java +++ b/spectator-ext-ipc/src/test/java/com/netflix/spectator/ipc/IpcLogEntryTest.java @@ -146,6 +146,16 @@ public void status() { Assertions.assertEquals(expected, actual); } + @Test + public void statusCode() { + String expected = "deadline_exceeded"; + String actual = (String) entry + .withStatusCode(expected) + .convert(this::toMap) + .get("statusCode"); + Assertions.assertEquals(expected, actual); + } + @Test public void statusDetail() { String expected = "connection_failed"; @@ -188,6 +198,26 @@ public void attempt() { Assertions.assertEquals(expected, actual); } + @Test + public void attemptReason() { + String expected = IpcAttemptReason.retry.value(); + String actual = (String) entry + .withAttemptReason(IpcAttemptReason.retry) + .convert(this::toMap) + .get("attemptReason"); + Assertions.assertEquals(expected, actual); + } + + @Test + public void customAttemptReason() { + String expected = "unknown"; + String actual = (String) entry + .withAttemptReason(expected) + .convert(this::toMap) + .get("attemptReason"); + Assertions.assertEquals(expected, actual); + } + @Test public void attemptFinal() { String expected = IpcAttemptFinal.is_true.value(); @@ -239,6 +269,27 @@ public void endpointViaUri404() { Assertions.assertEquals("unknown", actual); } + @Test + public void method() { + String expected = IpcMethod.get.value(); + String actual = (String) entry + .withMethod(IpcMethod.get) + .convert(this::toMap) + .get("method"); + Assertions.assertEquals(expected, actual); + } + + @Test + public void customMethod() { + String expected = "websocket"; + String actual = (String) entry + .withMethod(expected) + .convert(this::toMap) + .get("method"); + Assertions.assertEquals(expected, actual); + } + + @Test public void clientNode() { String expected = "i-12345"; From 477741c04c1e3ef9c88b8d4c55447e4387f1c69d Mon Sep 17 00:00:00 2001 From: annieyang Date: Mon, 11 Nov 2024 15:08:33 -0800 Subject: [PATCH 2/9] Add new api metrics values --- .../spectator/ipc/IpcAttemptReason.java | 44 -------------- .../netflix/spectator/ipc/IpcLogEntry.java | 28 --------- .../com/netflix/spectator/ipc/IpcMetric.java | 3 - .../com/netflix/spectator/ipc/IpcSource.java | 60 +++++++++++++++++++ .../com/netflix/spectator/ipc/IpcStatus.java | 5 ++ .../com/netflix/spectator/ipc/IpcTagKey.java | 14 +---- .../spectator/ipc/IpcLogEntryTest.java | 30 ---------- 7 files changed, 66 insertions(+), 118 deletions(-) delete mode 100644 spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcAttemptReason.java create mode 100644 spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcSource.java diff --git a/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcAttemptReason.java b/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcAttemptReason.java deleted file mode 100644 index 296817d35..000000000 --- a/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcAttemptReason.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Copyright 2024 Netflix, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.netflix.spectator.ipc; - -import com.netflix.spectator.api.Tag; - -public enum IpcAttemptReason implements Tag { - - /** - * Represents the initial attempt for the request. - */ - initial, - - /** - * Represents a retry attempt for the request. - */ - retry, - - /** - * Represents a hedge attempt for the request. - */ - hedge; - - @Override public String key() { - return IpcTagKey.attemptFinal.key(); - } - - @Override public String value() { - return name(); - } -} diff --git a/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcLogEntry.java b/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcLogEntry.java index e55069d94..e49f7a891 100644 --- a/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcLogEntry.java +++ b/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcLogEntry.java @@ -56,12 +56,10 @@ public final class IpcLogEntry { private String protocol; private IpcStatus status; - private String statusCode; private String statusDetail; private Throwable exception; private IpcAttempt attempt; - private String attemptReason; private IpcAttemptFinal attemptFinal; private String vip; @@ -220,14 +218,6 @@ public IpcLogEntry withStatus(IpcStatus status) { return this; } - /** - * Set the implementation specific status code for the request. - */ - public IpcLogEntry withStatusCode(String statusCode) { - this.statusCode = statusCode; - return this; - } - /** * Set the detailed implementation specific status for the request. In most cases it * is preferable to use {@link #withException(Throwable)} or {@link #withHttpStatus(int)} @@ -293,22 +283,6 @@ public IpcLogEntry withAttempt(int attempt) { return withAttempt(IpcAttempt.forAttemptNumber(attempt)); } - /** - * Set the reason for the attempt for the request. - * See {@link IpcAttemptReason} for possible values. - */ - public IpcLogEntry withAttemptReason(IpcAttemptReason attemptReason) { - return withAttemptReason(attemptReason.value()); - } - - /** - * Set the reason for the attempt for the request. - */ - public IpcLogEntry withAttemptReason(String attemptReason) { - this.attemptReason = attemptReason; - return this; - } - /** * Set whether or not this is the final attempt for the request. */ @@ -960,11 +934,9 @@ public String toString() { .addField("remoteAddress", remoteAddress) .addField("remotePort", remotePort) .addField("attempt", attempt) - .addField("attemptReason", attemptReason) .addField("attemptFinal", attemptFinal) .addField("result", result) .addField("status", status) - .addField("statusCode", statusCode) .addField("statusDetail", statusDetail) .addField("exceptionClass", getExceptionClass()) .addField("exceptionMessage", getExceptionMessage()) diff --git a/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcMetric.java b/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcMetric.java index 1de35180d..640d52a61 100644 --- a/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcMetric.java +++ b/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcMetric.java @@ -49,7 +49,6 @@ public enum IpcMetric { IpcTagKey.status ), EnumSet.of( - IpcTagKey.attemptReason, IpcTagKey.endpoint, IpcTagKey.method, IpcTagKey.failureInjected, @@ -60,7 +59,6 @@ public enum IpcMetric { IpcTagKey.serverApp, IpcTagKey.serverCluster, IpcTagKey.serverAsg, - IpcTagKey.statusCode, IpcTagKey.statusDetail, IpcTagKey.vip ) @@ -87,7 +85,6 @@ public enum IpcMetric { IpcTagKey.httpStatus, IpcTagKey.id, IpcTagKey.protocol, - IpcTagKey.statusCode, IpcTagKey.statusDetail, IpcTagKey.vip ) diff --git a/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcSource.java b/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcSource.java new file mode 100644 index 000000000..2f9d3e45d --- /dev/null +++ b/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcSource.java @@ -0,0 +1,60 @@ +package com.netflix.spectator.ipc; + +import com.netflix.spectator.api.Tag; + +public enum IpcSource implements Tag { + /** + * No call was made due to errors potentially. + */ + none, + + /** + * Data source directly from EVCache as the cache implementation (when the exact cache is known). + */ + evcache, + + /** + * Data sourced from a cache where the cache implementation is not directly known or abstracted. + */ + cache, + + /** + * Static fallback used to fetch the data. + */ + fallback, + + /** + * Response fetched using mesh. + */ + mesh, + + /** + * Response fetched directly from the downstream service (or if not known to be mesh). + */ + direct, + + /** + * Data sourced from a validation handler that may short-circuit the response immediately for failed validation. + */ + validation, + + /** + * Data sourced and returned directly by a filter or interceptor. + */ + filter, + + /** + * Data fetched from an in-memory cache. + */ + memory; + + @Override + public String key() { + return IpcTagKey.source.key(); + } + + @Override + public String value() { + return name(); + } +} diff --git a/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcStatus.java b/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcStatus.java index 0283e5027..47ae81ea0 100644 --- a/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcStatus.java +++ b/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcStatus.java @@ -40,6 +40,11 @@ public enum IpcStatus implements Tag { */ bad_request, + /** + * The request data was not found. + */ + not_found, + /** * The client or server encountered an unexpected error processing the request. */ diff --git a/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcTagKey.java b/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcTagKey.java index bbfbcd186..c3526c249 100644 --- a/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcTagKey.java +++ b/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcTagKey.java @@ -34,7 +34,7 @@ public enum IpcTagKey { /** * Indicates where the result was ultimately sourced from such as cache, direct, - * proxy, fallback, etc. + * proxy, fallback, etc. See {@link IpcSource} for possible values. */ source("ipc.source"), @@ -45,13 +45,6 @@ public enum IpcTagKey { */ status("ipc.status"), - /** - * Dimension indicating the transport-specific code that aligns to the IPC status. - * The values for this are implementation specific. For example with HTTP, - * the status code value would be used here. - */ - statusCode("ipc.status.code"), - /** * Optional dimension indicating a more detailed status. The values for this are * implementation specific. For example, the {@link #status} may be @@ -86,11 +79,6 @@ public enum IpcTagKey { */ attempt("ipc.attempt"), - /** - * Indicates the reason for the attempt. See {@link IpcAttemptReason} for possible values. - */ - attemptReason("ipc.attempt.reason"), - /** * Indicates if this is the final attempt for the request. For example, if the client * is configured to allow 1 retry, then the second attempt would be final. Acceptable diff --git a/spectator-ext-ipc/src/test/java/com/netflix/spectator/ipc/IpcLogEntryTest.java b/spectator-ext-ipc/src/test/java/com/netflix/spectator/ipc/IpcLogEntryTest.java index db8bc21ae..10fa809f3 100644 --- a/spectator-ext-ipc/src/test/java/com/netflix/spectator/ipc/IpcLogEntryTest.java +++ b/spectator-ext-ipc/src/test/java/com/netflix/spectator/ipc/IpcLogEntryTest.java @@ -149,16 +149,6 @@ public void status() { Assertions.assertEquals(expected, actual); } - @Test - public void statusCode() { - String expected = "deadline_exceeded"; - String actual = (String) entry - .withStatusCode(expected) - .convert(this::toMap) - .get("statusCode"); - Assertions.assertEquals(expected, actual); - } - @Test public void statusDetail() { String expected = "connection_failed"; @@ -201,26 +191,6 @@ public void attempt() { Assertions.assertEquals(expected, actual); } - @Test - public void attemptReason() { - String expected = IpcAttemptReason.retry.value(); - String actual = (String) entry - .withAttemptReason(IpcAttemptReason.retry) - .convert(this::toMap) - .get("attemptReason"); - Assertions.assertEquals(expected, actual); - } - - @Test - public void customAttemptReason() { - String expected = "unknown"; - String actual = (String) entry - .withAttemptReason(expected) - .convert(this::toMap) - .get("attemptReason"); - Assertions.assertEquals(expected, actual); - } - @Test public void attemptFinal() { String expected = IpcAttemptFinal.is_true.value(); From ba568f4b97ce9e6510aad8f28b49ba167643daa4 Mon Sep 17 00:00:00 2001 From: annieyang Date: Mon, 11 Nov 2024 15:22:15 -0800 Subject: [PATCH 3/9] Add test --- .../netflix/spectator/ipc/IpcLogEntry.java | 10 +++++++++ .../com/netflix/spectator/ipc/IpcMetric.java | 2 ++ .../com/netflix/spectator/ipc/IpcSource.java | 22 ++++++++++++++++++- .../spectator/ipc/IpcLogEntryTest.java | 9 ++++++++ 4 files changed, 42 insertions(+), 1 deletion(-) diff --git a/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcLogEntry.java b/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcLogEntry.java index e49f7a891..9c8f0989c 100644 --- a/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcLogEntry.java +++ b/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcLogEntry.java @@ -52,6 +52,7 @@ public final class IpcLogEntry { private String owner; private IpcResult result; + private IpcSource source; private String protocol; @@ -209,6 +210,14 @@ public IpcLogEntry withResult(IpcResult result) { return this; } + /** + * Set the source for this request. See {@link IpcSource} for more information. + */ + public IpcLogEntry withSource(IpcSource source) { + this.source = source; + return this; + } + /** * Set the high level status for the request. See {@link IpcStatus} for more * information. @@ -936,6 +945,7 @@ public String toString() { .addField("attempt", attempt) .addField("attemptFinal", attemptFinal) .addField("result", result) + .addField("source", source) .addField("status", status) .addField("statusDetail", statusDetail) .addField("exceptionClass", getExceptionClass()) diff --git a/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcMetric.java b/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcMetric.java index 640d52a61..f30f30b6b 100644 --- a/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcMetric.java +++ b/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcMetric.java @@ -49,6 +49,7 @@ public enum IpcMetric { IpcTagKey.status ), EnumSet.of( + IpcTagKey.source, IpcTagKey.endpoint, IpcTagKey.method, IpcTagKey.failureInjected, @@ -75,6 +76,7 @@ public enum IpcMetric { IpcTagKey.status ), EnumSet.of( + IpcTagKey.source, IpcTagKey.endpoint, IpcTagKey.method, IpcTagKey.clientApp, diff --git a/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcSource.java b/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcSource.java index 2f9d3e45d..5022c313e 100644 --- a/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcSource.java +++ b/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcSource.java @@ -1,3 +1,18 @@ +/** + * Copyright 2024 Netflix, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.netflix.spectator.ipc; import com.netflix.spectator.api.Tag; @@ -46,7 +61,12 @@ public enum IpcSource implements Tag { /** * Data fetched from an in-memory cache. */ - memory; + memory, + + /** + * Data sourced from a user defined business logic handler or root data fetcher. + */ + application; @Override public String key() { diff --git a/spectator-ext-ipc/src/test/java/com/netflix/spectator/ipc/IpcLogEntryTest.java b/spectator-ext-ipc/src/test/java/com/netflix/spectator/ipc/IpcLogEntryTest.java index 10fa809f3..9f8017a99 100644 --- a/spectator-ext-ipc/src/test/java/com/netflix/spectator/ipc/IpcLogEntryTest.java +++ b/spectator-ext-ipc/src/test/java/com/netflix/spectator/ipc/IpcLogEntryTest.java @@ -479,6 +479,15 @@ public void addResponseEndpointHeader() { Assertions.assertEquals("/api/v1/test", map.get("endpoint")); } + @Test + public void source() { + String expected = IpcSource.direct.value(); + String actual = (String) entry + .withSource(IpcSource.direct) + .convert(this::toMap).get("source"); + Assertions.assertEquals(expected, actual); + } + @Test public void httpStatusOk() { String actual = (String) entry From d0ee1b0608f1bf3a98d574d637138f45f1f20096 Mon Sep 17 00:00:00 2001 From: annieyang Date: Mon, 11 Nov 2024 15:25:40 -0800 Subject: [PATCH 4/9] Remove not found --- .../src/main/java/com/netflix/spectator/ipc/IpcStatus.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcStatus.java b/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcStatus.java index 47ae81ea0..0283e5027 100644 --- a/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcStatus.java +++ b/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcStatus.java @@ -40,11 +40,6 @@ public enum IpcStatus implements Tag { */ bad_request, - /** - * The request data was not found. - */ - not_found, - /** * The client or server encountered an unexpected error processing the request. */ From f2f2f6251ef0ad61cfe30d15f9a16dcb0da47c16 Mon Sep 17 00:00:00 2001 From: annieyang Date: Mon, 11 Nov 2024 15:28:59 -0800 Subject: [PATCH 5/9] Remove extraneous new line --- .../src/test/java/com/netflix/spectator/ipc/IpcLogEntryTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/spectator-ext-ipc/src/test/java/com/netflix/spectator/ipc/IpcLogEntryTest.java b/spectator-ext-ipc/src/test/java/com/netflix/spectator/ipc/IpcLogEntryTest.java index 9f8017a99..21b006953 100644 --- a/spectator-ext-ipc/src/test/java/com/netflix/spectator/ipc/IpcLogEntryTest.java +++ b/spectator-ext-ipc/src/test/java/com/netflix/spectator/ipc/IpcLogEntryTest.java @@ -262,7 +262,6 @@ public void customMethod() { Assertions.assertEquals(expected, actual); } - @Test public void clientNode() { String expected = "i-12345"; From 7f434dce5b914d4069c853f0a8455e0b3bf27669 Mon Sep 17 00:00:00 2001 From: annieyang Date: Mon, 11 Nov 2024 15:40:07 -0800 Subject: [PATCH 6/9] Formatting --- .../src/main/java/com/netflix/spectator/ipc/IpcSource.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcSource.java b/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcSource.java index 5022c313e..4c7d79e8f 100644 --- a/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcSource.java +++ b/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcSource.java @@ -18,13 +18,14 @@ import com.netflix.spectator.api.Tag; public enum IpcSource implements Tag { + /** * No call was made due to errors potentially. */ none, /** - * Data source directly from EVCache as the cache implementation (when the exact cache is known). + * Data sourced directly from EVCache as the cache implementation (when the exact cache is known). */ evcache, @@ -34,7 +35,7 @@ public enum IpcSource implements Tag { cache, /** - * Static fallback used to fetch the data. + * Static fallback was used to fetch the data. */ fallback, From 1fdadb36c1ffaf7c69565ff07bbcd8e05f914121 Mon Sep 17 00:00:00 2001 From: annieyang Date: Tue, 12 Nov 2024 16:00:46 -0800 Subject: [PATCH 7/9] Add API metrics enums --- .../com/netflix/spectator/ipc/IpcMetric.java | 73 +++++++++++++++++-- .../netflix/spectator/ipc/IpcMetricTest.java | 50 +++++++++++++ 2 files changed, 118 insertions(+), 5 deletions(-) diff --git a/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcMetric.java b/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcMetric.java index f30f30b6b..31dafeb07 100644 --- a/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcMetric.java +++ b/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcMetric.java @@ -49,9 +49,7 @@ public enum IpcMetric { IpcTagKey.status ), EnumSet.of( - IpcTagKey.source, IpcTagKey.endpoint, - IpcTagKey.method, IpcTagKey.failureInjected, IpcTagKey.httpMethod, IpcTagKey.httpStatus, @@ -76,9 +74,7 @@ public enum IpcMetric { IpcTagKey.status ), EnumSet.of( - IpcTagKey.source, IpcTagKey.endpoint, - IpcTagKey.method, IpcTagKey.clientApp, IpcTagKey.clientCluster, IpcTagKey.clientAsg, @@ -232,7 +228,74 @@ public enum IpcMetric { IpcTagKey.protocol, IpcTagKey.vip ) - ); + ), + + /** + * V2 - Timer recording the number and latency of outbound requests. + */ + apiClientCall( + "api.client.call", + EnumSet.of( + IpcTagKey.vip, + IpcTagKey.method, + IpcTagKey.endpoint, + IpcTagKey.owner, + IpcTagKey.id, + IpcTagKey.source, + IpcTagKey.result, + IpcTagKey.status, + IpcTagKey.statusDetail + ), + EnumSet.noneOf(IpcTagKey.class) + ), + + /** + * V2 - Timer recording the number and latency of inbound requests. + */ + apiServerCall( + "api.server.call", + EnumSet.of( + IpcTagKey.method, + IpcTagKey.endpoint, + IpcTagKey.owner, + IpcTagKey.id, + IpcTagKey.source, + IpcTagKey.result, + IpcTagKey.status, + IpcTagKey.statusDetail + ), + EnumSet.noneOf(IpcTagKey.class) + ), + + /** + * V2 - Number of outbound requests that are currently in flight. + */ + apiClientInflight( + "api.client.inflight", + EnumSet.of( + IpcTagKey.vip, + IpcTagKey.method, + IpcTagKey.endpoint, + IpcTagKey.owner, + IpcTagKey.id + ), + EnumSet.noneOf(IpcTagKey.class) + ), + + /** + * V2 - Number of inbound requests that are currently in flight. + */ + apiServerInflight( + "api.server.inflight", + EnumSet.of( + IpcTagKey.method, + IpcTagKey.endpoint, + IpcTagKey.owner, + IpcTagKey.id + ), + EnumSet.noneOf(IpcTagKey.class) + ), + ; private final String metricName; private final EnumSet requiredDimensions; diff --git a/spectator-ext-ipc/src/test/java/com/netflix/spectator/ipc/IpcMetricTest.java b/spectator-ext-ipc/src/test/java/com/netflix/spectator/ipc/IpcMetricTest.java index 46683b4a9..6fb86350a 100644 --- a/spectator-ext-ipc/src/test/java/com/netflix/spectator/ipc/IpcMetricTest.java +++ b/spectator-ext-ipc/src/test/java/com/netflix/spectator/ipc/IpcMetricTest.java @@ -252,4 +252,54 @@ public void validateFailureInjectionInvalid() { IpcMetric.clientCall.validate(id); }); } + + @Test + public void validateApiIdOk() { + Id id = registry.createId(IpcMetric.apiClientCall.metricName()) + .withTag(IpcTagKey.owner.tag("test")) + .withTag(IpcTagKey.vip.tag("localhost")) + .withTag(IpcMethod.get) + .withTag(IpcTagKey.endpoint.tag("hello")) + .withTag(IpcTagKey.id.tag("HelloEndpoint")) + .withTag(IpcSource.direct) + .withTag(IpcResult.success) + .withTag(IpcStatus.success) + .withTag(IpcTagKey.statusDetail.tag("200")); + IpcMetric.apiClientCall.validate(id, true); + } + + @Test + public void validateApiInflightOk() { + Id id = registry.createId(IpcMetric.apiClientInflight.metricName()) + .withTag(IpcTagKey.owner.tag("test")) + .withTag(IpcTagKey.vip.tag("localhost")) + .withTag(IpcMethod.get) + .withTag(IpcTagKey.endpoint.tag("hello")) + .withTag(IpcTagKey.id.tag("HelloEndpoint")); + IpcMetric.apiClientInflight.validate(id, true); + } + + @Test + public void validateApiServerIdOk() { + Id id = registry.createId(IpcMetric.apiServerCall.metricName()) + .withTag(IpcTagKey.owner.tag("test")) + .withTag(IpcMethod.get) + .withTag(IpcTagKey.endpoint.tag("hello")) + .withTag(IpcTagKey.id.tag("HelloEndpoint")) + .withTag(IpcSource.direct) + .withTag(IpcResult.success) + .withTag(IpcStatus.success) + .withTag(IpcTagKey.statusDetail.tag("200")); + IpcMetric.apiServerCall.validate(id, true); + } + + @Test + public void validateApiServerInflightOk() { + Id id = registry.createId(IpcMetric.apiServerInflight.metricName()) + .withTag(IpcTagKey.owner.tag("test")) + .withTag(IpcMethod.get) + .withTag(IpcTagKey.endpoint.tag("hello")) + .withTag(IpcTagKey.id.tag("HelloEndpoint")); + IpcMetric.apiServerInflight.validate(id, true); + } } From 38fbaf78e4453361d0635165fcf39791eb759e6f Mon Sep 17 00:00:00 2001 From: annieyang Date: Tue, 12 Nov 2024 16:13:22 -0800 Subject: [PATCH 8/9] Formatting --- .../src/main/java/com/netflix/spectator/ipc/IpcMetric.java | 3 +-- .../src/main/java/com/netflix/spectator/ipc/IpcSource.java | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcMetric.java b/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcMetric.java index 31dafeb07..5f01ccdfb 100644 --- a/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcMetric.java +++ b/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcMetric.java @@ -294,8 +294,7 @@ public enum IpcMetric { IpcTagKey.id ), EnumSet.noneOf(IpcTagKey.class) - ), - ; + ); private final String metricName; private final EnumSet requiredDimensions; diff --git a/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcSource.java b/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcSource.java index 4c7d79e8f..baaf25c24 100644 --- a/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcSource.java +++ b/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcSource.java @@ -18,7 +18,7 @@ import com.netflix.spectator.api.Tag; public enum IpcSource implements Tag { - + /** * No call was made due to errors potentially. */ From a665f79cc1c6822fdda6af93d0058b3892e5b77b Mon Sep 17 00:00:00 2001 From: annieyang Date: Thu, 14 Nov 2024 12:36:51 -0800 Subject: [PATCH 9/9] Remove inflight metrics --- .../com/netflix/spectator/ipc/IpcMetric.java | 29 ------------------- .../netflix/spectator/ipc/IpcMetricTest.java | 21 -------------- 2 files changed, 50 deletions(-) diff --git a/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcMetric.java b/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcMetric.java index 5f01ccdfb..072f588e8 100644 --- a/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcMetric.java +++ b/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/IpcMetric.java @@ -265,35 +265,6 @@ public enum IpcMetric { IpcTagKey.statusDetail ), EnumSet.noneOf(IpcTagKey.class) - ), - - /** - * V2 - Number of outbound requests that are currently in flight. - */ - apiClientInflight( - "api.client.inflight", - EnumSet.of( - IpcTagKey.vip, - IpcTagKey.method, - IpcTagKey.endpoint, - IpcTagKey.owner, - IpcTagKey.id - ), - EnumSet.noneOf(IpcTagKey.class) - ), - - /** - * V2 - Number of inbound requests that are currently in flight. - */ - apiServerInflight( - "api.server.inflight", - EnumSet.of( - IpcTagKey.method, - IpcTagKey.endpoint, - IpcTagKey.owner, - IpcTagKey.id - ), - EnumSet.noneOf(IpcTagKey.class) ); private final String metricName; diff --git a/spectator-ext-ipc/src/test/java/com/netflix/spectator/ipc/IpcMetricTest.java b/spectator-ext-ipc/src/test/java/com/netflix/spectator/ipc/IpcMetricTest.java index 6fb86350a..278acca10 100644 --- a/spectator-ext-ipc/src/test/java/com/netflix/spectator/ipc/IpcMetricTest.java +++ b/spectator-ext-ipc/src/test/java/com/netflix/spectator/ipc/IpcMetricTest.java @@ -268,17 +268,6 @@ public void validateApiIdOk() { IpcMetric.apiClientCall.validate(id, true); } - @Test - public void validateApiInflightOk() { - Id id = registry.createId(IpcMetric.apiClientInflight.metricName()) - .withTag(IpcTagKey.owner.tag("test")) - .withTag(IpcTagKey.vip.tag("localhost")) - .withTag(IpcMethod.get) - .withTag(IpcTagKey.endpoint.tag("hello")) - .withTag(IpcTagKey.id.tag("HelloEndpoint")); - IpcMetric.apiClientInflight.validate(id, true); - } - @Test public void validateApiServerIdOk() { Id id = registry.createId(IpcMetric.apiServerCall.metricName()) @@ -292,14 +281,4 @@ public void validateApiServerIdOk() { .withTag(IpcTagKey.statusDetail.tag("200")); IpcMetric.apiServerCall.validate(id, true); } - - @Test - public void validateApiServerInflightOk() { - Id id = registry.createId(IpcMetric.apiServerInflight.metricName()) - .withTag(IpcTagKey.owner.tag("test")) - .withTag(IpcMethod.get) - .withTag(IpcTagKey.endpoint.tag("hello")) - .withTag(IpcTagKey.id.tag("HelloEndpoint")); - IpcMetric.apiServerInflight.validate(id, true); - } }