Service dependencies not shown in Jaeger between Spring Boot Applications - spring

I'm currently trying to trace two Spring Boot (2.1.1) applications with Jaeger using https://github.com/opentracing-contrib/java-spring-web
<dependency>
<groupId>io.opentracing.contrib</groupId>
<artifactId>opentracing-spring-web-starter</artifactId>
</dependency>
also tryed with no success
<dependency>
<groupId>io.opentracing.contrib</groupId>
<artifactId>opentracing-spring-jaeger-cloud-starter</artifactId>
</dependency>
The tracing of the Spans for every single service / app works fine, but not over REST requests on a global level.
There is no dependency shown between the services like you can see in the image.
Shouldn't this work out of the box through the library? Or do I have to implement some interceptors and request filters by my own and if so, how?
You can CHECKOUT a minimalistic project containing the problem here
Btw: Jaeger runs as all-in-one via docker and works as expected
docker run \
--rm \
--name jaeger \
-p5775:5775/udp \
-p6831:6831/udp \
-p6832:6832/udp \
-p5778:5778 \
-p16686:16686 \
-p14268:14268 \
-p9411:9411 \
jaegertracing/all-in-one:latest

The problem is that you are using RestTemplate template = new RestTemplate(); to get an instance of the RestTemplate to make a REST call.
Doing that means that Opentracing cannot instrument the call to add necessary HTTP headers.
Please consider using #Autowired RestTemplate restTemplate

Could you try using a more recent version of Jaeger: https://www.jaegertracing.io/docs/latest/getting-started/#all-in-one - actually 1.11 is now out, so could try that.

Related

Client authentication failure on Neo4J

I basically followed the steps described here: https://docs.spring.io/spring-data/neo4j/docs/current/reference/html/#configure-spring-boot-project
My application.properties contains the following:
spring.neo4j.uri=neo4j://localhost:7687
spring.neo4j.authentication.username=neo4j
spring.neo4j.authentication.password=verySecret357
I have a Neo4jConfiguration Bean which only specifies the TransactionManager, rest is (supposedly) taken care of by spring-boot-starter-data-neo4j:
#Configuration
public class Neo4jConfiguration {
#Bean
public ReactiveNeo4jTransactionManager reactiveTransactionManager(Driver driver,
ReactiveDatabaseSelectionProvider databaseNameProvider) {
return new ReactiveNeo4jTransactionManager(driver, databaseNameProvider);
}
}
Neo4j (5.3.0) runs in a Docker container I started with
docker run -d --name neo4j -p 7474:7474 -p 7687:7687 -e 'NEO4J_AUTH=neo4j/verySecret357' neo4j:4.4.11-community
I can access it through HTTP on my localhost:7474 and can authenticate using the credentials above.
Now, when I run my springboot app and try to create Nodes in Neo4j, I keep getting the same exception:
org.neo4j.driver.exceptions.AuthenticationException: The client is unauthorized due to authentication failure.
Running in debug, it however seems the client authentication scheme is correctly set:
Any thoughts on what I might be doing wrong ?
Edit: one thing though, I would assume that the "authToken" would contain a base64-encoded String (username:password) as the scheme is basic auth. It looks like it's not the case (using neo4j-java-driver:5.2.0).
Edit: seems to be related to the Docker image. A standalone neo4j instance works fine.

Jaeger Service not shown in Jaeger UI

I installed the jaeger all in one in Docker with:
docker run --rm --name jaeger -p 5775:5775/udp -p 6831:6831/udp -p 6832:6832/udp -p 5778:5778 -p 16686:16686 -p 14267:14267 -p 14268:14268 -p 9411:9411 jaegertracing/all-in-one:1.7
And below is the sample code on how I initialize the tracer and spans.
I get the logs in my console but it does not reflect in my Jaeger UI.
Could anyone please help me with this?
logging = new LoggingReporter();
SamplerConfiguration sampler = new SamplerConfiguration();
sampler.withType("const");
sampler.withParam(1);
ReporterConfiguration reporter = new ReporterConfiguration();
reporter.withLogSpans(true);
reporter.withSender(sender);
tracer = Configuration.fromEnv("sample_jaeger").withSampler(sampler).withReporter(reporter).getTracer();
Scope scope = tracer.buildSpan("parent-span").startActive(true);
Tags.SAMPLING_PRIORITY.set(scope.span(), 1);
scope.span().setTag("this-is-test", "YUP");
logging.report((JaegerSpan) scope.span());
Are you closing the tracer and the scope? If you are using a version before 0.32.0, you should manually call tracer.close() before your process terminates, otherwise the spans in the buffer might not get dispatched.
As for the scope, it's common to wrap it in a try-with-resources statement:
try (Scope scope = tracer.buildSpan("parent-span").startActive(true)) {
Tags.SAMPLING_PRIORITY.set(scope.span(), 1);
scope.span().setTag("this-is-test", "YUP");
logging.report((JaegerSpan) scope.span());
}
You might also want to check the OpenTracing tutorial at https://github.com/yurishkuro/opentracing-tutorial or the Katacoda-based version at https://www.katacoda.com/courses/opentracing
-- EDIT
and is deployed on a different hostname and port
Then you do need to tell the tracer where to send the traces. Either export the JAEGER_ENDPOINT environment variable, pointing to a collector endpoint, or set JAEGER_AGENT_HOST/JAEGER_AGENT_PORT, with the location of the agent. You can check the available environment variables for your client on the following URL: https://www.jaegertracing.io/docs/1.7/client-features/

Spring Cloud Config refresh configurations

