-
Notifications
You must be signed in to change notification settings - Fork 169
OpAMP HTTP service #1928
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
OpAMP HTTP service #1928
Changes from 21 commits
Commits
Show all changes
38 commits
Select commit
Hold shift + click to select a range
0064a0b
Creating Request
LikeTheSalad 84bd658
Adding periodic task executor
LikeTheSalad 194a0ee
Adding RequestService and its http implementation
LikeTheSalad 815b7c5
Adding tests
LikeTheSalad bb084c3
Updating HttpRequestService
LikeTheSalad 61fb2ee
Creating RetryAfterParser
LikeTheSalad acce15e
Adding suggested delay
LikeTheSalad 3dc6f12
Clean up
LikeTheSalad 5657876
Spotless
LikeTheSalad d94ff62
Applying PR review suggestions
LikeTheSalad 37bf5a9
Applying PR review suggestions
LikeTheSalad 91f876a
Applying PR review suggestions
LikeTheSalad 84d17d8
Applying PR review suggestions
LikeTheSalad 8625f8f
Applying PR review suggestions
LikeTheSalad 70e7d95
Avoid using SimpleDateFormat
LikeTheSalad b190ad1
Validating when retry-after time is older than current one
LikeTheSalad 7afe527
Updating javadoc based on PR review
LikeTheSalad 51c9e08
Using daemon threads for opamp client, as mentioned in pr comments
LikeTheSalad 9a4e483
Update opamp-client/src/main/java/io/opentelemetry/opamp/client/inter…
LikeTheSalad b299d2c
Calling completable future when there's no response body
LikeTheSalad 71e6710
Updating retry-after pattern for seconds
LikeTheSalad 451812e
Simplifying retry-after parser patterns
LikeTheSalad 3c3830b
Created BodyWriter to use in HttpSender
LikeTheSalad 260cbc4
Removing nested try with resources as suggested in PR reviews
LikeTheSalad 98d1b7f
Clean up
LikeTheSalad 08c3bc2
Clean up
LikeTheSalad 6d3baed
Updating tests
LikeTheSalad 478e8c4
Updating tests
LikeTheSalad 77ae328
Calling callback.onConnectionFailed
LikeTheSalad 17ac9d6
Removing executor for HttpRequestServiceTest
LikeTheSalad c272f97
Updating tests
LikeTheSalad b709a81
Adding initial task validation
LikeTheSalad 7b21419
Simplifying HttpRequestService as suggested in the PR reviews
LikeTheSalad f49fa67
Spotless
LikeTheSalad 73cb995
Avoiding verifying task cancel call in tests
LikeTheSalad 3bb8d7b
Ensuring only one task is executed at a time and it always schedules …
LikeTheSalad af0fc20
Clean up
LikeTheSalad 0a62b94
Applying suggested changes in review
LikeTheSalad File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
27 changes: 27 additions & 0 deletions
27
...ain/java/io/opentelemetry/opamp/client/internal/connectivity/http/HttpErrorException.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| /* | ||
| * Copyright The OpenTelemetry Authors | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| package io.opentelemetry.opamp.client.internal.connectivity.http; | ||
|
|
||
| public class HttpErrorException extends Exception { | ||
| private final int errorCode; | ||
|
|
||
| private static final long serialVersionUID = 1L; | ||
|
|
||
| public int getErrorCode() { | ||
| return errorCode; | ||
| } | ||
|
|
||
| /** | ||
| * Constructs an HTTP error related exception. | ||
| * | ||
| * @param errorCode The HTTP error code. | ||
| * @param message The HTTP error message associated with the code. | ||
| */ | ||
| public HttpErrorException(int errorCode, String message) { | ||
| super(message); | ||
| this.errorCode = errorCode; | ||
| } | ||
| } |
27 changes: 27 additions & 0 deletions
27
...nt/src/main/java/io/opentelemetry/opamp/client/internal/connectivity/http/HttpSender.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| /* | ||
| * Copyright The OpenTelemetry Authors | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| package io.opentelemetry.opamp.client.internal.connectivity.http; | ||
|
|
||
| import java.io.Closeable; | ||
| import java.io.InputStream; | ||
| import java.io.OutputStream; | ||
| import java.util.concurrent.CompletableFuture; | ||
| import java.util.function.Consumer; | ||
|
|
||
| public interface HttpSender { | ||
|
|
||
| CompletableFuture<Response> send(Consumer<OutputStream> writer, int contentLength); | ||
|
|
||
| interface Response extends Closeable { | ||
| int statusCode(); | ||
|
|
||
| String statusMessage(); | ||
|
|
||
| InputStream bodyInputStream(); | ||
|
|
||
| String getHeader(String name); | ||
| } | ||
| } |
138 changes: 138 additions & 0 deletions
138
.../src/main/java/io/opentelemetry/opamp/client/internal/connectivity/http/OkHttpSender.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,138 @@ | ||
| /* | ||
| * Copyright The OpenTelemetry Authors | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| package io.opentelemetry.opamp.client.internal.connectivity.http; | ||
|
|
||
| import java.io.IOException; | ||
| import java.io.InputStream; | ||
| import java.io.OutputStream; | ||
| import java.util.concurrent.CompletableFuture; | ||
| import java.util.function.Consumer; | ||
| import okhttp3.Call; | ||
| import okhttp3.Callback; | ||
| import okhttp3.MediaType; | ||
| import okhttp3.OkHttpClient; | ||
| import okhttp3.RequestBody; | ||
| import okio.BufferedSink; | ||
| import org.jetbrains.annotations.NotNull; | ||
| import org.jetbrains.annotations.Nullable; | ||
|
|
||
| public final class OkHttpSender implements HttpSender { | ||
| private final OkHttpClient client; | ||
| private final String url; | ||
|
|
||
| public static OkHttpSender create(String url) { | ||
| return create(url, new OkHttpClient()); | ||
| } | ||
|
|
||
| public static OkHttpSender create(String url, OkHttpClient client) { | ||
| return new OkHttpSender(url, client); | ||
| } | ||
|
|
||
| private static final String CONTENT_TYPE = "application/x-protobuf"; | ||
| private static final MediaType MEDIA_TYPE = MediaType.parse(CONTENT_TYPE); | ||
|
|
||
| private OkHttpSender(String url, OkHttpClient client) { | ||
| this.url = url; | ||
| this.client = client; | ||
| } | ||
|
|
||
| @Override | ||
| public CompletableFuture<Response> send(Consumer<OutputStream> writer, int contentLength) { | ||
| CompletableFuture<Response> future = new CompletableFuture<>(); | ||
| okhttp3.Request.Builder builder = new okhttp3.Request.Builder().url(url); | ||
| builder.addHeader("Content-Type", CONTENT_TYPE); | ||
|
|
||
| RequestBody body = new RawRequestBody(writer, contentLength, MEDIA_TYPE); | ||
| builder.post(body); | ||
|
|
||
| client | ||
| .newCall(builder.build()) | ||
| .enqueue( | ||
| new Callback() { | ||
| @Override | ||
| public void onResponse(@NotNull Call call, @NotNull okhttp3.Response response) { | ||
| if (response.isSuccessful() && response.body() != null) { | ||
| future.complete(new OkHttpResponse(response)); | ||
| } else { | ||
| future.completeExceptionally( | ||
| new HttpErrorException(response.code(), response.message())); | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| public void onFailure(@NotNull Call call, @NotNull IOException e) { | ||
| future.completeExceptionally(e); | ||
| } | ||
| }); | ||
|
|
||
| return future; | ||
| } | ||
|
|
||
| private static class OkHttpResponse implements Response { | ||
| private final okhttp3.Response response; | ||
|
|
||
| private OkHttpResponse(okhttp3.Response response) { | ||
| if (response.body() == null) { | ||
| throw new IllegalStateException("null response body not expected"); | ||
| } | ||
| this.response = response; | ||
| } | ||
|
|
||
| @Override | ||
| public int statusCode() { | ||
| return response.code(); | ||
| } | ||
|
|
||
| @Override | ||
| public String statusMessage() { | ||
| return response.message(); | ||
| } | ||
|
|
||
| @Override | ||
| public InputStream bodyInputStream() { | ||
| return response.body().byteStream(); | ||
| } | ||
|
|
||
| @Override | ||
| public String getHeader(String name) { | ||
| return response.headers().get(name); | ||
| } | ||
|
|
||
| @Override | ||
| public void close() { | ||
| response.close(); | ||
| } | ||
| } | ||
|
|
||
| private static class RawRequestBody extends RequestBody { | ||
| private final Consumer<OutputStream> writer; | ||
| private final int contentLength; | ||
| private final MediaType contentType; | ||
|
|
||
| private RawRequestBody( | ||
| Consumer<OutputStream> writer, int contentLength, MediaType contentType) { | ||
| this.writer = writer; | ||
| this.contentLength = contentLength; | ||
| this.contentType = contentType; | ||
| } | ||
|
|
||
| @Nullable | ||
| @Override | ||
| public MediaType contentType() { | ||
| return contentType; | ||
| } | ||
|
|
||
| @Override | ||
| public long contentLength() { | ||
| return contentLength; | ||
| } | ||
|
|
||
| @Override | ||
| public void writeTo(@NotNull BufferedSink bufferedSink) { | ||
| writer.accept(bufferedSink.outputStream()); | ||
| } | ||
| } | ||
| } |
49 changes: 49 additions & 0 deletions
49
.../main/java/io/opentelemetry/opamp/client/internal/connectivity/http/RetryAfterParser.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| /* | ||
| * Copyright The OpenTelemetry Authors | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| package io.opentelemetry.opamp.client.internal.connectivity.http; | ||
|
|
||
| import io.opentelemetry.opamp.client.internal.tools.SystemTime; | ||
| import java.time.Duration; | ||
| import java.time.ZonedDateTime; | ||
| import java.time.format.DateTimeFormatter; | ||
| import java.util.Locale; | ||
| import java.util.Optional; | ||
| import java.util.regex.Pattern; | ||
|
|
||
| public final class RetryAfterParser { | ||
| private final SystemTime systemTime; | ||
| public static final Pattern SECONDS_PATTERN = Pattern.compile("^\\d+$"); | ||
| public static final Pattern DATE_PATTERN = | ||
| Pattern.compile( | ||
| "^([A-Za-z]{3}, [0-3][0-9] [A-Za-z]{3} [0-9]{4} [0-2][0-9]:[0-5][0-9]:[0-5][0-9] GMT)$"); | ||
| private static final DateTimeFormatter DATE_FORMAT = | ||
| DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss z", Locale.US); | ||
|
|
||
| public static RetryAfterParser getInstance() { | ||
| return new RetryAfterParser(SystemTime.getInstance()); | ||
| } | ||
|
|
||
| RetryAfterParser(SystemTime systemTime) { | ||
| this.systemTime = systemTime; | ||
| } | ||
|
|
||
| public Optional<Duration> tryParse(String value) { | ||
| Duration duration = null; | ||
| if (SECONDS_PATTERN.matcher(value).matches()) { | ||
| duration = Duration.ofSeconds(Long.parseLong(value)); | ||
| } else if (DATE_PATTERN.matcher(value).matches()) { | ||
| long difference = toMilliseconds(value) - systemTime.getCurrentTimeMillis(); | ||
| if (difference > 0) { | ||
| duration = Duration.ofMillis(difference); | ||
| } | ||
| } | ||
| return Optional.ofNullable(duration); | ||
| } | ||
|
|
||
| private static long toMilliseconds(String value) { | ||
| return ZonedDateTime.parse(value, DATE_FORMAT).toInstant().toEpochMilli(); | ||
| } | ||
| } | ||
19 changes: 19 additions & 0 deletions
19
opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/request/Request.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| /* | ||
| * Copyright The OpenTelemetry Authors | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| package io.opentelemetry.opamp.client.internal.request; | ||
|
|
||
| import com.google.auto.value.AutoValue; | ||
| import opamp.proto.AgentToServer; | ||
|
|
||
| /** Wrapper class for "AgentToServer" request body. */ | ||
| @AutoValue | ||
| public abstract class Request { | ||
| public abstract AgentToServer getAgentToServer(); | ||
|
|
||
| public static Request create(AgentToServer agentToServer) { | ||
| return new AutoValue_Request(agentToServer); | ||
| } | ||
| } |
18 changes: 18 additions & 0 deletions
18
...ain/java/io/opentelemetry/opamp/client/internal/request/delay/AcceptsDelaySuggestion.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| /* | ||
| * Copyright The OpenTelemetry Authors | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| package io.opentelemetry.opamp.client.internal.request.delay; | ||
|
|
||
| import java.time.Duration; | ||
|
|
||
| /** | ||
| * A {@link PeriodicDelay} implementation that wants to accept delay time suggestions, as explained | ||
| * <a | ||
| * href="https://github.com/open-telemetry/opamp-spec/blob/main/specification.md#throttling">here</a>, | ||
| * must implement this interface. | ||
| */ | ||
| public interface AcceptsDelaySuggestion { | ||
laurit marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| void suggestDelay(Duration delay); | ||
| } | ||
24 changes: 24 additions & 0 deletions
24
...rc/main/java/io/opentelemetry/opamp/client/internal/request/delay/FixedPeriodicDelay.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| /* | ||
| * Copyright The OpenTelemetry Authors | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| package io.opentelemetry.opamp.client.internal.request.delay; | ||
|
|
||
| import java.time.Duration; | ||
|
|
||
| final class FixedPeriodicDelay implements PeriodicDelay { | ||
| private final Duration duration; | ||
|
|
||
| public FixedPeriodicDelay(Duration duration) { | ||
| this.duration = duration; | ||
| } | ||
|
|
||
| @Override | ||
| public Duration getNextDelay() { | ||
| return duration; | ||
| } | ||
|
|
||
| @Override | ||
| public void reset() {} | ||
| } |
18 changes: 18 additions & 0 deletions
18
...ent/src/main/java/io/opentelemetry/opamp/client/internal/request/delay/PeriodicDelay.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| /* | ||
| * Copyright The OpenTelemetry Authors | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| package io.opentelemetry.opamp.client.internal.request.delay; | ||
|
|
||
| import java.time.Duration; | ||
|
|
||
| public interface PeriodicDelay { | ||
| static PeriodicDelay ofFixedDuration(Duration duration) { | ||
| return new FixedPeriodicDelay(duration); | ||
| } | ||
|
|
||
| Duration getNextDelay(); | ||
|
|
||
| void reset(); | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.