Skip to content
This repository has been archived by the owner on Jul 1, 2022. It is now read-only.

Initial implementation of a TracerResolver for Jaeger #175

Merged
merged 7 commits into from
May 14, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ ext.jerseyVersion = '2.22.2'
ext.slf4jVersion = '1.7.16'
ext.apacheHttpComponentsVersion = '4.1.2'
ext.gsonVersion = '2.8.0'
ext.tracerResolverVersion = '0.1.0'

ext.junitVersion = '4.12'
ext.mockitoVersion = '2.2.28'
Expand Down
36 changes: 36 additions & 0 deletions jaeger-core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,42 @@ Tracer tracer = config.getTracer();

The `config` objects lazily builds and configures Jaeger Tracer. Multiple calls to `getTracer()` return the same instance.


#### Configuration via Environment

It is also possible to obtain a `com.uber.jaeger.Configuration` object configured using properties specified
as environment variables or system properties. A value specified as a system property will override a value
specified as an environment variable for the same property name.

```java
Configuration config = Configuration.fromEnv();
```

The property names are:

Property | Required | Description
--- | --- | ---
JAEGER_SERVICE_NAME | yes | The service name
JAEGER_AGENT_HOST | no | The hostname for communicating with agent via UDP
JAEGER_AGENT_PORT | no | The port for communicating with agent via UDP
JAEGER_REPORTER_LOG_SPANS | no | Whether the reporter should also log the spans
JAEGER_REPORTER_MAX_QUEUE_SIZE | no | The reporter's maximum queue size
JAEGER_REPORTER_FLUSH_INTERVAL | no | The reporter's flush interval (ms)
JAEGER_SAMPLER_TYPE | no | The sampler type
JAEGER_SAMPLER_PARAM | no | The sampler parameter (number)
JAEGER_SAMPLER_MANAGER_HOST_PORT | no | The host name and port when using the remote controlled sampler


#### Obtaining Tracer via TracerResolver

