Skip to content

Commit

Permalink
wip: integration test eureka with armeria
Browse files Browse the repository at this point in the history
Signed-off-by: Adrian Cole <[email protected]>
  • Loading branch information
Adrian Cole committed Jan 14, 2024
1 parent fe58f3a commit 2c166e8
Show file tree
Hide file tree
Showing 9 changed files with 240 additions and 35 deletions.
59 changes: 54 additions & 5 deletions armeria/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,68 @@
<maven.compiler.release>8</maven.compiler.release>

<armeria.version>1.26.4</armeria.version>
<zipkin-reporter.version>3.2.0-SNAPSHOT</zipkin-reporter.version>
</properties>

<dependencies>
<dependency>
<groupId>com.linecorp.armeria</groupId>
<artifactId>armeria</artifactId>
<exclusions>
<!-- temporary until netty includes https://github.com/netty/netty/pull/13724 -->
<exclusion>
<groupId>io.netty</groupId>
<artifactId>netty-tcnative-boringssl-static</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- temporary until netty includes https://github.com/netty/netty/pull/13724 -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-tcnative-boringssl-static</artifactId>
<version>2.0.62.Final</version>
<classifier>linux-x86_64</classifier>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-tcnative-boringssl-static</artifactId>
<version>2.0.62.Final</version>
<classifier>linux-aarch_64</classifier>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-tcnative-boringssl-static</artifactId>
<version>2.0.62.Final</version>
<classifier>osx-x86_64</classifier>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-tcnative-boringssl-static</artifactId>
<version>2.0.62.Final</version>
<classifier>osx-aarch_64</classifier>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-tcnative-boringssl-static</artifactId>
<version>2.0.62.Final</version>
<classifier>windows-x86_64</classifier>
<scope>runtime</scope>
</dependency>

<!-- Instruments the underlying Armeria requests -->
<dependency>
<groupId>com.linecorp.armeria</groupId>
<artifactId>armeria-brave</artifactId>
</dependency>

<!-- Optionally look up Zipkin with Eureka -->
<dependency>
<groupId>com.linecorp.armeria</groupId>
<artifactId>armeria-eureka</artifactId>
</dependency>
<!-- Integrates so you can use log patterns like %X{traceId}/%X{spanId} -->
<dependency>
<groupId>com.linecorp.armeria</groupId>
Expand All @@ -45,10 +98,6 @@
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-reporter-brave</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-sender-urlconnection</artifactId>
</dependency>
</dependencies>

<dependencyManagement>
Expand Down
8 changes: 4 additions & 4 deletions armeria/src/main/java/brave/example/Backend.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public final class Backend {
public static void main(String[] args) {
final HttpTracing httpTracing = HttpTracingFactory.create("backend");

final Server server = Server.builder()
try (Server server = Server.builder()
.http(9000)
.service("/health", HealthCheckService.builder().build())
.service("/api", (ctx, req) -> {
Expand All @@ -24,8 +24,8 @@ public static void main(String[] args) {
})
.decorator(BraveService.newDecorator(httpTracing))
.decorator(LoggingService.newDecorator())
.build();

server.start().join();
.build()) {
server.start().join();
}
}
}
19 changes: 10 additions & 9 deletions armeria/src/main/java/brave/example/Frontend.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,16 @@ public static void main(String[] args) {
.decorator(BraveClient.newDecorator(httpTracing.clientOf("backend")))
.build();

final Server server =
Server.builder()
.http(8081)
.service("/health", HealthCheckService.builder().build())
.service("/", (ctx, req) -> backendClient.get(""))
.decorator(BraveService.newDecorator(httpTracing))
.decorator(LoggingService.newDecorator())
.build();
try (Server server =
Server.builder()
.http(8081)
.service("/health", HealthCheckService.builder().build())
.service("/", (ctx, req) -> backendClient.get(""))
.decorator(BraveService.newDecorator(httpTracing))
.decorator(LoggingService.newDecorator())
.build()) {

server.start().join();
server.start().join();
}
}
}
25 changes: 18 additions & 7 deletions armeria/src/main/java/brave/example/TracingFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,19 @@
import brave.propagation.CurrentTraceContext;
import brave.propagation.CurrentTraceContext.ScopeDecorator;
import brave.propagation.Propagation;
import com.linecorp.armeria.client.WebClient;
import com.linecorp.armeria.client.eureka.EurekaEndpointGroup;
import com.linecorp.armeria.common.SessionProtocol;
import com.linecorp.armeria.common.brave.RequestContextCurrentTraceContext;
import java.io.IOException;
import java.util.logging.Logger;
import zipkin2.reporter.Sender;
import zipkin2.reporter.BytesMessageSender;
import zipkin2.reporter.brave.AsyncZipkinSpanHandler;
import zipkin2.reporter.urlconnection.URLConnectionSender;

