diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/boot/AgentPackagePath.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/boot/AgentPackagePath.java index 8d6aa7d1c..a7574ef5a 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/boot/AgentPackagePath.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/boot/AgentPackagePath.java @@ -19,6 +19,7 @@ package org.apache.skywalking.apm.agent.core.boot; +import java.net.URISyntaxException; import org.apache.skywalking.apm.agent.core.logging.api.ILog; import org.apache.skywalking.apm.agent.core.logging.api.LogManager; @@ -61,9 +62,11 @@ public class AgentPackagePath { urlString = urlString.substring(urlString.indexOf("file:"), insidePathIndex); File agentJarFile = null; try { - agentJarFile = new File(new URL(urlString).getFile()); + agentJarFile = new File(new URL(urlString).toURI()); } catch (MalformedURLException e) { logger.error(e, "Can not locate agent jar file by url:" + urlString); + } catch (URISyntaxException e) { + logger.error(e, "Can not locate agent jar file by url:" + urlString); } if (agentJarFile.exists()) { return agentJarFile.getParentFile(); diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/AbstractTracerContext.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/AbstractTracerContext.java index a7c5453b1..4b3cd2d68 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/AbstractTracerContext.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/AbstractTracerContext.java @@ -16,7 +16,6 @@ * */ - package org.apache.skywalking.apm.agent.core.context; import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; @@ -28,41 +27,38 @@ import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; */ public interface AbstractTracerContext { /** - * Prepare for the cross-process propagation. - * How to initialize the carrier, depends on the implementation. + * Prepare for the cross-process propagation. How to initialize the carrier, depends on the implementation. * * @param carrier to carry the context for crossing process. */ void inject(ContextCarrier carrier); /** - * Build the reference between this segment and a cross-process segment. - * How to build, depends on the implementation. + * Build the reference between this segment and a cross-process segment. How to build, depends on the + * implementation. * * @param carrier carried the context from a cross-process segment. */ void extract(ContextCarrier carrier); /** - * Capture a snapshot for cross-thread propagation. - * It's a similar concept with ActiveSpan.Continuation in OpenTracing-java - * How to build, depends on the implementation. + * Capture a snapshot for cross-thread propagation. It's a similar concept with ActiveSpan.Continuation in + * OpenTracing-java How to build, depends on the implementation. * * @return the {@link ContextSnapshot} , which includes the reference context. */ ContextSnapshot capture(); /** - * Build the reference between this segment and a cross-thread segment. - * How to build, depends on the implementation. + * Build the reference between this segment and a cross-thread segment. How to build, depends on the + * implementation. * * @param snapshot from {@link #capture()} in the parent thread. */ void continued(ContextSnapshot snapshot); /** - * Get the global trace id, if needEnhance. - * How to build, depends on the implementation. + * Get the global trace id, if needEnhance. How to build, depends on the implementation. * * @return the string represents the id. */ @@ -102,7 +98,21 @@ public interface AbstractTracerContext { * Finish the given span, and the given span should be the active span of current tracing context(stack) * * @param span to finish + * @return true when context should be clear. */ - void stopSpan(AbstractSpan span); + boolean stopSpan(AbstractSpan span); + /** + * Notify this context, current span is going to be finished async in another thread. + * + * @return The current context + */ + AbstractTracerContext awaitFinishAsync(); + + /** + * The given span could be stopped officially. + * + * @param span to be stopped. + */ + void asyncStop(AsyncSpan span); } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/AsyncSpan.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/AsyncSpan.java new file mode 100644 index 000000000..8e2483e23 --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/AsyncSpan.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.skywalking.apm.agent.core.context; + +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; + +/** + * Span could use these APIs to active and extend its lift cycle across thread. + * + * This is typical used in async plugin, especially RPC plugins. + * + * @author wusheng + */ +public interface AsyncSpan { + /** + * The span finish at current tracing context, but the current span is still alive, until {@link #asyncFinish} + * called. + * + * This method must be called + * + * 1. In original thread(tracing context). + * 2. Current span is active span. + * + * During alive, tags, logs and attributes of the span could be changed, in any thread. + * + * The execution times of {@link #prepareForAsync} and {@link #asyncFinish()} must match. + * + * @return the current span + */ + AbstractSpan prepareForAsync(); + + /** + * Notify the span, it could be finished. + * + * The execution times of {@link #prepareForAsync} and {@link #asyncFinish()} must match. + * + * @return the current span + */ + AbstractSpan asyncFinish(); +} diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/ContextManager.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/ContextManager.java index aeaa708d2..2dbdb3574 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/ContextManager.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/ContextManager.java @@ -18,14 +18,11 @@ package org.apache.skywalking.apm.agent.core.context; -import org.apache.skywalking.apm.agent.core.boot.BootService; -import org.apache.skywalking.apm.agent.core.boot.ServiceManager; +import org.apache.skywalking.apm.agent.core.boot.*; import org.apache.skywalking.apm.agent.core.conf.RemoteDownstreamConfig; -import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; -import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment; +import org.apache.skywalking.apm.agent.core.context.trace.*; import org.apache.skywalking.apm.agent.core.dictionary.DictionaryUtil; -import org.apache.skywalking.apm.agent.core.logging.api.ILog; -import org.apache.skywalking.apm.agent.core.logging.api.LogManager; +import org.apache.skywalking.apm.agent.core.logging.api.*; import org.apache.skywalking.apm.agent.core.sampling.SamplingService; import org.apache.skywalking.apm.util.StringUtil; @@ -39,7 +36,7 @@ import org.apache.skywalking.apm.util.StringUtil; * * @author wusheng */ -public class ContextManager implements TracingContextListener, BootService, IgnoreTracerContextListener { +public class ContextManager implements BootService { private static final ILog logger = LogManager.getLogger(ContextManager.class); private static ThreadLocal CONTEXT = new ThreadLocal(); private static ThreadLocal RUNTIME_CONTEXT = new ThreadLocal(); @@ -59,7 +56,7 @@ public class ContextManager implements TracingContextListener, BootService, Igno } else { if (RemoteDownstreamConfig.Agent.SERVICE_ID != DictionaryUtil.nullValue() && RemoteDownstreamConfig.Agent.SERVICE_INSTANCE_ID != DictionaryUtil.nullValue() - ) { + ) { context = EXTEND_SERVICE.createTraceContext(operationName, forceSampling); } else { /** @@ -152,6 +149,14 @@ public class ContextManager implements TracingContextListener, BootService, Igno } } + public static AbstractTracerContext awaitFinishAsync(AbstractSpan span) { + AbstractSpan activeSpan = activeSpan(); + if (span != activeSpan) { + throw new RuntimeException("Span is not the active in current context."); + } + return get().awaitFinishAsync(); + } + public static AbstractSpan activeSpan() { return get().activeSpan(); } @@ -161,7 +166,9 @@ public class ContextManager implements TracingContextListener, BootService, Igno } public static void stopSpan(AbstractSpan span) { - get().stopSpan(span); + if (get().stopSpan(span)) { + CONTEXT.remove(); + } } @Override @@ -171,8 +178,6 @@ public class ContextManager implements TracingContextListener, BootService, Igno @Override public void boot() { - ContextManagerExtendService service = ServiceManager.INSTANCE.findService(ContextManagerExtendService.class); - service.registerListeners(this); } @Override @@ -184,16 +189,6 @@ public class ContextManager implements TracingContextListener, BootService, Igno } - @Override - public void afterFinished(TraceSegment traceSegment) { - CONTEXT.remove(); - } - - @Override - public void afterFinished(IgnoredTracerContext traceSegment) { - CONTEXT.remove(); - } - public static boolean isActive() { return get() != null; } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/ContextManagerExtendService.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/ContextManagerExtendService.java index f97853af8..d25e915f0 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/ContextManagerExtendService.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/ContextManagerExtendService.java @@ -18,9 +18,7 @@ package org.apache.skywalking.apm.agent.core.context; -import org.apache.skywalking.apm.agent.core.boot.BootService; -import org.apache.skywalking.apm.agent.core.boot.DefaultImplementor; -import org.apache.skywalking.apm.agent.core.boot.ServiceManager; +import org.apache.skywalking.apm.agent.core.boot.*; import org.apache.skywalking.apm.agent.core.conf.Config; import org.apache.skywalking.apm.agent.core.sampling.SamplingService; @@ -45,11 +43,6 @@ public class ContextManagerExtendService implements BootService { } - public void registerListeners(ContextManager manager) { - TracingContext.ListenerManager.add(manager); - IgnoredTracerContext.ListenerManager.add(manager); - } - public AbstractTracerContext createTraceContext(String operationName, boolean forceSampling) { AbstractTracerContext context; int suffixIdx = operationName.lastIndexOf("."); diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/IgnoredTracerContext.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/IgnoredTracerContext.java index fd115e566..59bc05cd4 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/IgnoredTracerContext.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/IgnoredTracerContext.java @@ -16,17 +16,14 @@ * */ - package org.apache.skywalking.apm.agent.core.context; -import java.util.LinkedList; -import java.util.List; -import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; -import org.apache.skywalking.apm.agent.core.context.trace.NoopSpan; +import java.util.*; +import org.apache.skywalking.apm.agent.core.context.trace.*; /** - * The IgnoredTracerContext represent a context should be ignored. - * So it just maintains the stack with an integer depth field. + * The IgnoredTracerContext represent a context should be ignored. So it just maintains the stack with an + * integer depth field. * * All operations through this will be ignored, and keep the memory and gc cost as low as possible. * @@ -88,11 +85,20 @@ public class IgnoredTracerContext implements AbstractTracerContext { } @Override - public void stopSpan(AbstractSpan span) { + public boolean stopSpan(AbstractSpan span) { stackDepth--; if (stackDepth == 0) { ListenerManager.notifyFinish(this); } + return stackDepth == 0; + } + + @Override public AbstractTracerContext awaitFinishAsync() { + return this; + } + + @Override public void asyncStop(AsyncSpan span) { + } public static class ListenerManager { diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/TracingContext.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/TracingContext.java index df35adabd..773907339 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/TracingContext.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/TracingContext.java @@ -18,25 +18,14 @@ package org.apache.skywalking.apm.agent.core.context; -import java.util.LinkedList; -import java.util.List; +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.locks.ReentrantLock; import org.apache.skywalking.apm.agent.core.boot.ServiceManager; import org.apache.skywalking.apm.agent.core.conf.Config; -import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; -import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan; -import org.apache.skywalking.apm.agent.core.context.trace.EntrySpan; -import org.apache.skywalking.apm.agent.core.context.trace.ExitSpan; -import org.apache.skywalking.apm.agent.core.context.trace.LocalSpan; -import org.apache.skywalking.apm.agent.core.context.trace.NoopExitSpan; -import org.apache.skywalking.apm.agent.core.context.trace.NoopSpan; -import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment; -import org.apache.skywalking.apm.agent.core.context.trace.TraceSegmentRef; -import org.apache.skywalking.apm.agent.core.context.trace.WithPeerInfo; -import org.apache.skywalking.apm.agent.core.dictionary.DictionaryManager; -import org.apache.skywalking.apm.agent.core.dictionary.DictionaryUtil; -import org.apache.skywalking.apm.agent.core.dictionary.PossibleFound; -import org.apache.skywalking.apm.agent.core.logging.api.ILog; -import org.apache.skywalking.apm.agent.core.logging.api.LogManager; +import org.apache.skywalking.apm.agent.core.context.trace.*; +import org.apache.skywalking.apm.agent.core.dictionary.*; +import org.apache.skywalking.apm.agent.core.logging.api.*; import org.apache.skywalking.apm.agent.core.sampling.SamplingService; import org.apache.skywalking.apm.util.StringUtil; @@ -80,6 +69,13 @@ public class TracingContext implements AbstractTracerContext { */ private int spanIdGenerator; + /** + * The counter indicates + */ + private AtomicInteger asyncSpanCounter; + private volatile boolean isRunningInAsyncMode; + private ReentrantLock asyncFinishLock; + /** * Initialize all fields with default value. */ @@ -89,6 +85,9 @@ public class TracingContext implements AbstractTracerContext { if (samplingService == null) { samplingService = ServiceManager.INSTANCE.findService(SamplingService.class); } + asyncSpanCounter = new AtomicInteger(0); + isRunningInAsyncMode = false; + asyncFinishLock = new ReentrantLock(); } /** @@ -392,7 +391,7 @@ public class TracingContext implements AbstractTracerContext { * @param span to finish */ @Override - public void stopSpan(AbstractSpan span) { + public boolean stopSpan(AbstractSpan span) { AbstractSpan lastSpan = peek(); if (lastSpan == span) { if (lastSpan instanceof AbstractTracingSpan) { @@ -407,9 +406,41 @@ public class TracingContext implements AbstractTracerContext { throw new IllegalStateException("Stopping the unexpected span = " + span); } - if (activeSpanStack.isEmpty()) { - this.finish(); + if (checkFinishConditions()) { + finish(); } + + return activeSpanStack.isEmpty(); + } + + @Override public AbstractTracerContext awaitFinishAsync() { + isRunningInAsyncMode = true; + asyncSpanCounter.addAndGet(1); + return this; + } + + @Override public void asyncStop(AsyncSpan span) { + asyncSpanCounter.addAndGet(-1); + + if (checkFinishConditions()) { + finish(); + } + } + + private boolean checkFinishConditions() { + if (isRunningInAsyncMode) { + asyncFinishLock.lock(); + } + try { + if (activeSpanStack.isEmpty() && asyncSpanCounter.get() == 0) { + return true; + } + } finally { + if (isRunningInAsyncMode) { + asyncFinishLock.unlock(); + } + } + return false; } /** diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/AbstractSpan.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/AbstractSpan.java index 17e8aefb7..00858967c 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/AbstractSpan.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/AbstractSpan.java @@ -19,6 +19,7 @@ package org.apache.skywalking.apm.agent.core.context.trace; import java.util.Map; +import org.apache.skywalking.apm.agent.core.context.AsyncSpan; import org.apache.skywalking.apm.agent.core.context.tag.AbstractTag; import org.apache.skywalking.apm.network.trace.component.Component; import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; @@ -28,7 +29,7 @@ import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; * * @author wusheng */ -public interface AbstractSpan { +public interface AbstractSpan extends AsyncSpan { /** * Set the component id, which defines in {@link ComponentsDefine} * diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/AbstractTracingSpan.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/AbstractTracingSpan.java index 803ce1b48..4c14aa2b1 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/AbstractTracingSpan.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/AbstractTracingSpan.java @@ -18,15 +18,10 @@ package org.apache.skywalking.apm.agent.core.context.trace; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import org.apache.skywalking.apm.agent.core.context.tag.AbstractTag; -import org.apache.skywalking.apm.agent.core.context.tag.StringTag; -import org.apache.skywalking.apm.agent.core.context.util.KeyValuePair; -import org.apache.skywalking.apm.agent.core.context.util.TagValuePair; -import org.apache.skywalking.apm.agent.core.context.util.ThrowableTransformer; +import java.util.*; +import org.apache.skywalking.apm.agent.core.context.*; +import org.apache.skywalking.apm.agent.core.context.tag.*; +import org.apache.skywalking.apm.agent.core.context.util.*; import org.apache.skywalking.apm.agent.core.dictionary.DictionaryUtil; import org.apache.skywalking.apm.network.language.agent.SpanType; import org.apache.skywalking.apm.network.language.agent.v2.SpanObjectV2; @@ -45,6 +40,9 @@ public abstract class AbstractTracingSpan implements AbstractSpan { protected String operationName; protected int operationId; protected SpanLayer layer; + protected boolean isInAsyncMode = false; + protected volatile AbstractTracerContext context; + /** * The start time of this Span. */ @@ -322,4 +320,20 @@ public abstract class AbstractTracingSpan implements AbstractSpan { refs.add(ref); } } + + @Override public AbstractSpan prepareForAsync() { + context = ContextManager.awaitFinishAsync(this); + isInAsyncMode = true; + return this; + } + + @Override public AbstractSpan asyncFinish() { + if (!isInAsyncMode) { + throw new RuntimeException("Span is not in async mode, please use '#prepareForAsync' to active."); + } + + this.endTime = System.currentTimeMillis(); + context.asyncStop(this); + return this; + } } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/NoopSpan.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/NoopSpan.java index 774ebca69..d91a813fb 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/NoopSpan.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/NoopSpan.java @@ -115,4 +115,12 @@ public class NoopSpan implements AbstractSpan { @Override public AbstractSpan setPeer(String remotePeer) { return this; } + + @Override public AbstractSpan prepareForAsync() { + return this; + } + + @Override public AbstractSpan asyncFinish() { + return this; + } } diff --git a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/boot/ServiceManagerTest.java b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/boot/ServiceManagerTest.java index afe858d44..462234950 100644 --- a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/boot/ServiceManagerTest.java +++ b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/boot/ServiceManagerTest.java @@ -69,16 +69,13 @@ public class ServiceManagerTest { private void assertIgnoreTracingContextListener() throws Exception { List listeners = getFieldValue(IgnoredTracerContext.ListenerManager.class, "LISTENERS"); - assertThat(listeners.size(), is(1)); - - assertThat(listeners.contains(ServiceManager.INSTANCE.findService(ContextManager.class)), is(true)); + assertThat(listeners.size(), is(0)); } private void assertTracingContextListener() throws Exception { List listeners = getFieldValue(TracingContext.ListenerManager.class, "LISTENERS"); - assertThat(listeners.size(), is(2)); + assertThat(listeners.size(), is(1)); - assertThat(listeners.contains(ServiceManager.INSTANCE.findService(ContextManager.class)), is(true)); assertThat(listeners.contains(ServiceManager.INSTANCE.findService(TraceSegmentServiceClient.class)), is(true)); } diff --git a/docs/en/guides/How-to-build.md b/docs/en/guides/How-to-build.md index 80c8ccbfe..aa2aca014 100644 --- a/docs/en/guides/How-to-build.md +++ b/docs/en/guides/How-to-build.md @@ -30,6 +30,7 @@ For each official Apache release, there is a complete and independent source cod * `grpc-java` and `java` folders in **apm-protocol/apm-network/target/generated-sources/protobuf** * `grpc-java` and `java` folders in **oap-server/server-core/target/generated-sources/protobuf** * `grpc-java` and `java` folders in **oap-server/server-receiver-plugin/skywalking-istio-telemetry-receiver-plugin/target/generated-sources/protobuf** + * `grpc-java` and `java` folders in **oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/target/generated-sources/protobuf** * `antlr4` folder in **oap-server/generate-tool-grammar/target/generated-sources** * `oal` folder in **oap-server/generated-analysis/target/generated-sources** diff --git a/docs/en/guides/Java-Plugin-Development-Guide.md b/docs/en/guides/Java-Plugin-Development-Guide.md index fd6ed452f..992770700 100644 --- a/docs/en/guides/Java-Plugin-Development-Guide.md +++ b/docs/en/guides/Java-Plugin-Development-Guide.md @@ -160,6 +160,42 @@ SpanLayer is the catalog of span. Here are 5 values: Component IDs are defined and reserved by SkyWalking project. For component name/ID extension, please follow [cComponent library definition and extension](Component-library-settings.md) document. +### Advanced APIs +#### Async Span APIs +There is a set of advanced APIs in Span, which work specific for async scenario. When tags, logs, attributes(including end time) of the span +needs to set in another thread, you should use these APIs. + +```java + /** + * The span finish at current tracing context, but the current span is still alive, until {@link #asyncFinish} + * called. + * + * This method must be called
+ * 1. In original thread(tracing context). + * 2. Current span is active span. + * + * During alive, tags, logs and attributes of the span could be changed, in any thread. + * + * The execution times of {@link #prepareForAsync} and {@link #asyncFinish()} must match. + * + * @return the current span + */ + AbstractSpan prepareForAsync(); + + /** + * Notify the span, it could be finished. + * + * The execution times of {@link #prepareForAsync} and {@link #asyncFinish()} must match. + * + * @return the current span + */ + AbstractSpan asyncFinish(); +``` +1. Call `#prepareForAsync` in original context. +1. Propagate the span to any other thread. +1. After all set, call `#asyncFinish` in any thread. +1. Tracing context will be finished and report to backend when all spans's `#prepareForAsync` finished(Judged by count of API execution). + ## Develop a plugin ### Abstract The basic method to trace is intercepting a Java method, by using byte code manipulation tech and AOP concept. diff --git a/docs/en/protocols/Trace-Data-Protocol-v2.md b/docs/en/protocols/Trace-Data-Protocol-v2.md index 6b6481b7f..8e6ef2506 100644 --- a/docs/en/protocols/Trace-Data-Protocol-v2.md +++ b/docs/en/protocols/Trace-Data-Protocol-v2.md @@ -47,9 +47,9 @@ e.g. accessing DB by JDBC, reading Redis/Memcached are cataloged an ExitSpan. 3. Span parent info called Reference, which is included in span. Reference carries more fields besides trace id, parent segment id, span id. Others are **entry service instance id**, **parent service instance id**, -**entry endpoint**, **parent endpoint** and **network address**. Follow [SkyWalking Trace Data Protocol v2](Trace-Data-Protocol-v2.md), +**entry endpoint**, **parent endpoint** and **network address**. Follow [Cross Process Propagation Headers Protocol v2](Skywalking-Cross-Process-Propagation-Headers-Protocol-v2.md), you will know how to get all these fields. ### Step 3. Keep alive. `ServiceInstancePing#doPing` should be called per several seconds. Make the backend know this instance is still -alive. Existed **service instance id** and **UUID** used in `doServiceInstanceRegister` are required. \ No newline at end of file +alive. Existed **service instance id** and **UUID** used in `doServiceInstanceRegister` are required. diff --git a/docs/powered-by.md b/docs/powered-by.md index 20dd90e77..f836a985e 100644 --- a/docs/powered-by.md +++ b/docs/powered-by.md @@ -48,7 +48,8 @@ or providing commercial products including Apache SkyWalking. 1. Mxnavi. 沈阳美行科技有限公司 http://www.mxnavi.com/ 1. Moji 墨叽(深圳)科技有限公司 https://www.mojivip.com 1. Mypharma.com 北京融贯电子商务有限公司 https://www.mypharma.com -1. Primeton.com 普元信息技术股份有限公司 http://www.primeton.com . +1. Osacart in WeChat app 广州美克曼尼电子商务有限公司 +1. Primeton.com 普元信息技术股份有限公司 http://www.primeton.com 1. qiniu.com 七牛云 http://qiniu.com 1. Qingyidai.com 轻易贷 https://www.qingyidai.com/ 1. Qsdjf.com 浙江钱宝网络科技有限公司 https://www.qsdjf.com/index.html @@ -92,3 +93,5 @@ Provide a customized version SkyWalking agent. It could provide distributed trac ## Primeton Integrated in Primeton EOS PLATFORM 8, which is a commercial micro-service platform. +## Oscart +Use multiple language agents from SkyWalking and its ecosystem, including SkyWalking Javaagent and [SkyAPM nodejs agent](https://github.com/SkyAPM/SkyAPM-nodejs). SkyWalking OAP platform acts as backend and visualization. diff --git a/oap-server/exporter/pom.xml b/oap-server/exporter/pom.xml new file mode 100644 index 000000000..492a8e279 --- /dev/null +++ b/oap-server/exporter/pom.xml @@ -0,0 +1,39 @@ + + + + + + oap-server + org.apache.skywalking + 6.1.0-SNAPSHOT + + 4.0.0 + + exporter + + + + org.apache.skywalking + server-core + ${project.version} + + + \ No newline at end of file diff --git a/oap-server/exporter/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider b/oap-server/exporter/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider new file mode 100644 index 000000000..eafb5530d --- /dev/null +++ b/oap-server/exporter/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider @@ -0,0 +1,17 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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. +# +# diff --git a/oap-server/generate-tool/src/main/resources/code-templates/IndicatorImplementor.ftl b/oap-server/generate-tool/src/main/resources/code-templates/IndicatorImplementor.ftl index 8fe2b5a93..aa7be17d5 100644 --- a/oap-server/generate-tool/src/main/resources/code-templates/IndicatorImplementor.ftl +++ b/oap-server/generate-tool/src/main/resources/code-templates/IndicatorImplementor.ftl @@ -28,8 +28,6 @@ import org.apache.skywalking.oap.server.core.Const; <#break> -import org.apache.skywalking.oap.server.core.alarm.AlarmMeta; -import org.apache.skywalking.oap.server.core.alarm.AlarmSupported; import org.apache.skywalking.oap.server.core.analysis.indicator.*; import org.apache.skywalking.oap.server.core.analysis.indicator.annotation.IndicatorType; import org.apache.skywalking.oap.server.core.remote.annotation.StreamData; @@ -45,7 +43,7 @@ import org.apache.skywalking.oap.server.core.storage.StorageBuilder; @IndicatorType @StreamData @StorageEntity(name = "${tableName}", builder = ${metricName}Indicator.Builder.class, sourceScopeId = ${sourceScopeId}) -public class ${metricName}Indicator extends ${indicatorClassName} implements AlarmSupported { +public class ${metricName}Indicator extends ${indicatorClassName} implements WithMetadata { <#list fieldsFromSource as sourceField> @Setter @Getter @Column(columnName = "${sourceField.columnName}") <#if sourceField.isID()>@IDColumn private ${sourceField.typeName} ${sourceField.fieldName}; @@ -170,8 +168,8 @@ public class ${metricName}Indicator extends ${indicatorClassName} implements Ala } - @Override public AlarmMeta getAlarmMeta() { - return new AlarmMeta("${varName}", ${sourceScopeId}<#if (fieldsFromSource?size>0) ><#list fieldsFromSource as field><#if field.isID()>, ${field.fieldName}); + @Override public IndicatorMetaInfo getMeta() { + return new IndicatorMetaInfo("${varName}", ${sourceScopeId}<#if (fieldsFromSource?size>0) ><#list fieldsFromSource as field><#if field.isID()>, ${field.fieldName}); } @Override diff --git a/oap-server/generate-tool/src/test/resources/expectedFiles/IndicatorImplementorExpected.java b/oap-server/generate-tool/src/test/resources/expectedFiles/IndicatorImplementorExpected.java index 461553be9..25a102a9f 100644 --- a/oap-server/generate-tool/src/test/resources/expectedFiles/IndicatorImplementorExpected.java +++ b/oap-server/generate-tool/src/test/resources/expectedFiles/IndicatorImplementorExpected.java @@ -21,8 +21,6 @@ package org.apache.skywalking.oap.server.core.analysis.generated.service.service import java.util.*; import lombok.*; import org.apache.skywalking.oap.server.core.Const; -import org.apache.skywalking.oap.server.core.alarm.AlarmMeta; -import org.apache.skywalking.oap.server.core.alarm.AlarmSupported; import org.apache.skywalking.oap.server.core.analysis.indicator.*; import org.apache.skywalking.oap.server.core.analysis.indicator.annotation.IndicatorType; import org.apache.skywalking.oap.server.core.remote.annotation.StreamData; @@ -38,7 +36,7 @@ import org.apache.skywalking.oap.server.core.storage.StorageBuilder; @IndicatorType @StreamData @StorageEntity(name = "service_avg", builder = ServiceAvgIndicator.Builder.class, sourceScopeId = 1) -public class ServiceAvgIndicator extends LongAvgIndicator implements AlarmSupported { +public class ServiceAvgIndicator extends LongAvgIndicator implements WithMetadata { @Setter @Getter @Column(columnName = "entity_id") @IDColumn private java.lang.String entityId; @@ -108,8 +106,8 @@ public class ServiceAvgIndicator extends LongAvgIndicator implements AlarmSuppor } - @Override public AlarmMeta getAlarmMeta() { - return new AlarmMeta("generate_indicator", 1, entityId); + @Override public IndicatorMetaInfo getMeta() { + return new IndicatorMetaInfo("generate_indicator", 1, entityId); } @Override diff --git a/oap-server/pom.xml b/oap-server/pom.xml index 77bc8a4d8..dba03700a 100644 --- a/oap-server/pom.xml +++ b/oap-server/pom.xml @@ -41,6 +41,7 @@ generate-tool server-telemetry generate-tool-grammar + exporter diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/alarm/AlarmEntrance.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/alarm/AlarmEntrance.java index d673e46e5..7037a4a29 100644 --- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/alarm/AlarmEntrance.java +++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/alarm/AlarmEntrance.java @@ -20,7 +20,7 @@ package org.apache.skywalking.oap.server.core.alarm; import java.util.concurrent.locks.ReentrantLock; import org.apache.skywalking.oap.server.core.CoreModule; -import org.apache.skywalking.oap.server.core.analysis.indicator.Indicator; +import org.apache.skywalking.oap.server.core.analysis.indicator.*; import org.apache.skywalking.oap.server.core.cache.*; import org.apache.skywalking.oap.server.core.register.*; import org.apache.skywalking.oap.server.library.module.ModuleManager; @@ -50,33 +50,33 @@ public class AlarmEntrance { init(); - AlarmMeta alarmMeta = ((AlarmSupported)indicator).getAlarmMeta(); + IndicatorMetaInfo indicatorMetaInfo = ((WithMetadata)indicator).getMeta(); MetaInAlarm metaInAlarm; - switch (alarmMeta.getScope()) { + switch (indicatorMetaInfo.getScope()) { case SERVICE: - int serviceId = Integer.parseInt(alarmMeta.getId()); + int serviceId = Integer.parseInt(indicatorMetaInfo.getId()); ServiceInventory serviceInventory = serviceInventoryCache.get(serviceId); ServiceMetaInAlarm serviceMetaInAlarm = new ServiceMetaInAlarm(); - serviceMetaInAlarm.setIndicatorName(alarmMeta.getIndicatorName()); + serviceMetaInAlarm.setIndicatorName(indicatorMetaInfo.getIndicatorName()); serviceMetaInAlarm.setId(serviceId); serviceMetaInAlarm.setName(serviceInventory.getName()); metaInAlarm = serviceMetaInAlarm; break; case SERVICE_INSTANCE: - int serviceInstanceId = Integer.parseInt(alarmMeta.getId()); + int serviceInstanceId = Integer.parseInt(indicatorMetaInfo.getId()); ServiceInstanceInventory serviceInstanceInventory = serviceInstanceInventoryCache.get(serviceInstanceId); ServiceInstanceMetaInAlarm instanceMetaInAlarm = new ServiceInstanceMetaInAlarm(); - instanceMetaInAlarm.setIndicatorName(alarmMeta.getIndicatorName()); + instanceMetaInAlarm.setIndicatorName(indicatorMetaInfo.getIndicatorName()); instanceMetaInAlarm.setId(serviceInstanceId); instanceMetaInAlarm.setName(serviceInstanceInventory.getName()); metaInAlarm = instanceMetaInAlarm; break; case ENDPOINT: - int endpointId = Integer.parseInt(alarmMeta.getId()); + int endpointId = Integer.parseInt(indicatorMetaInfo.getId()); EndpointInventory endpointInventory = endpointInventoryCache.get(endpointId); EndpointMetaInAlarm endpointMetaInAlarm = new EndpointMetaInAlarm(); - endpointMetaInAlarm.setIndicatorName(alarmMeta.getIndicatorName()); + endpointMetaInAlarm.setIndicatorName(indicatorMetaInfo.getIndicatorName()); endpointMetaInAlarm.setId(endpointId); serviceId = endpointInventory.getServiceId(); diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/alarm/AlarmMeta.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/indicator/IndicatorMetaInfo.java similarity index 74% rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/alarm/AlarmMeta.java rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/indicator/IndicatorMetaInfo.java index c751df0b4..125179159 100644 --- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/alarm/AlarmMeta.java +++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/indicator/IndicatorMetaInfo.java @@ -16,7 +16,7 @@ * */ -package org.apache.skywalking.oap.server.core.alarm; +package org.apache.skywalking.oap.server.core.analysis.indicator; import lombok.*; import org.apache.skywalking.oap.server.core.Const; @@ -24,18 +24,18 @@ import org.apache.skywalking.oap.server.core.Const; /** * @author wusheng */ -public class AlarmMeta { +public class IndicatorMetaInfo { @Setter @Getter private String indicatorName; @Setter @Getter private int scope; @Setter @Getter private String id; - public AlarmMeta(String indicatorName, int scope) { + public IndicatorMetaInfo(String indicatorName, int scope) { this.indicatorName = indicatorName; this.scope = scope; this.id = Const.EMPTY_STRING; } - public AlarmMeta(String indicatorName, int scope, String id) { + public IndicatorMetaInfo(String indicatorName, int scope, String id) { this.indicatorName = indicatorName; this.scope = scope; this.id = id; @@ -48,4 +48,12 @@ public class AlarmMeta { public void setId(String id) { this.id = id; } + + @Override public String toString() { + return "IndicatorMetaInfo{" + + "indicatorName='" + indicatorName + '\'' + + ", scope=" + scope + + ", id='" + id + '\'' + + '}'; + } } diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/alarm/AlarmSupported.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/indicator/WithMetadata.java similarity index 79% rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/alarm/AlarmSupported.java rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/indicator/WithMetadata.java index 9846491d5..c3a2cc3a1 100644 --- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/alarm/AlarmSupported.java +++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/indicator/WithMetadata.java @@ -16,13 +16,13 @@ * */ -package org.apache.skywalking.oap.server.core.alarm; +package org.apache.skywalking.oap.server.core.analysis.indicator; /** - * Alarm supported interface implementor could return the {@link AlarmMeta} + * Indicator, which implement this interface, could provide {@link IndicatorMetaInfo}. * * @author wusheng */ -public interface AlarmSupported { - AlarmMeta getAlarmMeta(); +public interface WithMetadata { + IndicatorMetaInfo getMeta(); } diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/worker/AlarmNotifyWorker.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/worker/AlarmNotifyWorker.java index 2b63572b9..d325648c6 100644 --- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/worker/AlarmNotifyWorker.java +++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/worker/AlarmNotifyWorker.java @@ -18,9 +18,9 @@ package org.apache.skywalking.oap.server.core.analysis.worker; -import org.apache.skywalking.oap.server.core.alarm.AlarmEntrance; -import org.apache.skywalking.oap.server.core.alarm.AlarmSupported; -import org.apache.skywalking.oap.server.core.analysis.indicator.Indicator; +import org.apache.skywalking.oap.server.core.alarm.*; +import org.apache.skywalking.oap.server.core.analysis.indicator.*; +import org.apache.skywalking.oap.server.core.analysis.indicator.WithMetadata; import org.apache.skywalking.oap.server.core.worker.AbstractWorker; import org.apache.skywalking.oap.server.library.module.ModuleManager; @@ -40,7 +40,7 @@ public class AlarmNotifyWorker extends AbstractWorker { } @Override public void in(Indicator indicator) { - if (indicator instanceof AlarmSupported) { + if (indicator instanceof WithMetadata) { entrance.forward(indicator); } } diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/worker/ExportWorker.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/worker/ExportWorker.java new file mode 100644 index 000000000..21ab3abaa --- /dev/null +++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/worker/ExportWorker.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.skywalking.oap.server.core.analysis.worker; + +import org.apache.skywalking.oap.server.core.analysis.indicator.*; +import org.apache.skywalking.oap.server.core.exporter.*; +import org.apache.skywalking.oap.server.core.worker.AbstractWorker; +import org.apache.skywalking.oap.server.library.module.ModuleManager; + +/** + * @author wusheng + */ +public class ExportWorker extends AbstractWorker { + private ModuleManager moduleManager; + private MetricValuesExportService exportService; + + public ExportWorker(int workerId, ModuleManager moduleManager) { + super(workerId); + this.moduleManager = moduleManager; + } + + @Override public void in(Indicator indicator) { + if (exportService != null || moduleManager.has(ExporterModule.NAME)) { + if (indicator instanceof WithMetadata) { + if (exportService == null) { + exportService = moduleManager.find(ExporterModule.NAME).provider().getService(MetricValuesExportService.class); + } + exportService.export(((WithMetadata)indicator).getMeta(), indicator); + } + } + } +} diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/worker/IndicatorPersistentWorker.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/worker/IndicatorPersistentWorker.java index 53134cfa6..13a519339 100644 --- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/worker/IndicatorPersistentWorker.java +++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/worker/IndicatorPersistentWorker.java @@ -18,21 +18,16 @@ package org.apache.skywalking.oap.server.core.analysis.worker; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Objects; +import java.util.*; import org.apache.skywalking.apm.commons.datacarrier.DataCarrier; import org.apache.skywalking.apm.commons.datacarrier.consumer.*; import org.apache.skywalking.oap.server.core.UnexpectedException; -import org.apache.skywalking.oap.server.core.analysis.data.EndOfBatchContext; -import org.apache.skywalking.oap.server.core.analysis.data.MergeDataCache; +import org.apache.skywalking.oap.server.core.analysis.data.*; import org.apache.skywalking.oap.server.core.analysis.indicator.Indicator; import org.apache.skywalking.oap.server.core.storage.IIndicatorDAO; import org.apache.skywalking.oap.server.core.worker.AbstractWorker; import org.apache.skywalking.oap.server.library.module.ModuleManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.slf4j.*; import static java.util.Objects.nonNull; @@ -46,16 +41,19 @@ public class IndicatorPersistentWorker extends PersistenceWorker mergeDataCache; private final IIndicatorDAO indicatorDAO; - private final AbstractWorker nextWorker; + private final AbstractWorker nextAlarmWorker; + private final AbstractWorker nextExportWorker; private final DataCarrier dataCarrier; IndicatorPersistentWorker(int workerId, String modelName, int batchSize, ModuleManager moduleManager, - IIndicatorDAO indicatorDAO, AbstractWorker nextWorker) { + IIndicatorDAO indicatorDAO, AbstractWorker nextAlarmWorker, + AbstractWorker nextExportWorker) { super(moduleManager, workerId, batchSize); this.modelName = modelName; this.mergeDataCache = new MergeDataCache<>(); this.indicatorDAO = indicatorDAO; - this.nextWorker = nextWorker; + this.nextAlarmWorker = nextAlarmWorker; + this.nextExportWorker = nextExportWorker; String name = "INDICATOR_L2_AGGREGATION"; int size = BulkConsumePool.Creator.recommendMaxSize() / 8; @@ -117,8 +115,11 @@ public class IndicatorPersistentWorker extends PersistenceWorker>() { + }.getType(); private final String path; @@ -75,8 +78,7 @@ public class GraphQLQueryHandler extends JettyJsonHandler { JsonObject requestJson = gson.fromJson(request.toString(), JsonObject.class); - return execute(requestJson.get(QUERY).getAsString(), gson.fromJson(requestJson.get(VARIABLES), new TypeToken>() { - }.getType())); + return execute(requestJson.get(QUERY).getAsString(), gson.fromJson(requestJson.get(VARIABLES), mapOfStringObjectType)); } private JsonObject execute(String request, Map variables) { diff --git a/pom.xml b/pom.xml index 868204047..1527fec9a 100644 --- a/pom.xml +++ b/pom.xml @@ -17,7 +17,8 @@ ~ --> - + 4.0.0 org.apache.skywalking @@ -82,7 +83,6 @@ UTF-8 1.8 - 2.11.7 1.6.4 6.18 4.12 @@ -114,13 +114,11 @@ junit junit - ${junit.version} test org.mockito mockito-all - ${mockito-all.version} test @@ -140,13 +138,13 @@ junit junit - 4.12 + ${junit.version} test org.mockito mockito-all - 1.10.19 + ${mockito-all.version} test