Jaeger's Java Client also provides an implementation of the
[TracerResolver](https://github.com/opentracing-contrib/java-tracerresolver), allowing a `Tracer` to be
obtained in a vendor neutral manner. This `TracerResolver` implementation uses the configuration via
environment approach described above.

More information about using the `TracerResolver` can be found [here](../jaeger-tracerresolver/README.md).


### Development

The last two parameters to `new Configuration()` allow control over configuration of the Sampler and Reporter.
Expand Down
112 changes: 112 additions & 0 deletions jaeger-core/src/main/java/com/uber/jaeger/Configuration.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,66 @@
import com.uber.jaeger.samplers.RemoteControlledSampler;
import com.uber.jaeger.samplers.Sampler;
import com.uber.jaeger.senders.UdpSender;

import java.text.NumberFormat;
import java.text.ParseException;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class Configuration {
public static final double DEFAULT_SAMPLING_PROBABILITY = 0.001;

/**
* Prefix for all properties used to configure the Jaeger tracer.
*/
public static final String JAEGER_PREFIX = "JAEGER_";

/**
* The host name used to locate the agent.
*/
public static final String JAEGER_AGENT_HOST = JAEGER_PREFIX + "AGENT_HOST";

/**
* The port used to locate the agent.
*/
public static final String JAEGER_AGENT_PORT = JAEGER_PREFIX + "AGENT_PORT";

/**
* Whether the reporter should log the spans.
*/
public static final String JAEGER_REPORTER_LOG_SPANS = JAEGER_PREFIX + "REPORTER_LOG_SPANS";

/**
* The maximum queue size for use when reporting spans remotely.
*/
public static final String JAEGER_REPORTER_MAX_QUEUE_SIZE = JAEGER_PREFIX + "REPORTER_MAX_QUEUE_SIZE";

/**
* The flush interval when reporting spans remotely.
*/
public static final String JAEGER_REPORTER_FLUSH_INTERVAL = JAEGER_PREFIX + "REPORTER_FLUSH_INTERVAL";

/**
* The sampler type.
*/
public static final String JAEGER_SAMPLER_TYPE = JAEGER_PREFIX + "SAMPLER_TYPE";

/**
* The sampler parameter (number).
*/
public static final String JAEGER_SAMPLER_PARAM = "JAEGER_SAMPLER_PARAM";

/**
* The sampler manager host:port.
*/
public static final String JAEGER_SAMPLER_MANAGER_HOST_PORT = JAEGER_PREFIX + "SAMPLER_MANAGER_HOST_PORT";

/**
* The service name.
*/
public static final String JAEGER_SERVICE_NAME = JAEGER_PREFIX + "SERVICE_NAME";

/**
* The serviceName that the tracer will use
*/
Expand Down Expand Up @@ -85,6 +139,27 @@ public Configuration(
statsFactory = new StatsFactoryImpl(new NullStatsReporter());
}

public static Configuration fromEnv() {
return new Configuration(getProperty(JAEGER_SERVICE_NAME),
getSamplerConfigurationFromEnv(), getReporterConfigurationFromEnv());
}

static ReporterConfiguration getReporterConfigurationFromEnv() {
return new ReporterConfiguration(
getPropertyAsBoolean(JAEGER_REPORTER_LOG_SPANS),
getProperty(JAEGER_AGENT_HOST),
getPropertyAsInt(JAEGER_AGENT_PORT),
getPropertyAsInt(JAEGER_REPORTER_FLUSH_INTERVAL),
getPropertyAsInt(JAEGER_REPORTER_MAX_QUEUE_SIZE));
}

static SamplerConfiguration getSamplerConfigurationFromEnv() {
return new SamplerConfiguration(
getProperty(JAEGER_SAMPLER_TYPE),
getPropertyAsNum(JAEGER_SAMPLER_PARAM),
getProperty(JAEGER_SAMPLER_MANAGER_HOST_PORT));
}

public Tracer.Builder getTracerBuilder() {
Metrics metrics = new Metrics(statsFactory);
Reporter reporter = reporterConfig.getReporter(metrics);
Expand Down Expand Up @@ -282,4 +357,41 @@ private static String stringOrDefault(String value, String defaultValue) {
private static Number numberOrDefault(Number value, Number defaultValue) {
return value != null ? value : defaultValue;
}

private static String getProperty(String name) {
return System.getProperty(name, System.getenv(name));
}

private static Integer getPropertyAsInt(String name) {
String value = getProperty(name);
if (value != null) {
try {
return Integer.parseInt(value);
} catch (NumberFormatException e) {
log.error("Failed to parse integer for property '" + name + "' with value '" + value + "'", e);
}
}
return null;
}

private static Number getPropertyAsNum(String name) {
String value = getProperty(name);
if (value != null) {
try {
return NumberFormat.getInstance().parse(value);
} catch (ParseException e) {
log.error("Failed to parse number for property '" + name + "' with value '" + value + "'", e);
}
}
return null;
}

private static Boolean getPropertyAsBoolean(String name) {
String value = getProperty(name);
if (value != null) {
return Boolean.valueOf(value);
}
return null;
}

}
109 changes: 109 additions & 0 deletions jaeger-core/src/test/java/com/uber/jaeger/ConfigurationTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* Copyright (c) 2017, Uber Technologies, Inc
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

package com.uber.jaeger;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import com.uber.jaeger.Configuration.ReporterConfiguration;
import com.uber.jaeger.Configuration.SamplerConfiguration;
import com.uber.jaeger.samplers.ConstSampler;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class ConfigurationTest {

@Before
@After
public void clearProperties() {
// Explicitly clear all properties
System.clearProperty(Configuration.JAEGER_AGENT_HOST);
System.clearProperty(Configuration.JAEGER_AGENT_PORT);
System.clearProperty(Configuration.JAEGER_REPORTER_LOG_SPANS);
System.clearProperty(Configuration.JAEGER_REPORTER_MAX_QUEUE_SIZE);
System.clearProperty(Configuration.JAEGER_REPORTER_FLUSH_INTERVAL);
System.clearProperty(Configuration.JAEGER_SAMPLER_TYPE);
System.clearProperty(Configuration.JAEGER_SAMPLER_PARAM);
System.clearProperty(Configuration.JAEGER_SAMPLER_MANAGER_HOST_PORT);
System.clearProperty(Configuration.JAEGER_SERVICE_NAME);
}

@Test
public void testFromEnv() {
System.setProperty(Configuration.JAEGER_SERVICE_NAME, "Test");
assertNotNull(Configuration.fromEnv().getTracer());
}

@Test
public void testSamplerConst() {
System.setProperty(Configuration.JAEGER_SAMPLER_TYPE, ConstSampler.TYPE);
System.setProperty(Configuration.JAEGER_SAMPLER_PARAM, "1");
SamplerConfiguration samplerConfig = Configuration.getSamplerConfigurationFromEnv();
assertEquals(ConstSampler.TYPE, samplerConfig.getType());
assertEquals(1, samplerConfig.getParam().intValue());
}

@Test
public void testSamplerConstInvalidParam() {
System.setProperty(Configuration.JAEGER_SAMPLER_TYPE, ConstSampler.TYPE);
System.setProperty(Configuration.JAEGER_SAMPLER_PARAM, "X");
SamplerConfiguration samplerConfig = Configuration.getSamplerConfigurationFromEnv();
assertEquals(ConstSampler.TYPE, samplerConfig.getType());
assertNull(samplerConfig.getParam());
}

@Test
public void testReporterConfiguration() {
System.setProperty(Configuration.JAEGER_REPORTER_LOG_SPANS, "true");
System.setProperty(Configuration.JAEGER_AGENT_HOST, "MyHost");
System.setProperty(Configuration.JAEGER_AGENT_PORT, "1234");
System.setProperty(Configuration.JAEGER_REPORTER_FLUSH_INTERVAL, "500");
System.setProperty(Configuration.JAEGER_REPORTER_MAX_QUEUE_SIZE, "1000");
ReporterConfiguration reporterConfig = Configuration.getReporterConfigurationFromEnv();
assertTrue(reporterConfig.getLogSpans());
assertEquals("MyHost", reporterConfig.getAgentHost());
assertEquals(1234, reporterConfig.getAgentPort().intValue());
assertEquals(500, reporterConfig.getFlushIntervalMs().intValue());
assertEquals(1000, reporterConfig.getMaxQueueSize().intValue());
}

@Test
public void testReporterConfigurationInvalidFlushInterval() {
System.setProperty(Configuration.JAEGER_REPORTER_FLUSH_INTERVAL, "X");
ReporterConfiguration reporterConfig = Configuration.getReporterConfigurationFromEnv();
assertNull(reporterConfig.getFlushIntervalMs());
}

@Test
public void testReporterConfigurationInvalidLogSpans() {
System.setProperty(Configuration.JAEGER_REPORTER_LOG_SPANS, "X");
ReporterConfiguration reporterConfig = Configuration.getReporterConfigurationFromEnv();
assertFalse(reporterConfig.getLogSpans());
}

}
23 changes: 23 additions & 0 deletions jaeger-tracerresolver/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Jaeger Tracer Resolver
Copy link
Contributor

@mabn mabn May 10, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to have here a short comment describing what it is


This module provides a Jaeger implementation for the [TracerResolver](https://github.com/opentracing-contrib/java-tracerresolver). This mechanism provides a vendor neutral approach for obtaining a `Tracer` using the JDK
`ServiceLoader`.


## Maven Dependency
```xml
<dependency>
<groupId>com.uber.jaeger</groupId>
<artifactId>jaeger-tracerresolver</artifactId>
<version>$jaegerVersion</version>
</dependency>
```

## Usage

```java
Tracer tracer = TracerResolver.resolveTracer();
```

This tracer is configured via environment variables (or system properties). The properties are
described [here](../jaeger-core/README.md).
17 changes: 17 additions & 0 deletions jaeger-tracerresolver/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
description = 'TracerResolver implementation for Jaeger Tracer'

dependencies {
compile project(':jaeger-core')
compile group: 'io.opentracing.contrib', name: 'opentracing-tracerresolver', version: tracerResolverVersion

testCompile group: 'junit', name: 'junit', version: junitVersion

signature 'org.codehaus.mojo.signature:java16:1.1@signature'
}

jar {
from sourceSets.main.output
manifest {
attributes('Implementation-Title': 'jaeger-tracerresolver', 'Implementation-Version': project.version)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't be this added to allProjects in root script?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's repeated in every module.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If its possible then sounds like a good idea, but outside the remit of this PR.

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright (c) 2017, Uber Technologies, Inc
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

package com.uber.jaeger.tracerresolver;

import com.uber.jaeger.Configuration;

import io.opentracing.contrib.tracerresolver.TracerResolver;

public class JaegerTracerResolver extends TracerResolver {

@Override
protected io.opentracing.Tracer resolve() {
return Configuration.fromEnv().getTracer();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
com.uber.jaeger.tracerresolver.JaegerTracerResolver
Loading