Add strategy EndpointLocator to help with service host/port location

This commit is contained in:
Dave Syer
2015-10-01 11:52:28 +01:00
parent 1d8d5a0956
commit 4e21bf1b35
11 changed files with 263 additions and 81 deletions

View File

@@ -10,7 +10,7 @@ include::intro.adoc[]
----
logging:
pattern:
console: '%d{yyyy-MM-dd HH:mm:ss.SSS} [trace=%X{X-Trace-Id:-},span=%X{X-Span-Id:-}] [%15.15t] %-40.40logger{39}: %m%n'
level: '[trace=%X{X-Trace-Id:-},span=%X{X-Span-Id:-}] %5p'
----
+
(notice the `%X` entries from the MDC).

View File

@@ -11,7 +11,7 @@ spring:
logging:
pattern:
console: '%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p) %clr(${PID:- }){magenta} %clr(---){faint} %clr([trace=%X{X-Trace-Id:-},span=%X{X-Span-Id:-}]){yellow} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n%wex'
level: '%clr([trace=%X{X-Trace-Id:-},span=%X{X-Span-Id:-}]){yellow} %5p'
sample:
zipkin:

View File

@@ -37,4 +37,4 @@ zuul:
logging:
pattern:
console: '%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p) %clr(${PID:- }){magenta} %clr(---){faint} %clr([trace=%X{X-Trace-Id:-},span=%X{X-Span-Id:-}]){yellow} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n%wex'
level: '%clr([trace=%X{X-Trace-Id:-},span=%X{X-Span-Id:-}]){yellow} %5p'

View File

@@ -7,7 +7,7 @@ spring:
logging:
pattern:
console: '%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p) %clr(${PID:- }){magenta} %clr(---){faint} %clr([trace=%X{X-Trace-Id:-},span=%X{X-Span-Id:-}]){yellow} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n%wex'
level: '%clr([trace=%X{X-Trace-Id:-},span=%X{X-Span-Id:-}]){yellow} %5p'
sample:
zipkin:

View File

@@ -11,4 +11,4 @@ spring:
logging:
pattern:
console: '%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p) %clr(${PID:- }){magenta} %clr(---){faint} %clr([trace=%X{X-Trace-Id:-},span=%X{X-Span-Id:-}]){yellow} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n%wex'
level: '%clr([trace=%X{X-Trace-Id:-},span=%X{X-Span-Id:-}]){yellow} %5p'

View File

@@ -37,9 +37,19 @@
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<artifactId>spring-boot-actuator</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
<optional>true</optional>
</dependency>
<dependency>
@@ -47,18 +57,6 @@
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.github.kristofa</groupId>
<artifactId>brave-core</artifactId>
</dependency>
<dependency>
<groupId>com.github.kristofa</groupId>
<artifactId>brave-http</artifactId>
</dependency>
<dependency>
<groupId>com.github.kristofa</groupId>
<artifactId>brave-core-spring</artifactId>
</dependency>
<dependency>
<groupId>com.github.kristofa</groupId>
<artifactId>brave-zipkin-spancollector</artifactId>

View File

