diff --git a/idl b/idl index 23f33f2d1..c5adbc983 160000 --- a/idl +++ b/idl @@ -1 +1 @@ -Subproject commit 23f33f2d162607dd4b2177e7ebcfe78d4f9717bc +Subproject commit c5adbc98341c5228472af96ea612c54173a3ec2e diff --git a/jaeger-core/src/main/java/com/uber/jaeger/Span.java b/jaeger-core/src/main/java/com/uber/jaeger/Span.java index 11aff3b4a..bc7f15670 100644 --- a/jaeger-core/src/main/java/com/uber/jaeger/Span.java +++ b/jaeger-core/src/main/java/com/uber/jaeger/Span.java @@ -22,7 +22,6 @@ package com.uber.jaeger; -import com.uber.jaeger.baggage.BaggageSetter; import io.opentracing.tag.Tags; import java.util.ArrayList; import java.util.Collections; @@ -106,6 +105,12 @@ public String getOperationName() { } } + public String getServiceName() { + synchronized (this) { + return this.getTracer().getServiceName(); + } + } + public List getLogs() { synchronized (this) { if (logs == null) { diff --git a/jaeger-core/src/main/java/com/uber/jaeger/baggage/BaggageRestrictionManagerProxy.java b/jaeger-core/src/main/java/com/uber/jaeger/baggage/BaggageRestrictionManagerProxy.java new file mode 100644 index 000000000..c61895567 --- /dev/null +++ b/jaeger-core/src/main/java/com/uber/jaeger/baggage/BaggageRestrictionManagerProxy.java @@ -0,0 +1,37 @@ +/* + * 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.baggage; + +import com.uber.jaeger.baggage.http.BaggageRestrictionResponse; +import com.uber.jaeger.exceptions.BaggageRestrictionManagerException; + +import java.util.List; + +/** + * BaggageRestrictionManagerProxy is an interface for a class that fetches baggage + * restrictions for specific service from a remote source i.e. jaeger-agent. + */ +public interface BaggageRestrictionManagerProxy { + List getBaggageRestrictions(String serviceName) + throws BaggageRestrictionManagerException; +} diff --git a/jaeger-core/src/main/java/com/uber/jaeger/baggage/BaggageSetter.java b/jaeger-core/src/main/java/com/uber/jaeger/baggage/BaggageSetter.java index 2405f3654..3f145aa18 100644 --- a/jaeger-core/src/main/java/com/uber/jaeger/baggage/BaggageSetter.java +++ b/jaeger-core/src/main/java/com/uber/jaeger/baggage/BaggageSetter.java @@ -58,7 +58,7 @@ public BaggageSetter(BaggageRestrictionManager restrictionManager, Metrics metri * @return the SpanContext with the baggage set */ public SpanContext setBaggage(Span span, String key, String value) { - Restriction restriction = restrictionManager.getRestriction(span.getTracer().getServiceName(), key); + Restriction restriction = restrictionManager.getRestriction(span.getServiceName(), key); boolean truncated = false; String prevItem = null; if (!restriction.isKeyAllowed()) { diff --git a/jaeger-core/src/main/java/com/uber/jaeger/baggage/HttpBaggageRestrictionManagerProxy.java b/jaeger-core/src/main/java/com/uber/jaeger/baggage/HttpBaggageRestrictionManagerProxy.java new file mode 100644 index 000000000..89b6ede40 --- /dev/null +++ b/jaeger-core/src/main/java/com/uber/jaeger/baggage/HttpBaggageRestrictionManagerProxy.java @@ -0,0 +1,71 @@ +/* + * 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.baggage; + +import static com.uber.jaeger.utils.Http.makeGetRequest; + +import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; +import com.google.gson.reflect.TypeToken; +import com.uber.jaeger.baggage.http.BaggageRestrictionResponse; +import com.uber.jaeger.exceptions.BaggageRestrictionManagerException; + +import java.io.IOException; +import java.lang.reflect.Type; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.List; + +public class HttpBaggageRestrictionManagerProxy implements BaggageRestrictionManagerProxy { + private static final String DEFAULT_HOST_PORT = "localhost:5778"; + private final Gson gson = new Gson(); + private final String hostPort; + + public HttpBaggageRestrictionManagerProxy(String hostPort) { + this.hostPort = hostPort != null ? hostPort : DEFAULT_HOST_PORT; + } + + List parseJson(String json) throws BaggageRestrictionManagerException { + try { + Type listType = new TypeToken>(){}.getType(); + return gson.fromJson(json, listType); + } catch (JsonSyntaxException e) { + throw new BaggageRestrictionManagerException("Cannot deserialize json", e); + } + } + + @Override + public List getBaggageRestrictions(String serviceName) + throws BaggageRestrictionManagerException { + String jsonString; + try { + jsonString = + makeGetRequest( + "http://" + hostPort + "/baggageRestrictions?service=" + URLEncoder.encode(serviceName, "UTF-8")); + } catch (IOException e) { + throw new BaggageRestrictionManagerException( + "http call to get baggage restriction from local agent failed.", e); + } + return parseJson(jsonString); + } +} diff --git a/jaeger-core/src/main/java/com/uber/jaeger/baggage/RemoteBaggageRestrictionManager.java b/jaeger-core/src/main/java/com/uber/jaeger/baggage/RemoteBaggageRestrictionManager.java new file mode 100644 index 000000000..02c4d8eb8 --- /dev/null +++ b/jaeger-core/src/main/java/com/uber/jaeger/baggage/RemoteBaggageRestrictionManager.java @@ -0,0 +1,167 @@ +/* + * 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.baggage; + +import com.uber.jaeger.baggage.http.BaggageRestrictionResponse; +import com.uber.jaeger.exceptions.BaggageRestrictionManagerException; +import com.uber.jaeger.metrics.Metrics; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Timer; +import java.util.TimerTask; + +/** + * NewRestrictionManager returns a BaggageRestrictionManager that polls the agent for the latest + * baggage restrictions. + */ +public class RemoteBaggageRestrictionManager implements BaggageRestrictionManager { + private static final int DEFAULT_REFRESH_INTERVAL_MS = 60000; + private static final int DEFAULT_INITIAL_DELAY_MS = 0; + + private final String serviceName; + private final BaggageRestrictionManagerProxy proxy; + private final Timer pollTimer; + private final Metrics metrics; + private final boolean denyBaggageOnInitializationFailure; + private volatile boolean initialized; + private volatile Map restrictions = new HashMap(); + private final Restriction invalidRestriction; + private final Restriction validRestriction; + + public RemoteBaggageRestrictionManager( + String serviceName, + BaggageRestrictionManagerProxy proxy, + Metrics metrics, + boolean denyBaggageOnInitializationFailure + ) { + this(serviceName, proxy, metrics, denyBaggageOnInitializationFailure, DEFAULT_REFRESH_INTERVAL_MS); + } + + public RemoteBaggageRestrictionManager( + String serviceName, + BaggageRestrictionManagerProxy proxy, + Metrics metrics, + boolean denyBaggageOnInitializationFailure, + int refreshIntervalMs + ) { + this(serviceName, proxy, metrics, denyBaggageOnInitializationFailure, refreshIntervalMs, DEFAULT_INITIAL_DELAY_MS); + } + + /** + * Creates a RemoteBaggageRestrictionManager that fetches {@link BaggageRestrictionResponse} from a remote + * agent and keeps track of {@link Restriction} for a service. + * + * {@param initialDelayMs} is only exposed for testing purposes so users can determine when the first call to + * remote agent is made. Under normal operations, this RemoteBaggageRestrictionManager will start up and + * asynchronously fetch restrictions. If the user wants to know if restrictions are ready, they can check via + * isReady(). + * + * @param serviceName restrictions for this service are kept track of. + * @param proxy proxy to remote agent. + * @param metrics metrics for metrics emission. + * @param denyBaggageOnInitializationFailure determines the startup failure mode of RemoteBaggageRestrictionManager. + * If DenyBaggageOnInitializationFailure is true, + * RemoteBaggageRestrictionManager will not allow any baggage to be written + * until baggage restrictions have been retrieved from agent. If + * DenyBaggageOnInitializationFailure is false, + * RemoteBaggageRestrictionManager will allow any baggage to be written + * until baggage restrictions have been retrieved from agent. + * @param refreshIntervalMs how often restriction are fetched from remote agent. + * @param initialDelayMs delay before first fetch of restrictions. + */ + RemoteBaggageRestrictionManager( + String serviceName, + BaggageRestrictionManagerProxy proxy, + Metrics metrics, + boolean denyBaggageOnInitializationFailure, + int refreshIntervalMs, + int initialDelayMs + ) { + this.serviceName = serviceName; + this.proxy = proxy; + this.metrics = metrics; + this.denyBaggageOnInitializationFailure = denyBaggageOnInitializationFailure; + this.initialized = false; + this.invalidRestriction = Restriction.of(false, 0); + this.validRestriction = Restriction.of(true, DEFAULT_MAX_VALUE_LENGTH); + + pollTimer = new Timer(true); // true makes this a daemon thread + pollTimer.schedule( + new TimerTask() { + @Override + public void run() { + updateBaggageRestrictions(); + } + }, + initialDelayMs, + refreshIntervalMs); + } + + public boolean isReady() { + return initialized; + } + + void updateBaggageRestrictions() { + List response; + try { + response = proxy.getBaggageRestrictions(serviceName); + } catch (BaggageRestrictionManagerException e) { + metrics.baggageRestrictionsUpdateFailure.inc(1); + return; + } + + updateBaggageRestrictions(response); + metrics.baggageRestrictionsUpdateSuccess.inc(1); + } + + private void updateBaggageRestrictions(List restrictions) { + Map baggageRestrictions = new HashMap(); + for (BaggageRestrictionResponse restriction : restrictions) { + baggageRestrictions.put(restriction.getBaggageKey(), Restriction.of(true, restriction.getMaxValueLength())); + } + this.restrictions = baggageRestrictions; + initialized = true; + } + + public void close() { + pollTimer.cancel(); + } + + @Override + public Restriction getRestriction(String service, String key) { + if (!initialized) { + if (denyBaggageOnInitializationFailure) { + return invalidRestriction; + } else { + return validRestriction; + } + } + Restriction restriction = this.restrictions.get(key); + if (restriction != null) { + return restriction; + } + return invalidRestriction; + } +} diff --git a/jaeger-core/src/main/java/com/uber/jaeger/baggage/http/BaggageRestrictionResponse.java b/jaeger-core/src/main/java/com/uber/jaeger/baggage/http/BaggageRestrictionResponse.java new file mode 100644 index 000000000..d00626d1f --- /dev/null +++ b/jaeger-core/src/main/java/com/uber/jaeger/baggage/http/BaggageRestrictionResponse.java @@ -0,0 +1,31 @@ +/* + * 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.baggage.http; + +import lombok.Value; + +@Value +public class BaggageRestrictionResponse { + String baggageKey; + int maxValueLength; +} diff --git a/jaeger-core/src/main/java/com/uber/jaeger/exceptions/BaggageRestrictionManagerException.java b/jaeger-core/src/main/java/com/uber/jaeger/exceptions/BaggageRestrictionManagerException.java new file mode 100644 index 000000000..c58dd30e6 --- /dev/null +++ b/jaeger-core/src/main/java/com/uber/jaeger/exceptions/BaggageRestrictionManagerException.java @@ -0,0 +1,35 @@ +/* + * 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.exceptions; + +import java.io.IOException; + +public class BaggageRestrictionManagerException extends IOException { + public BaggageRestrictionManagerException(String msg) { + super(msg); + } + + public BaggageRestrictionManagerException(String msg, Throwable cause) { + super(msg, cause); + } +} diff --git a/jaeger-core/src/main/java/com/uber/jaeger/metrics/Metrics.java b/jaeger-core/src/main/java/com/uber/jaeger/metrics/Metrics.java index 44542656d..e02da6d47 100644 --- a/jaeger-core/src/main/java/com/uber/jaeger/metrics/Metrics.java +++ b/jaeger-core/src/main/java/com/uber/jaeger/metrics/Metrics.java @@ -229,4 +229,18 @@ public static Metrics fromStatsReporter(StatsReporter reporter) { @Metric(name = "baggage-truncate") // Number of times baggage was truncated as per baggage restrictions public Counter baggageTruncate; + + @Metric( + name = "baggage-restrictions-update", + tags = {@Tag(key = "result", value = "ok")} + ) + // Number of times baggage restrictions were successfully updated + public Counter baggageRestrictionsUpdateSuccess; + + @Metric( + name = "baggage-restrictions-update", + tags = {@Tag(key = "result", value = "err")} + ) + // Number of times baggage restrictions failed to update + public Counter baggageRestrictionsUpdateFailure; } diff --git a/jaeger-core/src/main/java/com/uber/jaeger/samplers/HttpSamplingManager.java b/jaeger-core/src/main/java/com/uber/jaeger/samplers/HttpSamplingManager.java index 9ece37a8c..278ff5c00 100644 --- a/jaeger-core/src/main/java/com/uber/jaeger/samplers/HttpSamplingManager.java +++ b/jaeger-core/src/main/java/com/uber/jaeger/samplers/HttpSamplingManager.java @@ -22,52 +22,27 @@ package com.uber.jaeger.samplers; +import static com.uber.jaeger.utils.Http.makeGetRequest; + import com.google.gson.Gson; import com.google.gson.JsonSyntaxException; import com.uber.jaeger.exceptions.SamplingStrategyErrorException; import com.uber.jaeger.samplers.http.SamplingStrategyResponse; -import java.io.BufferedReader; + import java.io.IOException; -import java.io.InputStreamReader; -import java.net.HttpURLConnection; -import java.net.URL; import java.net.URLEncoder; -import java.nio.charset.Charset; + import lombok.ToString; + @ToString public class HttpSamplingManager implements SamplingManager { - private static final String defaultSamplingServerHostPort = "localhost:5778"; - private String hostPort = defaultSamplingServerHostPort; - private Gson gson = new Gson(); + private static final String DEFAULT_HOST_PORT = "localhost:5778"; + private final Gson gson = new Gson(); + private final String hostPort; public HttpSamplingManager(String hostPort) { - if (hostPort != null) { - this.hostPort = hostPort; - } - } - - private String makeGetRequest(String urlToRead) throws IOException { - URL url = new URL(urlToRead); - HttpURLConnection conn = (HttpURLConnection) url.openConnection(); - StringBuilder result = new StringBuilder(); - try { - conn.setRequestMethod("GET"); - BufferedReader rd = - new BufferedReader( - new InputStreamReader(conn.getInputStream(), Charset.forName("UTF-8"))); - try { - String line; - while ((line = rd.readLine()) != null) { - result.append(line); - } - } finally { - rd.close(); - } - } finally { - conn.disconnect(); - } - return result.toString(); + this.hostPort = hostPort != null ? hostPort : DEFAULT_HOST_PORT; } SamplingStrategyResponse parseJson(String json) { diff --git a/jaeger-core/src/main/java/com/uber/jaeger/utils/Http.java b/jaeger-core/src/main/java/com/uber/jaeger/utils/Http.java new file mode 100644 index 000000000..b8140ce23 --- /dev/null +++ b/jaeger-core/src/main/java/com/uber/jaeger/utils/Http.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2016, 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.utils; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.charset.Charset; + +public class Http { + + private static final int TIMEOUT_MS = 5000; + + public static String makeGetRequest(String urlToRead) throws IOException { + URL url = new URL(urlToRead); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setConnectTimeout(TIMEOUT_MS); + StringBuilder result = new StringBuilder(); + try { + conn.setRequestMethod("GET"); + BufferedReader rd = + new BufferedReader( + new InputStreamReader(conn.getInputStream(), Charset.forName("UTF-8"))); + try { + String line; + while ((line = rd.readLine()) != null) { + result.append(line); + } + } finally { + rd.close(); + } + } finally { + conn.disconnect(); + } + return result.toString(); + } +} diff --git a/jaeger-core/src/main/java/com/uber/jaeger/utils/Utils.java b/jaeger-core/src/main/java/com/uber/jaeger/utils/Utils.java index 1643cb72c..33a057c96 100644 --- a/jaeger-core/src/main/java/com/uber/jaeger/utils/Utils.java +++ b/jaeger-core/src/main/java/com/uber/jaeger/utils/Utils.java @@ -24,6 +24,7 @@ import com.uber.jaeger.exceptions.EmptyIpException; import com.uber.jaeger.exceptions.NotFourOctetsException; + import java.net.InetAddress; import java.net.UnknownHostException; diff --git a/jaeger-core/src/test/java/com/uber/jaeger/baggage/HttpBaggageRestrictionManagerProxyTest.java b/jaeger-core/src/test/java/com/uber/jaeger/baggage/HttpBaggageRestrictionManagerProxyTest.java new file mode 100644 index 000000000..200d84af3 --- /dev/null +++ b/jaeger-core/src/test/java/com/uber/jaeger/baggage/HttpBaggageRestrictionManagerProxyTest.java @@ -0,0 +1,100 @@ +/* + * 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.baggage; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import com.uber.jaeger.baggage.http.BaggageRestrictionResponse; +import com.uber.jaeger.exceptions.BaggageRestrictionManagerException; +import com.uber.jaeger.mocks.MockAgentResource; + +import java.net.URI; +import java.util.List; +import java.util.Properties; + +import javax.ws.rs.core.Application; + +import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.test.JerseyTest; +import org.glassfish.jersey.test.TestProperties; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + + +public class HttpBaggageRestrictionManagerProxyTest extends JerseyTest { + + private HttpBaggageRestrictionManagerProxy undertest; + private BaggageRestrictionResponse expectedRestriction = new BaggageRestrictionResponse("key", 10); + + private static Properties originalProps; + + @BeforeClass + public static void beforeClass() { + Properties originalProps = new Properties(System.getProperties()); + if (System.getProperty(TestProperties.CONTAINER_PORT) == null) { + System.setProperty(TestProperties.CONTAINER_PORT, "0"); + } + } + + @AfterClass + public static void afterClass() { + System.setProperties(originalProps); + } + + @Override + @Before + public void setUp() throws Exception { + super.setUp(); + undertest = new HttpBaggageRestrictionManagerProxy(null); + } + + @Override + protected Application configure() { + return new ResourceConfig(MockAgentResource.class); + } + + @Test + public void testGetBaggageRestrictions() throws Exception { + URI uri = target().getUri(); + undertest = new HttpBaggageRestrictionManagerProxy(uri.getHost() + ":" + uri.getPort()); + List response = undertest.getBaggageRestrictions("clairvoyant"); + assertNotNull(response); + assertEquals(1, response.size()); + assertEquals(expectedRestriction, response.get(0)); + } + + @Test(expected = BaggageRestrictionManagerException.class) + public void testGetSamplingStrategyError() throws Exception { + URI uri = target().getUri(); + undertest = new HttpBaggageRestrictionManagerProxy(uri.getHost() + ":" + uri.getPort()); + undertest.getBaggageRestrictions(""); + } + + @Test(expected = BaggageRestrictionManagerException.class) + public void testParseInvalidJson() throws Exception { + undertest.parseJson("invalid json"); + } +} diff --git a/jaeger-core/src/test/java/com/uber/jaeger/baggage/RemoteBaggageRestrictionManagerTest.java b/jaeger-core/src/test/java/com/uber/jaeger/baggage/RemoteBaggageRestrictionManagerTest.java new file mode 100644 index 000000000..be954c13d --- /dev/null +++ b/jaeger-core/src/test/java/com/uber/jaeger/baggage/RemoteBaggageRestrictionManagerTest.java @@ -0,0 +1,110 @@ +/* + * 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.baggage; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.when; + +import com.uber.jaeger.baggage.http.BaggageRestrictionResponse; +import com.uber.jaeger.exceptions.BaggageRestrictionManagerException; +import com.uber.jaeger.metrics.InMemoryStatsReporter; +import com.uber.jaeger.metrics.Metrics; + +import java.util.ArrayList; +import java.util.Arrays; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class RemoteBaggageRestrictionManagerTest { + @Mock private BaggageRestrictionManagerProxy baggageRestrictionProxy; + private Metrics metrics; + private InMemoryStatsReporter metricsReporter; + private static final String SERVICE_NAME = "service"; + private static final String BAGGAGE_KEY = "key"; + private static final int MAX_VALUE_LENGTH = 10; + private static final BaggageRestrictionResponse RESTRICTION = + new BaggageRestrictionResponse(BAGGAGE_KEY, MAX_VALUE_LENGTH); + + private RemoteBaggageRestrictionManager undertest; + + @Before + public void setUp() throws Exception { + metricsReporter = new InMemoryStatsReporter(); + metrics = Metrics.fromStatsReporter(metricsReporter); + undertest = new RemoteBaggageRestrictionManager(SERVICE_NAME, baggageRestrictionProxy, metrics, + false); + } + + @After + public void tearDown() { + undertest.close(); + } + + @Test + public void testUpdateBaggageRestrictions() throws Exception { + when(baggageRestrictionProxy.getBaggageRestrictions(SERVICE_NAME)) + .thenReturn(new ArrayList(Arrays.asList(RESTRICTION))); + undertest.updateBaggageRestrictions(); + + assertEquals(Restriction.of(true, MAX_VALUE_LENGTH), undertest.getRestriction(SERVICE_NAME, BAGGAGE_KEY)); + assertFalse(undertest.getRestriction(SERVICE_NAME, "bad-key").isKeyAllowed()); + assertTrue( + metricsReporter.counters.get("jaeger.baggage-restrictions-update.result=ok") > 0L); + } + + @Test + public void testAllowBaggageOnInitializationFailure() throws Exception { + when(baggageRestrictionProxy.getBaggageRestrictions(SERVICE_NAME)) + .thenThrow(new BaggageRestrictionManagerException("error")); + undertest = new RemoteBaggageRestrictionManager(SERVICE_NAME, baggageRestrictionProxy, metrics, + false, 60000, 60000); + + assertTrue(undertest.getRestriction(SERVICE_NAME, BAGGAGE_KEY).isKeyAllowed()); + undertest.updateBaggageRestrictions(); + assertFalse(undertest.isReady()); + // If baggage restriction update fails, all baggage should still be allowed. + assertTrue(undertest.getRestriction(SERVICE_NAME, BAGGAGE_KEY).isKeyAllowed()); + assertTrue(metricsReporter.counters.get("jaeger.baggage-restrictions-update.result=err") > 0L); + } + + @Test + public void testDenyBaggageOnInitializationFailure() throws Exception { + when(baggageRestrictionProxy.getBaggageRestrictions(SERVICE_NAME)) + .thenReturn(new ArrayList(Arrays.asList(RESTRICTION))); + undertest = new RemoteBaggageRestrictionManager(SERVICE_NAME, baggageRestrictionProxy, metrics, + true, 60000, 60000); + + assertFalse(undertest.getRestriction(SERVICE_NAME, BAGGAGE_KEY).isKeyAllowed()); + undertest.updateBaggageRestrictions(); + assertTrue(undertest.isReady()); + assertTrue(undertest.getRestriction(SERVICE_NAME, BAGGAGE_KEY).isKeyAllowed()); + } +} diff --git a/jaeger-core/src/test/java/com/uber/jaeger/samplers/MockAgentResource.java b/jaeger-core/src/test/java/com/uber/jaeger/mocks/MockAgentResource.java similarity index 82% rename from jaeger-core/src/test/java/com/uber/jaeger/samplers/MockAgentResource.java rename to jaeger-core/src/test/java/com/uber/jaeger/mocks/MockAgentResource.java index 8bd0c7b1c..78b295531 100644 --- a/jaeger-core/src/test/java/com/uber/jaeger/samplers/MockAgentResource.java +++ b/jaeger-core/src/test/java/com/uber/jaeger/mocks/MockAgentResource.java @@ -20,7 +20,7 @@ * THE SOFTWARE. */ -package com.uber.jaeger.samplers; +package com.uber.jaeger.mocks; import javax.ws.rs.GET; import javax.ws.rs.Path; @@ -42,4 +42,14 @@ public String getServiceSamplingStrategy(@QueryParam("service") String serviceNa throw new WebApplicationException(); } + + @GET + @Path("baggageRestrictions") + @Produces(MediaType.APPLICATION_JSON) + public String getBaggageRestrictions(@QueryParam("service") String serviceName) { + if (serviceName.equals("clairvoyant")) { + return "[{\"baggageKey\":\"key\",\"maxValueLength\":\"10\"}]"; + } + throw new WebApplicationException(); + } } diff --git a/jaeger-core/src/test/java/com/uber/jaeger/samplers/HttpSamplingManagerTest.java b/jaeger-core/src/test/java/com/uber/jaeger/samplers/HttpSamplingManagerTest.java index 190cd0b9e..e33307a04 100644 --- a/jaeger-core/src/test/java/com/uber/jaeger/samplers/HttpSamplingManagerTest.java +++ b/jaeger-core/src/test/java/com/uber/jaeger/samplers/HttpSamplingManagerTest.java @@ -27,6 +27,7 @@ import static org.junit.Assert.assertNull; import com.uber.jaeger.exceptions.SamplingStrategyErrorException; +import com.uber.jaeger.mocks.MockAgentResource; import com.uber.jaeger.samplers.http.OperationSamplingParameters; import com.uber.jaeger.samplers.http.PerOperationSamplingParameters; import com.uber.jaeger.samplers.http.ProbabilisticSamplingStrategy;