final class HttpTracingFactory {
static final BaggageField USER_NAME = BaggageField.create("userName");

/** Decides how to name and tag spans. By default they are named the same as the http method. */
/** Decides how to name and tag spans. By default, they are named the same as the http method. */
static HttpTracing create(String serviceName) {
return HttpTracing.create(tracing((System.getProperty("brave.localServiceName", serviceName))));
}
Expand Down Expand Up @@ -61,13 +63,22 @@ static Propagation.Factory propagationFactory() {
}

/** Configuration for how to send spans to Zipkin */
static Sender sender() {
return URLConnectionSender.create(
System.getProperty("zipkin.baseUrl", "http://127.0.0.1:9411") + "/api/v2/spans");
static BytesMessageSender sender() {
String postPath = "/api/v2/spans";
String eurekaUri = System.getenv("EUREKA_SERVICE_URL");
if (eurekaUri != null && !eurekaUri.isEmpty()) {
EurekaEndpointGroup zipkin =
EurekaEndpointGroup.builder(eurekaUri).appName("zipkin").build();
Runtime.getRuntime().addShutdownHook(new Thread(zipkin::close));
return new WebClientSender(WebClient.of(SessionProtocol.H2C, zipkin, postPath));
}
String zipkinUri =
System.getProperty("zipkin.baseUrl", "http://127.0.0.1:9411") + postPath;
return new WebClientSender(WebClient.of(zipkinUri));
}

/** Configuration for how to buffer spans into messages for Zipkin */
static AsyncZipkinSpanHandler spanHandler(Sender sender) {
static AsyncZipkinSpanHandler spanHandler(BytesMessageSender sender) {
final AsyncZipkinSpanHandler spanHandler = AsyncZipkinSpanHandler.create(sender);

Runtime.getRuntime().addShutdownHook(new Thread(() -> {
Expand Down
73 changes: 73 additions & 0 deletions armeria/src/main/java/brave/example/WebClientSender.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Copyright 2016-2024 The OpenZipkin Authors
*
* 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 brave.example;

import com.linecorp.armeria.client.WebClient;
import com.linecorp.armeria.common.AggregatedHttpResponse;
import com.linecorp.armeria.common.HttpData;
import com.linecorp.armeria.common.HttpMethod;
import com.linecorp.armeria.common.HttpRequest;
import com.linecorp.armeria.common.MediaType;
import java.io.IOException;
import java.util.List;
import zipkin2.reporter.BytesMessageEncoder;
import zipkin2.reporter.BytesMessageSender;
import zipkin2.reporter.ClosedSenderException;
import zipkin2.reporter.Encoding;

final class WebClientSender extends BytesMessageSender.Base {
final WebClient client;
final BytesMessageEncoder encoder = BytesMessageEncoder.JSON;
final MediaType mediaType = MediaType.JSON;

WebClientSender(WebClient client) {
super(Encoding.JSON);
this.client = client;
}

@Override public int messageMaxBytes() {
return 500000;
}

/** close is typically called from a different thread */
volatile boolean closeCalled;

/** Sends spans as a POST to the configured endpoint. */
@Override public void send(List<byte[]> encodedSpans) throws IOException {
if (closeCalled) throw new ClosedSenderException();
byte[] body = encoder.encode(encodedSpans);
HttpRequest request =
HttpRequest.of(HttpMethod.POST, "", mediaType, HttpData.wrap(body));
AggregatedHttpResponse response = client.blocking().execute(request);
try (HttpData content = response.content()) {
if (!response.status().isSuccess()) {
if (content.isEmpty()) {
throw new IOException("response failed: " + response);
}
throw new IOException("response for failed: " + content.toStringAscii());
}
}
}

/** Waits up to a second for in-flight requests to finish before cancelling them */
@Override public synchronized void close() {
if (closeCalled) return;
closeCalled = true;
// webclient cannot be closed
}

@Override public String toString() {
return "WebClientSender{" + client + "}";
}
}
59 changes: 59 additions & 0 deletions docker-compose-eureka.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#
# Copyright 2015-2024 The OpenZipkin Authors
#
# 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.
#

# This file uses the version 2 docker-compose file format, described here:
# https://docs.docker.com/compose/compose-file/#version-2
#
# It extends the default configuration from docker-compose.yml to register
# zipkin into a test eureka server.

version: '2.4'

services:
eureka:
image: ghcr.io/openzipkin/zipkin-eureka
container_name: eureka
# Uncomment to expose the eureka port for testing
# ports:
# - 8761:8761

zipkin:
extends:
file: docker-compose.yml
service: zipkin
environment:
- EUREKA_SERVICE_URL=http://eureka:8761/eureka/v2
depends_on:
eureka:
condition: service_healthy

frontend:
extends:
file: docker-compose.yml
service: frontend
environment:
- EUREKA_SERVICE_URL=http://eureka:8761/eureka/v2
depends_on:
eureka:
condition: service_healthy

backend:
extends:
file: docker-compose.yml
service: backend
environment:
- EUREKA_SERVICE_URL=http://eureka:8761/eureka/v2
depends_on:
eureka:
condition: service_healthy
5 changes: 2 additions & 3 deletions docker-compose-kafka.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
---
# Format version 2.1 was introduced with Docker Compose v1.9
# We need Docker Compose v1.9+ for unset variable interpolation
version: "2.1"
# permit depends_on/condition: service_healthy
version: "2.4"

services:
kafka:
Expand Down
13 changes: 6 additions & 7 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,30 +1,29 @@
# Format version 2.1 was introduced with Docker Compose v1.9
# We need Docker Compose v1.9+ for unset variable interpolation
version: "2.1"
# permit depends_on/condition: service_healthy
version: "2.4"

# BRAVE_EXAMPLE choices are listed here https://github.com/openzipkin/brave-example#example-projects

services:
# Generate traffic by hitting http://localhost:8081
frontend:
container_name: frontend
image: ghcr.io/openzipkin/brave-example:${BRAVE_EXAMPLE:-armeria}
image: openzipkin/brave-example:armeria-test
entrypoint: start-frontend
ports:
- 8081:8081
depends_on:
backend:
condition: service_healthy
zipkin:
condition: service_started
condition: service_healthy
# Serves the /api endpoint the frontend uses
backend:
container_name: backend
image: ghcr.io/openzipkin/brave-example:${BRAVE_EXAMPLE:-armeria}
image: openzipkin/brave-example:armeria-test
entrypoint: start-backend
depends_on:
zipkin:
condition: service_started
condition: service_healthy
# View traces at http://127.0.0.1:9411/zipkin
zipkin:
image: ghcr.io/openzipkin/zipkin-slim
Expand Down
14 changes: 14 additions & 0 deletions parent-pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,20 @@
</license>
</licenses>

<repositories>
<repository>
<id>sonatype.snapshots</id>
<name>Sonatype Snapshots</name>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.build.resourceEncoding>UTF-8</project.build.resourceEncoding>
Expand Down

0 comments on commit 2c166e8

Please sign in to comment.