@@ -0,0 +1,60 @@
/*
* Copyright 2015 the original author or 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 org.springframework.cloud.sleuth.zipkin;
import java.net.InetAddress;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.util.InetUtils;
import com.twitter.zipkin.gen.Endpoint;
/**
* An {@link EndpointLocator} that tries to find local service information from a
* {@link DiscoveryClient}.
*
* @author Dave Syer
*
*/
public class DiscoveryClientEndpointLocator implements EndpointLocator {
private DiscoveryClient client;
public DiscoveryClientEndpointLocator(DiscoveryClient client) {
this.client = client;
}
@Override
public Endpoint locate(Span span) {
ServiceInstance instance = this.client.getLocalServiceInstance();
return new Endpoint(getIpAddress(instance),
new Integer(instance.getPort()).shortValue(), instance.getServiceId());
}
private int getIpAddress(ServiceInstance instance) {
try {
InetAddress address = InetAddress.getByName(instance.getHost());
return InetUtils.convert(address).getIpAddressAsInt();
}
catch (Exception e) {
return 0;
}
}
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2015 the original author or 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 org.springframework.cloud.sleuth.zipkin;
import org.springframework.cloud.sleuth.Span;
import com.twitter.zipkin.gen.Endpoint;
/**
* Strategy for locating a Brave "Endpoin" from a Spring Cloud Span (and whatever other
* environment properties might be available).
*
* @author Dave Syer
*
*/
public interface EndpointLocator {
Endpoint locate(Span span);
}

View File

@@ -0,0 +1,109 @@
/*
* Copyright 2015 the original author or 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 org.springframework.cloud.sleuth.zipkin;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.context.embedded.EmbeddedServletContainerInitializedEvent;
import org.springframework.cloud.sleuth.Span;
import org.springframework.context.event.EventListener;
import com.twitter.zipkin.gen.Endpoint;
/**
* @author Dave Syer
*
*/
public class ServerPropertiesEndpointLocator implements EndpointLocator {
@Value("${spring.application.name:application}")
private String appName;
private ServerProperties serverProperties;
private Integer port;
public ServerPropertiesEndpointLocator(ServerProperties serverProperties) {
this.serverProperties = serverProperties;
}
@Override
public Endpoint locate(Span span) {
String serviceName = getServiceName(span);
int address = getAddress();
Integer port = getPort();
Endpoint ep = new Endpoint(address, port.shortValue(), serviceName);
return ep;
}
@EventListener(EmbeddedServletContainerInitializedEvent.class)
public void grabPort(EmbeddedServletContainerInitializedEvent event) {
this.port = event.getEmbeddedServletContainer().getPort();
}
private Integer getPort() {
if (this.port!=null) {
return this.port;
}
Integer port;
if (this.serverProperties!=null && this.serverProperties.getPort() != null) {
port = this.serverProperties.getPort();
}
else {
port = 8080;
}
return port;
}
private int getAddress() {
String address;
if (this.serverProperties!=null && this.serverProperties.getAddress() != null) {
address = this.serverProperties.getAddress().getHostAddress();
}
else {
address = "127.0.0.1";
}
return ipAddressToInt(address);
}
private String getServiceName(Span span) {
String serviceName;
if (span.getProcessId() != null) {
serviceName = span.getProcessId().toLowerCase();
}
else {
serviceName = this.appName;
}
return serviceName;
}
private int ipAddressToInt(final String ip) {
InetAddress inetAddress = null;
try {
inetAddress = InetAddress.getByName(ip);
}
catch (final UnknownHostException e) {
throw new IllegalArgumentException(e);
}
return ByteBuffer.wrap(inetAddress.getAddress()).getInt();
}
}

View File

@@ -16,10 +16,14 @@
package org.springframework.cloud.sleuth.zipkin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -50,10 +54,42 @@ public class ZipkinAutoConfiguration {
}
@Bean
// @ConditionalOnProperty(value = "spring.sleuth.zipkin.braveTracer.enabled",
// havingValue = "false")
public ZipkinSpanListener sleuthTracer(SpanCollector spanCollector) {
return new ZipkinSpanListener(spanCollector);
public ZipkinSpanListener sleuthTracer(SpanCollector spanCollector, EndpointLocator endpointLocator) {
return new ZipkinSpanListener(spanCollector, endpointLocator);
}
@Configuration
@ConditionalOnMissingClass("org.springframework.cloud.client.discovery.DiscoveryClient")
protected static class DefaultEndpointLocatorConfiguration {
@Autowired(required=false)
private ServerProperties serverProperties;
@Bean
public EndpointLocator zipkinEndpointLocator() {
return new ServerPropertiesEndpointLocator(this.serverProperties);
}
}
@Configuration
@ConditionalOnClass(DiscoveryClient.class)
protected static class DiscoveryClientEndpointLocatorConfiguration {
@Autowired(required=false)
private ServerProperties serverProperties;
@Autowired(required=false)
private DiscoveryClient client;
@Bean
public EndpointLocator zipkinEndpointLocator() {
if (this.client!=null) {
return new DiscoveryClientEndpointLocator(this.client);
}
return new ServerPropertiesEndpointLocator(this.serverProperties);
}
}
}

View File

@@ -17,16 +17,10 @@
package org.springframework.cloud.sleuth.zipkin;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.TimelineAnnotation;
import org.springframework.cloud.sleuth.event.ClientReceivedEvent;
@@ -55,13 +49,11 @@ import lombok.extern.apachecommons.CommonsLog;
public class ZipkinSpanListener {
private SpanCollector spanCollector;
@Value("${spring.application.name:application}")
private String appName;
@Autowired(required=false)
private ServerProperties serverProperties;
private EndpointLocator endpointLocator;
public ZipkinSpanListener(SpanCollector spanCollector) {
public ZipkinSpanListener(SpanCollector spanCollector, EndpointLocator endpointLocator) {
this.spanCollector = spanCollector;
this.endpointLocator = endpointLocator;
}
@EventListener
@@ -117,11 +109,7 @@ public class ZipkinSpanListener {
public com.twitter.zipkin.gen.Span convert(Span span) {
com.twitter.zipkin.gen.Span zipkinSpan = new com.twitter.zipkin.gen.Span();
String serviceName = getServiceName(span);
int address = getAddress();
Integer port = getPort();
Endpoint ep = new Endpoint(address, port.shortValue(), serviceName);
Endpoint ep = this.endpointLocator.locate(span);
List<Annotation> annotationList = createZipkinAnnotations(span, ep);
List<BinaryAnnotation> binaryAnnotationList = createZipkinBinaryAnnotations(span,
ep);
@@ -142,49 +130,6 @@ public class ZipkinSpanListener {
return zipkinSpan;
}
public Integer getPort() {
Integer port;
if (this.serverProperties!=null && this.serverProperties.getPort() != null) {
port = this.serverProperties.getPort();
}
else {
port = 8080; // TODO: support random port
}
return port;
}
public int getAddress() {
String address;
if (this.serverProperties!=null && this.serverProperties.getAddress() != null) {
address = this.serverProperties.getAddress().getHostAddress();
}
else {
address = "127.0.0.1"; // TODO: get address from config
}
return ipAddressToInt(address);
}
public String getServiceName(Span span) {
String serviceName;
if (span.getProcessId() != null) {
serviceName = span.getProcessId().toLowerCase();
}
else {
serviceName = this.appName;
}
return serviceName;
}
private int ipAddressToInt(final String ip) {
InetAddress inetAddress = null;
try {
inetAddress = InetAddress.getByName(ip);
}
catch (final UnknownHostException e) {
throw new IllegalArgumentException(e);
}
return ByteBuffer.wrap(inetAddress.getAddress()).getInt();
}
/**
* Add annotations from the sleuth Span.