Is it possible to refresh the configurations calling a java method instead to use the REST api:
curl localhost:8080/actuator/refresh -d {} -H "Content-Type: application/json"
You can use the ResartEndpoint class from spring-cloud-context:
#Autowired
private RestartEndpoint restartEndpoint;
...
Thread restartThread = new Thread(() -> restartEndpoint.restart());
restartThread.setDaemon(false);
restartThread.start();
This is how #alexbt suggests to do it. But note that the spring cloud documentation also says you can refresh individual beans provided they are RefreshScope.

Turbine instanceURLSuffix not working

I'm gathering hystrix streams from turbine but the services have the management port enabled on port 5555.
When I set the property in turbine:
eureka.client.serviceUrl.defaultZone=http://discovery:8761/eureka/
server.port=8989
InstanceDiscovery.impl=com.netflix.turbine.discovery.EurekaInstanceDiscovery.class
turbine.instanceUrlSuffix=:5555/hystrix.stream
turbine.InstanceMonitor.eventStream.skipLineLogic.enabled=false
turbine.appConfig=service1,service2,gateway
turbine.clusterNameExpression=new String('default')
it tries to connect to:
http://gateway-ip:10000/:5555/hystrix.stream
instead of replacing the port. Is there something I'm missing?
UPDATE
I suspect there's an incompatibility between the instanceUrlSuffix and the EurekaInstanceDiscovery.
Is there any information I need to put in metadataMap for that service in order to make it work?
Versions are:
Turbine service:
spring-cloud-starter-parent: Brixton.SR5
spring-cloud-starter-turbine: 1.1.6
Eureka service:
spring-cloud-starter-parent: Brixton.SR5
To make it work I had to add these two properties to the configuration:
turbine:
instanceInsertPort: false
instanceUrlSuffix: :5555/hystrix.stream
turbine.instanceInsertPort is what did the trick, composing the final URL from schema://host+urlSuffix
Following worked for me.
Note: Default profile doesn't work for me either, but individual stream works this way.
my service1 is registered to Eureka with -Dserver.port=5151 and -Dmanagement.port=5152 so my hystrix stream is on different port than my service endpoint.
turbine.instanceInsertPort=false
turbine.appConfig=service1
turbine.aggregator.clusterConfig=SERVICE1
turbine.instanceUrlSuffix.USER=:5152/hystrix.stream
InstanceDiscovery.impl=com.netflix.turbine.discovery.EurekaInstanceDiscovery.class
Turbine can not read 'turbine.instanceUrlSuffix' in application.property or environment, it need other lib to read properties.
Did you dependency lib spring-cloud-starter-netflix-hystrix-dashboard or spring-cloud-starter-netflix-archaius? If not, try to add it to your pom.xml.
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
<version>2.2.7.RELEASE</version>
</dependency>

OSGi bundle as external webservice client

I need to call an external webservice from my bundle which is deployed in apache felix container ( I can not use ServiceMix, fuse...)
I added the bundle cxf-dosgi (which can be downloaded from here) and put the following lines in my pom.xml:
<Require-Bundle>cxf-dosgi-ri-singlebundle-distribution</Require-Bundle>
<Import-Package>
javax.jws,
javax.xml.bind,
javax.xml.bind.annotation,
javax.xml.namespace,
javax.xml.ws,
META-INF.cxf,
org.apache.cxf,
org.apache.cxf.binding,
org.apache.cxf.binding.soap,
org.apache.cxf.binding.soap.spring,
org.apache.cxf.bus,
org.apache.cxf.bus.resource,
org.apache.cxf.bus.spring,
org.apache.cxf.buslifecycle,
org.apache.cxf.catalog,
org.apache.cxf.configuration,
org.apache.cxf.configuration.spring,
org.apache.cxf.endpoint,
org.apache.cxf.headers,
org.apache.cxf.management,
org.apache.cxf.phase,
org.apache.cxf.resource,
org.apache.cxf.transport,
org.apache.cxf.transport.http,
org.apache.cxf.transport.http.policy,
org.apache.cxf.transport.http_jetty,
org.apache.cxf.transports.http,
org.apache.cxf.workqueue,
org.apache.cxf.ws.policy.builder.jaxb,
org.apache.cxf.wsdl,
org.apache.cxf.wsdl11,
org.apache.cxf.jaxws.*,
*
</Import-Package>
I use the jaxws way to establish the communication:
QName SERVICE_NAME = new QName("http://test.com/", "MockImplService");
Service service = Service.create(new URL(endpointAddress + "?wsdl"), SERVICE_NAME);
mockService= service.getPort(IMock.class);
When I run the example I have the following exception:
Caused by: javax.xml.ws.spi.FactoryFinder$ConfigurationError: Provider org.apache.axis2.jaxws.spi.Provider not found
at javax.xml.ws.spi.FactoryFinder$2.run(FactoryFinder.java:138)
at javax.xml.ws.spi.FactoryFinder.doPrivileged(FactoryFinder.java:282)
at javax.xml.ws.spi.FactoryFinder.newInstance(FactoryFinder.java:125)
at javax.xml.ws.spi.FactoryFinder.access$200(FactoryFinder.java:42)
at javax.xml.ws.spi.FactoryFinder$3.run(FactoryFinder.java:273)
at javax.xml.ws.spi.FactoryFinder.doPrivileged(FactoryFinder.java:282)
at javax.xml.ws.spi.FactoryFinder.find(FactoryFinder.java:168)
at javax.xml.ws.spi.Provider.provider(Provider.java:39)
at javax.xml.ws.Service.<init>(Service.java:36)
at javax.xml.ws.Service.create(Service.java:116)
any idea please ?
Apache DOSGi is designed for exposing services as webservices, not for calling other webservices. Though, it probably contains some api to call other webservices.
Somehow the axis jaxws implementation is used. You probably have a axis2-jaxws-xxx.jar on your classpath. Try to remove it. The JRA jaxws will be used instead (which should be fine for axis and better for cxf).

Resources