|
| 1 | +/* |
| 2 | + * Copyright 2025 LY Corporation |
| 3 | + * |
| 4 | + * LY Corporation licenses this file to you under the Apache License, |
| 5 | + * version 2.0 (the "License"); you may not use this file except in compliance |
| 6 | + * with the License. You may obtain a copy of the License at: |
| 7 | + * |
| 8 | + * https://www.apache.org/licenses/LICENSE-2.0 |
| 9 | + * |
| 10 | + * Unless required by applicable law or agreed to in writing, software |
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| 12 | + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| 13 | + * License for the specific language governing permissions and limitations |
| 14 | + * under the License. |
| 15 | + */ |
| 16 | + |
1 | 17 | package com.linecorp.armeria.client.metric; |
2 | 18 |
|
3 | 19 | import com.linecorp.armeria.client.ClientRequestContext; |
4 | 20 | import com.linecorp.armeria.common.ResponseHeaders; |
5 | 21 | import com.linecorp.armeria.common.annotation.Nullable; |
6 | 22 | import com.linecorp.armeria.common.annotation.UnstableApi; |
| 23 | +import com.linecorp.armeria.common.logging.RequestLogListener; |
7 | 24 |
|
| 25 | +/** |
| 26 | + * Listens to the lifecycle events of client requests. |
| 27 | + * |
| 28 | + * <p>This interface provides a high-level view of a request's lifecycle (e.g., pending, started, completed). |
| 29 | + * unlike {@link RequestLogListener} which provides low-level property changes. |
| 30 | + * |
| 31 | + * <p>Note: The methods in this interface are typically not invoked directly by the |
| 32 | + * transport layer. Instead, they are triggered by inspecting the changes in |
| 33 | + * {@link com.linecorp.armeria.common.logging.RequestLog}. |
| 34 | + * Implementations should use {@link #asRequestLogListener()} to bridge |
| 35 | + * {@link com.linecorp.armeria.common.logging.RequestLogProperty} |
| 36 | + * changes to these lifecycle methods. |
| 37 | + * |
| 38 | + * <p>For example, a standard implementation might map: |
| 39 | + * <ul> |
| 40 | + * <li>{@link com.linecorp.armeria.common.logging.RequestLogProperty#REQUEST_FIRST_BYTES_TRANSFERRED_TIME} |
| 41 | + * to {@link #onRequestStart(ClientRequestContext)}</li> |
| 42 | + * <li>{@link com.linecorp.armeria.common.logging.RequestLogProperty#ALL_COMPLETE} |
| 43 | + * to {@link #onRequestComplete(ClientRequestContext, Throwable)}</li> |
| 44 | + * </ul> |
| 45 | + * |
| 46 | + * @see com.linecorp.armeria.client.ClientFactoryBuilder#clientRequestLifecycleListener( |
| 47 | + * ClientRequestLifecycleListener) |
| 48 | + */ |
8 | 49 | @UnstableApi |
9 | 50 | public interface ClientRequestLifecycleListener { |
10 | 51 |
|
11 | 52 | /** |
12 | | - * Called when a request is created and scheduled but not yet executed. |
| 53 | + * Invoked when a request is created and scheduled for execution but has not yet started. |
| 54 | + * Note: This method is explicitly invoked by HttpClientDelegate when |
| 55 | + * HttpClientDelegate starts to call execute(). |
13 | 56 | */ |
14 | 57 | void onRequestPending(ClientRequestContext ctx); |
15 | 58 |
|
@@ -37,19 +80,41 @@ public interface ClientRequestLifecycleListener { |
37 | 80 | * Called when a request is completed with either success or failure. |
38 | 81 | */ |
39 | 82 | void onRequestComplete(ClientRequestContext ctx, @Nullable Throwable cause); |
40 | | - |
| 83 | + |
| 84 | + /** |
| 85 | + * Returns a {@link RequestLogListener} that delegates |
| 86 | + * {@link com.linecorp.armeria.common.logging.RequestLog} |
| 87 | + * events to this lifecycle listener. |
| 88 | + * This method bridges the low-level {@link com.linecorp.armeria.common.logging.RequestLog} |
| 89 | + * updates to the high-level lifecycle methods |
| 90 | + * defined in this interface. The returned listener is registered to the {@link ClientRequestContext} |
| 91 | + * automatically when the request starts. |
| 92 | + */ |
| 93 | + RequestLogListener asRequestLogListener(); |
| 94 | + |
| 95 | + /** |
| 96 | + * Returns a {@link ClientRequestMetrics} that collects the number of pending and active requests. |
| 97 | + */ |
41 | 98 | static ClientRequestMetrics counting() { |
42 | 99 | return new ClientRequestMetrics(); |
43 | 100 | } |
44 | | - |
| 101 | + |
| 102 | + /** |
| 103 | + * Returns a {@link ClientRequestLifecycleListener} that does nothing. |
| 104 | + */ |
45 | 105 | static ClientRequestLifecycleListener noop() { |
46 | 106 | return NoopClientRequestLifecycleListener.INSTANCE; |
47 | 107 | } |
48 | | - |
| 108 | + |
| 109 | + /** |
| 110 | + * A {@link ClientRequestLifecycleListener} that does nothing. |
| 111 | + */ |
49 | 112 | class NoopClientRequestLifecycleListener implements ClientRequestLifecycleListener { |
50 | | - |
51 | | - private static final NoopClientRequestLifecycleListener INSTANCE = new NoopClientRequestLifecycleListener(); |
52 | | - |
| 113 | + |
| 114 | + private static final NoopClientRequestLifecycleListener INSTANCE = |
| 115 | + new NoopClientRequestLifecycleListener(); |
| 116 | + private final RequestLogListener requestLogListener = ((property, log) -> {}); |
| 117 | + |
53 | 118 | @Override |
54 | 119 | public void onRequestPending(ClientRequestContext ctx) { |
55 | 120 | // no-op |
@@ -79,6 +144,11 @@ public void onResponseComplete(ClientRequestContext ctx) { |
79 | 144 | public void onRequestComplete(ClientRequestContext ctx, @Nullable Throwable cause) { |
80 | 145 | // no-op |
81 | 146 | } |
| 147 | + |
| 148 | + @Override |
| 149 | + public RequestLogListener asRequestLogListener() { |
| 150 | + // no-op |
| 151 | + return requestLogListener; |
| 152 | + } |
82 | 153 | } |
83 | | - |
84 | 154 | } |
0 commit comments