mirror of
https://github.com/valitydev/woody_java.git
synced 2024-11-06 08:15:21 +00:00
commit
2bc87f211e
@ -14,6 +14,7 @@
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<!--Test libs-->
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
|
@ -47,26 +47,26 @@ public abstract class AbstractClientBuilder implements ClientBuilder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T build(Class<T> clientInterface) {
|
||||
public <T> T build(Class<T> iface) {
|
||||
try {
|
||||
T target = createProviderClient(clientInterface);
|
||||
return createProxyClient(clientInterface, target);
|
||||
T target = createProviderClient(iface);
|
||||
return createProxyClient(iface, target);
|
||||
} catch (Exception e) {
|
||||
throw new WoodyInstantiationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected <T> T createProxyClient(Class<T> clientInterface, T target) {
|
||||
return createProxyBuilder(clientInterface).build(clientInterface, target);
|
||||
protected <T> T createProxyClient(Class<T> iface, T target) {
|
||||
return createProxyBuilder(iface).build(iface, target);
|
||||
}
|
||||
|
||||
protected ProxyBuilder createProxyBuilder(Class clientInterface) {
|
||||
protected ProxyBuilder createProxyBuilder(Class iface) {
|
||||
ProxyBuilder proxyBuilder = new ProxyBuilder();
|
||||
proxyBuilder.setIdGenerator(idGenerator);
|
||||
proxyBuilder.setStartEventListener(getOnCallStartEventListener());
|
||||
proxyBuilder.setEndEventListener(getOnCallEndEventListener());
|
||||
proxyBuilder.setErrEventListener(getErrorListener());
|
||||
proxyBuilder.setMetadataExtender(getOnCallMetadataExtender(clientInterface));
|
||||
proxyBuilder.setMetadataExtender(getOnCallMetadataExtender(iface));
|
||||
return proxyBuilder;
|
||||
}
|
||||
|
||||
@ -80,9 +80,9 @@ public abstract class AbstractClientBuilder implements ClientBuilder {
|
||||
|
||||
abstract protected Runnable getOnCallEndEventListener();
|
||||
|
||||
abstract protected MethodCallTracer getOnCallMetadataExtender(Class clientInterface);
|
||||
abstract protected MethodCallTracer getOnCallMetadataExtender(Class iface);
|
||||
|
||||
abstract protected <T> T createProviderClient(Class<T> clientInterface);
|
||||
abstract protected <T> T createProviderClient(Class<T> iface);
|
||||
|
||||
protected static class ProxyBuilder {
|
||||
public static final int EVENT_DISABLE = 0b0;
|
||||
@ -143,9 +143,9 @@ public abstract class AbstractClientBuilder implements ClientBuilder {
|
||||
this.errorEventPhases = phases;
|
||||
}
|
||||
|
||||
public <T> T build(Class<T> clientInterface, T target) {
|
||||
public <T> T build(Class<T> iface, T target) {
|
||||
ProxyFactory proxyFactory = createProxyFactory();
|
||||
return proxyFactory.getInstance(clientInterface, target);
|
||||
return proxyFactory.getInstance(iface, target);
|
||||
}
|
||||
|
||||
protected ProxyFactory createProxyFactory() {
|
||||
@ -169,7 +169,7 @@ public abstract class AbstractClientBuilder implements ClientBuilder {
|
||||
new EventTracer(
|
||||
hasFlag(EVENT_BEFORE_CALL_START, startEventPhases) ? startEventListener : listenerStub,
|
||||
hasFlag(EVENT_AFTER_CALL_END, endEventPhases) ? endEventListener : listenerStub,
|
||||
errEventListener)
|
||||
hasFlag(EVENT_AFTER_CALL_END, errorEventPhases) ? errEventListener : listenerStub)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
package com.rbkmoney.woody.api;
|
||||
|
||||
import com.rbkmoney.woody.api.event.ServiceEventListener;
|
||||
import com.rbkmoney.woody.api.generator.IdGenerator;
|
||||
import com.rbkmoney.woody.api.proxy.MethodCallTracer;
|
||||
import com.rbkmoney.woody.api.proxy.ProxyFactory;
|
||||
import com.rbkmoney.woody.api.trace.context.CompositeTracer;
|
||||
@ -14,7 +13,6 @@ import com.rbkmoney.woody.api.trace.context.MetadataTracer;
|
||||
*/
|
||||
public abstract class AbstractServiceBuilder<Service> implements ServiceBuilder<Service> {
|
||||
private ServiceEventListener eventListener;
|
||||
private IdGenerator idGenerator;
|
||||
|
||||
|
||||
@Override
|
||||
@ -24,20 +22,10 @@ public abstract class AbstractServiceBuilder<Service> implements ServiceBuilder<
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServiceBuilder withIdGenerator(IdGenerator generator) {
|
||||
this.idGenerator = generator;
|
||||
return this;
|
||||
}
|
||||
|
||||
protected IdGenerator getIdGenerator() {
|
||||
return idGenerator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Service build(Class<T> serviceInterface, T serviceHandler) {
|
||||
public <T> Service build(Class<T> iface, T serviceHandler) {
|
||||
try {
|
||||
T target = createProxyService(serviceInterface, serviceHandler);
|
||||
return createProviderService(serviceInterface, target);
|
||||
T target = createProxyService(iface, serviceHandler);
|
||||
return createProviderService(iface, target);
|
||||
} catch (Exception e) {
|
||||
throw new WoodyInstantiationException(e);
|
||||
}
|
||||
@ -62,17 +50,16 @@ public abstract class AbstractServiceBuilder<Service> implements ServiceBuilder<
|
||||
abstract protected <T> Service createProviderService(Class<T> serviceInterface, T handler);
|
||||
|
||||
|
||||
protected <T> T createProxyService(Class<T> serviceInterface, T handler) {
|
||||
return createProxyBuilder(serviceInterface).build(serviceInterface, handler);
|
||||
protected <T> T createProxyService(Class<T> iface, T handler) {
|
||||
return createProxyBuilder(iface).build(iface, handler);
|
||||
}
|
||||
|
||||
protected ProxyBuilder createProxyBuilder(Class serviceInterface) {
|
||||
protected ProxyBuilder createProxyBuilder(Class iface) {
|
||||
ProxyBuilder proxyBuilder = new ProxyBuilder();
|
||||
proxyBuilder.setIdGenerator(idGenerator);
|
||||
proxyBuilder.setStartEventListener(getOnCallStartEventListener());
|
||||
proxyBuilder.setEndEventListener(getOnCallEndEventListener());
|
||||
proxyBuilder.setErrEventListener(getErrorListener());
|
||||
proxyBuilder.setMetadataExtender(getOnCallMetadataExtender(serviceInterface));
|
||||
proxyBuilder.setMetadataExtender(getOnCallMetadataExtender(iface));
|
||||
return proxyBuilder;
|
||||
}
|
||||
|
||||
@ -94,7 +81,6 @@ public abstract class AbstractServiceBuilder<Service> implements ServiceBuilder<
|
||||
private Runnable startEventListener;
|
||||
private Runnable endEventListener;
|
||||
private Runnable errEventListener;
|
||||
private IdGenerator idGenerator;
|
||||
private MethodCallTracer metadataExtender;
|
||||
|
||||
public void setStartEventListener(Runnable startEventListener) {
|
||||
@ -109,10 +95,6 @@ public abstract class AbstractServiceBuilder<Service> implements ServiceBuilder<
|
||||
this.errEventListener = errEventListener;
|
||||
}
|
||||
|
||||
public void setIdGenerator(IdGenerator idGenerator) {
|
||||
this.idGenerator = idGenerator;
|
||||
}
|
||||
|
||||
public void setMetadataExtender(MethodCallTracer metadataExtender) {
|
||||
this.metadataExtender = metadataExtender;
|
||||
}
|
||||
@ -133,9 +115,9 @@ public abstract class AbstractServiceBuilder<Service> implements ServiceBuilder<
|
||||
this.errorEventPhases = phases;
|
||||
}
|
||||
|
||||
public <T> T build(Class<T> serviceInterface, T target) {
|
||||
public <T> T build(Class<T> iface, T target) {
|
||||
ProxyFactory proxyFactory = createProxyFactory();
|
||||
return proxyFactory.getInstance(serviceInterface, target);
|
||||
return proxyFactory.getInstance(iface, target);
|
||||
}
|
||||
|
||||
protected ProxyFactory createProxyFactory() {
|
||||
@ -152,7 +134,7 @@ public abstract class AbstractServiceBuilder<Service> implements ServiceBuilder<
|
||||
new EventTracer(
|
||||
hasFlag(EVENT_BEFORE_CALL_START, startEventPhases) ? startEventListener : listenerStub,
|
||||
hasFlag(EVENT_AFTER_CALL_END, endEventPhases) ? endEventListener : listenerStub,
|
||||
errEventListener)
|
||||
hasFlag(EVENT_AFTER_CALL_END, errorEventPhases) ? errEventListener : listenerStub)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -15,5 +15,5 @@ public interface ClientBuilder {
|
||||
|
||||
ClientBuilder withIdGenerator(IdGenerator generator);
|
||||
|
||||
<T> T build(Class<T> clientInterface);
|
||||
<T> T build(Class<T> iface);
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package com.rbkmoney.woody.api;
|
||||
|
||||
import com.rbkmoney.woody.api.event.ServiceEventListener;
|
||||
import com.rbkmoney.woody.api.generator.IdGenerator;
|
||||
|
||||
/**
|
||||
* Created by vpankrashkin on 22.04.16.
|
||||
@ -9,7 +8,5 @@ import com.rbkmoney.woody.api.generator.IdGenerator;
|
||||
public interface ServiceBuilder<Service> {
|
||||
ServiceBuilder withEventListener(ServiceEventListener listener);
|
||||
|
||||
ServiceBuilder withIdGenerator(IdGenerator generator);
|
||||
|
||||
<T> Service build(Class<T> serviceInterface, T serviceHandler);
|
||||
<T> Service build(Class<T> iface, T serviceHandler);
|
||||
}
|
||||
|
@ -0,0 +1,55 @@
|
||||
package com.rbkmoney.woody.api.concurrent;
|
||||
|
||||
import com.rbkmoney.woody.api.trace.TraceData;
|
||||
import com.rbkmoney.woody.api.trace.context.TraceContext;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
|
||||
public class WCallable<T> implements Callable<T> {
|
||||
|
||||
private final TraceData traceData;
|
||||
private final Callable<T> wrappedCallable;
|
||||
|
||||
public static <T> WCallable<T> create(Callable<T> callable) {
|
||||
return new WCallable<>(callable);
|
||||
}
|
||||
|
||||
public static <T> WCallable<T> create(Callable<T> callable, TraceData traceData) {
|
||||
return new WCallable<>(callable, traceData);
|
||||
}
|
||||
|
||||
public static <T> WCallable<T> createFork(Callable<T> callable) {
|
||||
return create(callable, new TraceData());
|
||||
}
|
||||
|
||||
public Callable<T> getWrappedCallable() {
|
||||
return wrappedCallable;
|
||||
}
|
||||
|
||||
public TraceData getTraceData() {
|
||||
return traceData;
|
||||
}
|
||||
|
||||
|
||||
private WCallable(Callable<T> callable) {
|
||||
this(callable, TraceContext.getCurrentTraceData());
|
||||
}
|
||||
|
||||
private WCallable(Callable<T> wrappedCallable, TraceData traceData) {
|
||||
this.traceData = traceData;
|
||||
this.wrappedCallable = wrappedCallable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T call() throws Exception {
|
||||
TraceData originalTraceData = TraceContext.getCurrentTraceData();
|
||||
TraceContext.setCurrentTraceData(getTraceData().cloneObject());
|
||||
try {
|
||||
return getWrappedCallable().call();
|
||||
} finally {
|
||||
TraceContext.setCurrentTraceData(originalTraceData);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,149 @@
|
||||
package com.rbkmoney.woody.api.concurrent;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
public class WExecutorService implements ExecutorService, Closeable {
|
||||
|
||||
private final ExecutorService wrappedExecutor;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param wrappedExecutor Wrapped ExecutorService to which execution will be delegated.
|
||||
*/
|
||||
public WExecutorService(final ExecutorService wrappedExecutor) {
|
||||
this.wrappedExecutor = wrappedExecutor;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void execute(final Runnable arg0) {
|
||||
final WRunnable wRunnable = WRunnable.create(arg0);
|
||||
wrappedExecutor.execute(wRunnable);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean awaitTermination(final long timeout, final TimeUnit unit) throws InterruptedException {
|
||||
return wrappedExecutor.awaitTermination(timeout, unit);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public <T> List<Future<T>> invokeAll(final Collection<? extends Callable<T>> arg0) throws InterruptedException {
|
||||
|
||||
return wrappedExecutor.invokeAll(buildWCollection(arg0));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public <T> List<Future<T>> invokeAll(final Collection<? extends Callable<T>> arg0, final long arg1, final TimeUnit arg2)
|
||||
throws InterruptedException {
|
||||
return wrappedExecutor.invokeAll(buildWCollection(arg0), arg1, arg2);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public <T> T invokeAny(final Collection<? extends Callable<T>> arg0) throws InterruptedException, ExecutionException {
|
||||
return wrappedExecutor.invokeAny(buildWCollection(arg0));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public <T> T invokeAny(final Collection<? extends Callable<T>> arg0, final long arg1, final TimeUnit arg2)
|
||||
throws InterruptedException, ExecutionException, TimeoutException {
|
||||
return wrappedExecutor.invokeAny(buildWCollection(arg0), arg1, arg2);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean isShutdown() {
|
||||
return wrappedExecutor.isShutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean isTerminated() {
|
||||
return wrappedExecutor.isTerminated();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void shutdown() {
|
||||
wrappedExecutor.shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public List<Runnable> shutdownNow() {
|
||||
return wrappedExecutor.shutdownNow();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public <T> Future<T> submit(final Callable<T> arg0) {
|
||||
final WCallable<T> wCallable = WCallable.create(arg0);
|
||||
return wrappedExecutor.submit(wCallable);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Future<?> submit(final Runnable arg0) {
|
||||
final WRunnable wRunnable = WRunnable.create(arg0);
|
||||
return wrappedExecutor.submit(wRunnable);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public <T> Future<T> submit(final Runnable arg0, final T arg1) {
|
||||
final WRunnable wRunnable = WRunnable.create(arg0);
|
||||
return wrappedExecutor.submit(wRunnable, arg1);
|
||||
}
|
||||
|
||||
private <T> Collection<? extends Callable<T>> buildWCollection(
|
||||
final Collection<? extends Callable<T>> originalCollection) {
|
||||
final Collection<Callable<T>> collection = new ArrayList<Callable<T>>();
|
||||
for (final Callable<T> t : originalCollection) {
|
||||
collection.add(WCallable.create(t));
|
||||
}
|
||||
return collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience for try-with-resources, or frameworks such as Spring that automatically process this.
|
||||
**/
|
||||
@Override
|
||||
public void close() {
|
||||
shutdown();
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
package com.rbkmoney.woody.api.concurrent;
|
||||
|
||||
import com.rbkmoney.woody.api.trace.TraceData;
|
||||
import com.rbkmoney.woody.api.trace.context.TraceContext;
|
||||
|
||||
public class WRunnable implements Runnable {
|
||||
|
||||
private final TraceData traceData;
|
||||
private final Runnable wrappedRunnable;
|
||||
|
||||
public static WRunnable create(Runnable runnable) {
|
||||
return new WRunnable(runnable);
|
||||
}
|
||||
|
||||
public static WRunnable create(Runnable runnable, TraceData traceData) {
|
||||
return new WRunnable(runnable, traceData);
|
||||
}
|
||||
|
||||
public static WRunnable createFork(Runnable runnable) {
|
||||
return create(runnable, new TraceData());
|
||||
}
|
||||
|
||||
private WRunnable(Runnable runnable) {
|
||||
this(runnable, TraceContext.getCurrentTraceData());
|
||||
}
|
||||
|
||||
private WRunnable(Runnable runnable, TraceData traceData) {
|
||||
this.wrappedRunnable = runnable;
|
||||
this.traceData = traceData;
|
||||
}
|
||||
|
||||
public Runnable geWrappedRunnable() {
|
||||
return wrappedRunnable;
|
||||
}
|
||||
|
||||
public TraceData getTraceData() {
|
||||
return traceData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
TraceData originalTraceData = TraceContext.getCurrentTraceData();
|
||||
TraceContext.setCurrentTraceData(getTraceData().cloneObject());
|
||||
try {
|
||||
geWrappedRunnable().run();
|
||||
} finally {
|
||||
TraceContext.setCurrentTraceData(originalTraceData);
|
||||
}
|
||||
}
|
||||
}
|
@ -3,7 +3,7 @@ package com.rbkmoney.woody.api.event;
|
||||
/**
|
||||
* Created by vpankrashkin on 22.04.16.
|
||||
*/
|
||||
public interface ClientEventListener extends EventListener<ClientEvent> {
|
||||
void notifyEvent(ClientEvent event);
|
||||
public interface ClientEventListener<E extends ClientEvent> extends EventListener<E> {
|
||||
void notifyEvent(E event);
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,19 @@
|
||||
package com.rbkmoney.woody.api.event;
|
||||
|
||||
/**
|
||||
* Created by vpankrashkin on 28.04.16.
|
||||
*/
|
||||
public class CompositeClientEventListener<E extends ClientEvent> extends CompositeEventListener<E> implements ClientEventListener<E> {
|
||||
private final EventListener<E>[] listeners;
|
||||
|
||||
public CompositeClientEventListener(EventListener<E>... listeners) {
|
||||
this.listeners = listeners.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyEvent(E event) {
|
||||
for (int i = 0; i < listeners.length; ++i) {
|
||||
listeners[i].notifyEvent(event);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package com.rbkmoney.woody.api.event;
|
||||
|
||||
/**
|
||||
* Created by vpankrashkin on 28.04.16.
|
||||
*/
|
||||
public class CompositeEventListener<E extends Event> implements EventListener<E> {
|
||||
private final EventListener<E>[] listeners;
|
||||
|
||||
public CompositeEventListener(EventListener<E>... listeners) {
|
||||
this.listeners = listeners.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyEvent(E event) {
|
||||
for (int i = 0; i < listeners.length; ++i) {
|
||||
listeners[i].notifyEvent(event);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package com.rbkmoney.woody.api.event;
|
||||
|
||||
/**
|
||||
* Created by vpankrashkin on 28.04.16.
|
||||
*/
|
||||
public class CompositeServiceEventListener<E extends ServiceEvent> extends CompositeEventListener<E> implements ServiceEventListener<E> {
|
||||
private final EventListener<E>[] listeners;
|
||||
|
||||
public CompositeServiceEventListener(EventListener<E>... listeners) {
|
||||
this.listeners = listeners.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyEvent(E event) {
|
||||
for (int i = 0; i < listeners.length; ++i) {
|
||||
listeners[i].notifyEvent(event);
|
||||
}
|
||||
}
|
||||
}
|
@ -3,6 +3,6 @@ package com.rbkmoney.woody.api.event;
|
||||
/**
|
||||
* Created by vpankrashkin on 25.04.16.
|
||||
*/
|
||||
public interface ServiceEventListener extends EventListener<ServiceEvent> {
|
||||
void notifyEvent(ServiceEvent event);
|
||||
public interface ServiceEventListener<E extends ServiceEvent> extends EventListener<E> {
|
||||
void notifyEvent(E event);
|
||||
}
|
||||
|
@ -5,13 +5,13 @@ import com.rbkmoney.woody.api.trace.TraceData;
|
||||
/**
|
||||
* Created by vpankrashkin on 04.05.16.
|
||||
*/
|
||||
public class BasicCommonInterceptor<ReqProvider, RespProvider> implements CommonInterceptor<ReqProvider, RespProvider> {
|
||||
public class ContainerCommonInterceptor<ReqProvider, RespProvider> implements CommonInterceptor<ReqProvider, RespProvider> {
|
||||
private RequestInterceptor<ReqProvider> requestInterceptor;
|
||||
private ResponseInterceptor<RespProvider> responseInterceptor;
|
||||
|
||||
public BasicCommonInterceptor(RequestInterceptor<ReqProvider> requestInterceptor, ResponseInterceptor<RespProvider> responseInterceptor) {
|
||||
this.requestInterceptor = requestInterceptor == null ? new EmptyCommonInterceptor() : requestInterceptor;
|
||||
this.responseInterceptor = responseInterceptor == null ? new EmptyCommonInterceptor() : responseInterceptor;
|
||||
public ContainerCommonInterceptor(RequestInterceptor<ReqProvider> requestInterceptor, ResponseInterceptor<RespProvider> responseInterceptor) {
|
||||
this.requestInterceptor = requestInterceptor != null ? requestInterceptor : new EmptyCommonInterceptor();
|
||||
this.responseInterceptor = responseInterceptor != null ? responseInterceptor : new EmptyCommonInterceptor();
|
||||
}
|
||||
|
||||
@Override
|
@ -13,7 +13,7 @@ public class ContextInterceptor<ReqProvider, RespProvider> implements CommonInte
|
||||
|
||||
public ContextInterceptor(TraceContext traceContext, CommonInterceptor interceptor) {
|
||||
this.traceContext = traceContext;
|
||||
this.interceptor = interceptor;
|
||||
this.interceptor = interceptor != null ? interceptor : new EmptyCommonInterceptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -5,4 +5,15 @@ package com.rbkmoney.woody.api.trace;
|
||||
*/
|
||||
public class ClientSpan extends ContextSpan {
|
||||
|
||||
public ClientSpan() {
|
||||
}
|
||||
|
||||
protected ClientSpan(ClientSpan clientSpan) {
|
||||
super(clientSpan);
|
||||
}
|
||||
|
||||
public ClientSpan cloneObject() {
|
||||
return new ClientSpan(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4,8 +4,18 @@ package com.rbkmoney.woody.api.trace;
|
||||
* Created by vpankrashkin on 22.04.16.
|
||||
*/
|
||||
public class ContextSpan {
|
||||
protected final Span span = new Span();
|
||||
protected final Metadata metadata = new Metadata();
|
||||
protected final Span span;
|
||||
protected final Metadata metadata;
|
||||
|
||||
public ContextSpan() {
|
||||
span = new Span();
|
||||
metadata = new Metadata();
|
||||
}
|
||||
|
||||
protected ContextSpan(ContextSpan oldSpan) {
|
||||
this.span = oldSpan.span.cloneObject();
|
||||
this.metadata = oldSpan.metadata.cloneObject();
|
||||
}
|
||||
|
||||
public Span getSpan() {
|
||||
return span;
|
||||
@ -27,4 +37,8 @@ public class ContextSpan {
|
||||
span.reset();
|
||||
metadata.reset();
|
||||
}
|
||||
|
||||
public ContextSpan cloneObject() {
|
||||
return new ContextSpan(this);
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,14 @@ public class ContextUtils {
|
||||
span.getMetadata().putValue(MetadataProperties.INTERCEPTION_ERROR, t);
|
||||
}
|
||||
|
||||
public static void setInterceptionErrorReason(ContextSpan span, Object reason) {
|
||||
span.getMetadata().putValue(MetadataProperties.INTERCEPTION_ERROR_REASON, reason);
|
||||
}
|
||||
|
||||
public static <T> T getInterceptionErrorReason(ContextSpan span, Class<T> targetType) {
|
||||
return getMetadataParameter(span, targetType, MetadataProperties.INTERCEPTION_ERROR_REASON);
|
||||
}
|
||||
|
||||
public static void setCallError(ContextSpan span, Throwable t) {
|
||||
span.getMetadata().putValue(MetadataProperties.CALL_ERROR, t);
|
||||
}
|
||||
|
@ -11,7 +11,16 @@ public class Metadata {
|
||||
private static final int DEFAULT_INIT_SIZE = 16;
|
||||
private static final float DEFAULT_LOAD_FACTOR = 0.75f;
|
||||
|
||||
private Map<String, Object> values = createStore(DEFAULT_INIT_SIZE, DEFAULT_LOAD_FACTOR);
|
||||
private Map<String, Object> values;
|
||||
|
||||
public Metadata() {
|
||||
this.values = createStore(DEFAULT_INIT_SIZE, DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
protected Metadata(Metadata oldMetadata) {
|
||||
this.values = cloneStore(oldMetadata.values);
|
||||
}
|
||||
|
||||
|
||||
public <T> T getValue(String key) {
|
||||
return (T) values.get(key);
|
||||
@ -38,8 +47,18 @@ public class Metadata {
|
||||
values = createStore(DEFAULT_INIT_SIZE, DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
private static Map<String, Object> createStore(int size, float loadFactor) {
|
||||
public Metadata cloneObject() {
|
||||
return new Metadata(this);
|
||||
}
|
||||
|
||||
private static HashMap<String, Object> createStore(int size, float loadFactor) {
|
||||
return new HashMap<>(size, loadFactor);
|
||||
}
|
||||
|
||||
private static Map<String, Object> cloneStore(Map<String, Object> oldMap) {
|
||||
Map<String, Object> newMap = createStore(DEFAULT_INIT_SIZE, DEFAULT_LOAD_FACTOR);
|
||||
newMap.putAll(oldMap);
|
||||
return newMap;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -10,7 +10,6 @@ public class MetadataProperties {
|
||||
public static final String CALL_ERROR = "md_call_error";
|
||||
public static final String CALL_NAME = "md_call_name";
|
||||
public static final String CALL_TYPE = "md_call_type";
|
||||
|
||||
public static final String CALL_ENDPOINT = "md_call_endpoint";
|
||||
|
||||
public static final String EVENT_TYPE = "md_event_type";
|
||||
@ -20,6 +19,7 @@ public class MetadataProperties {
|
||||
public static final String ERROR_MESSAGE = "md_error_message";
|
||||
|
||||
public static final String INTERCEPTION_ERROR = "md_interception_error";
|
||||
public static final String INTERCEPTION_ERROR_REASON = "md_interception_error_reason";
|
||||
|
||||
|
||||
}
|
||||
|
@ -9,6 +9,18 @@ public class ServiceSpan extends ContextSpan {
|
||||
|
||||
private final AtomicInteger counter = new AtomicInteger();
|
||||
|
||||
public ServiceSpan() {
|
||||
}
|
||||
|
||||
protected ServiceSpan(ServiceSpan serviceSpan) {
|
||||
super(serviceSpan);
|
||||
this.counter.set(serviceSpan.counter.get());
|
||||
}
|
||||
|
||||
public ServiceSpan cloneObject() {
|
||||
return new ServiceSpan(this);
|
||||
}
|
||||
|
||||
public AtomicInteger getCounter() {
|
||||
return counter;
|
||||
}
|
||||
|
@ -11,6 +11,18 @@ public class Span {
|
||||
private long timestamp;
|
||||
private long duration;
|
||||
|
||||
public Span() {
|
||||
}
|
||||
|
||||
protected Span(Span oldSpan) {
|
||||
this.traceId = oldSpan.traceId;
|
||||
this.name = oldSpan.name;
|
||||
this.id = oldSpan.id;
|
||||
this.parentId = oldSpan.parentId;
|
||||
this.timestamp = oldSpan.timestamp;
|
||||
this.duration = oldSpan.duration;
|
||||
}
|
||||
|
||||
public String getTraceId() {
|
||||
return traceId;
|
||||
}
|
||||
@ -76,6 +88,10 @@ public class Span {
|
||||
duration = 0;
|
||||
}
|
||||
|
||||
public Span cloneObject() {
|
||||
return new Span(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Span{" +
|
||||
|
@ -4,8 +4,18 @@ package com.rbkmoney.woody.api.trace;
|
||||
* Created by vpankrashkin on 21.04.16.
|
||||
*/
|
||||
public class TraceData {
|
||||
private final ClientSpan clientSpan = new ClientSpan();
|
||||
private final ServiceSpan serviceSpan = new ServiceSpan();
|
||||
private final ClientSpan clientSpan;
|
||||
private final ServiceSpan serviceSpan;
|
||||
|
||||
public TraceData() {
|
||||
this.clientSpan = new ClientSpan();
|
||||
this.serviceSpan = new ServiceSpan();
|
||||
}
|
||||
|
||||
protected TraceData(TraceData oldTraceData) {
|
||||
this.clientSpan = oldTraceData.clientSpan.cloneObject();
|
||||
this.serviceSpan = oldTraceData.serviceSpan.cloneObject();
|
||||
}
|
||||
|
||||
public ClientSpan getClientSpan() {
|
||||
return clientSpan;
|
||||
@ -43,7 +53,7 @@ public class TraceData {
|
||||
* 1,1 means that both spans exist and child client call is active now because for any client request client span is cleared after call completion, so after child call state returns to (1,0) case - (1,1) is child client state -> true
|
||||
* <p>
|
||||
* This allows to eliminate the necessity for call processing code to be explicitly configured with expected call state. This can be figured out directly from the context in runtime.
|
||||
* The only exclusion is {@link com.rbkmoney.woody.api.trace.context.TraceContext} itself. It uses already filled trace id field for server state initiazation
|
||||
* The only exclusion is {@link com.rbkmoney.woody.api.trace.context.TraceContext} itself. It uses already filled trace id field for server state initialization
|
||||
*
|
||||
* @return true - if call is running as root client or child client call for server request handling; false - if call is running in server request handing
|
||||
*/
|
||||
@ -63,4 +73,8 @@ public class TraceData {
|
||||
clientSpan.reset();
|
||||
serviceSpan.reset();
|
||||
}
|
||||
|
||||
public TraceData cloneObject() {
|
||||
return new TraceData(this);
|
||||
}
|
||||
}
|
||||
|
@ -38,8 +38,8 @@ public class TraceContext {
|
||||
return new TraceContext(idGenerator, postInit, preDestroy, preErrDestroy);
|
||||
}
|
||||
|
||||
public static TraceContext forServer(IdGenerator idGenerator, Runnable postInit, Runnable preDestroy, Runnable preErrDestroy) {
|
||||
return new TraceContext(idGenerator, postInit, preDestroy, preErrDestroy);
|
||||
public static TraceContext forServer(Runnable postInit, Runnable preDestroy, Runnable preErrDestroy) {
|
||||
return new TraceContext(null, postInit, preDestroy, preErrDestroy);
|
||||
}
|
||||
|
||||
private final IdGenerator idGenerator;
|
||||
@ -116,6 +116,8 @@ public class TraceContext {
|
||||
}
|
||||
|
||||
private void initClientContext(TraceData traceData) {
|
||||
assert idGenerator != null;
|
||||
|
||||
long timestamp = System.currentTimeMillis();
|
||||
Span clientSpan = traceData.getClientSpan().getSpan();
|
||||
Span serverSpan = traceData.getServiceSpan().getSpan();
|
||||
|
@ -0,0 +1,81 @@
|
||||
package com.rbkmoney.woody.api.concurrent;
|
||||
|
||||
import com.rbkmoney.woody.api.trace.TraceData;
|
||||
import com.rbkmoney.woody.api.trace.context.TraceContext;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* Created by vpankrashkin on 19.05.16.
|
||||
*/
|
||||
public class TestWExecutorService {
|
||||
private WExecutorService executorService;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
executorService = new WExecutorService(Executors.newSingleThreadExecutor());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRunnable() throws ExecutionException, InterruptedException {
|
||||
AtomicBoolean hasErrors = new AtomicBoolean();
|
||||
TraceData traceData = TraceContext.getCurrentTraceData();
|
||||
traceData.getActiveSpan().getSpan().setId("testID");
|
||||
traceData.getActiveSpan().getMetadata().putValue(Boolean.TRUE.toString(), new Object());
|
||||
Future future = executorService.submit(() -> {
|
||||
try {
|
||||
TraceData cData = TraceContext.getCurrentTraceData();
|
||||
Assert.assertNotSame(traceData, cData);
|
||||
Assert.assertEquals(traceData.getActiveSpan().getSpan().getId(), cData.getActiveSpan().getSpan().getId());
|
||||
Assert.assertSame(traceData.getActiveSpan().getMetadata().<Object>getValue(Boolean.TRUE.toString()), cData.getActiveSpan().getMetadata().getValue(Boolean.TRUE.toString()));
|
||||
Assert.assertNotSame(traceData, cData);
|
||||
} catch (Throwable t) {
|
||||
hasErrors.set(true);
|
||||
t.printStackTrace();
|
||||
}
|
||||
});
|
||||
future.get();
|
||||
Assert.assertSame(traceData, TraceContext.getCurrentTraceData());
|
||||
Assert.assertFalse(hasErrors.get());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCallable() throws ExecutionException, InterruptedException {
|
||||
AtomicBoolean hasErrors = new AtomicBoolean();
|
||||
TraceData traceData = TraceContext.getCurrentTraceData();
|
||||
traceData.getActiveSpan().getSpan().setId("testID");
|
||||
traceData.getActiveSpan().getMetadata().putValue(Boolean.TRUE.toString(), new Object());
|
||||
Future future = executorService.submit(() -> {
|
||||
try {
|
||||
TraceData cData = TraceContext.getCurrentTraceData();
|
||||
Assert.assertNotSame(traceData, cData);
|
||||
Assert.assertEquals(traceData.getActiveSpan().getSpan().getId(), cData.getActiveSpan().getSpan().getId());
|
||||
Assert.assertSame(traceData.getActiveSpan().getMetadata().<Object>getValue(Boolean.TRUE.toString()), cData.getActiveSpan().getMetadata().getValue(Boolean.TRUE.toString()));
|
||||
Assert.assertNotSame(traceData, cData);
|
||||
} catch (Throwable t) {
|
||||
hasErrors.set(true);
|
||||
t.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
});
|
||||
future.get();
|
||||
Assert.assertSame(traceData, TraceContext.getCurrentTraceData());
|
||||
Assert.assertFalse(hasErrors.get());
|
||||
|
||||
}
|
||||
|
||||
@After
|
||||
public void after() {
|
||||
executorService.shutdownNow();
|
||||
}
|
||||
|
||||
}
|
@ -12,23 +12,7 @@
|
||||
<artifactId>woody-thrift</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>1.7.21</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-quickstart</artifactId>
|
||||
<version>9.3.9.M1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.11</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!--RBK libs-->
|
||||
<dependency>
|
||||
<groupId>com.rbkmoney.woody</groupId>
|
||||
<artifactId>woody-api</artifactId>
|
||||
@ -37,19 +21,39 @@
|
||||
<dependency>
|
||||
<groupId>com.rbkmoney.thrift</groupId>
|
||||
<artifactId>libthrift</artifactId>
|
||||
<version>0.9.3</version>
|
||||
<version>0.9.3-1</version>
|
||||
</dependency>
|
||||
<!--Thirdparty libs-->
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>1.7.21</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!--Test libs-->
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.11</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-quickstart</artifactId>
|
||||
<version>9.3.9.M1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
<version>1.7.21</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.easymock</groupId>
|
||||
<artifactId>easymock</artifactId>
|
||||
|
@ -2,9 +2,9 @@ package com.rbkmoney.woody.thrift.impl.http;
|
||||
|
||||
import com.rbkmoney.woody.api.AbstractClientBuilder;
|
||||
import com.rbkmoney.woody.api.event.ClientEventListener;
|
||||
import com.rbkmoney.woody.api.interceptor.BasicCommonInterceptor;
|
||||
import com.rbkmoney.woody.api.interceptor.CommonInterceptor;
|
||||
import com.rbkmoney.woody.api.interceptor.CompositeInterceptor;
|
||||
import com.rbkmoney.woody.api.interceptor.ContainerCommonInterceptor;
|
||||
import com.rbkmoney.woody.api.provider.ProviderEventInterceptor;
|
||||
import com.rbkmoney.woody.api.proxy.InstanceMethodCaller;
|
||||
import com.rbkmoney.woody.api.proxy.MethodCallTracer;
|
||||
@ -41,9 +41,9 @@ public class THClientBuilder extends AbstractClientBuilder {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MethodCallTracer getOnCallMetadataExtender(Class clientInterface) {
|
||||
protected MethodCallTracer getOnCallMetadataExtender(Class iface) {
|
||||
return new EmptyTracer() {
|
||||
THErrorMetadataExtender metadataExtender = new THErrorMetadataExtender(clientInterface);
|
||||
THErrorMetadataExtender metadataExtender = new THErrorMetadataExtender(iface);
|
||||
|
||||
@Override
|
||||
public void callError(Object[] args, InstanceMethodCaller caller, Throwable error) {
|
||||
@ -78,21 +78,22 @@ public class THClientBuilder extends AbstractClientBuilder {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> T createProviderClient(Class<T> clientInterface) {
|
||||
protected <T> T createProviderClient(Class<T> iface) {
|
||||
try {
|
||||
THttpClient tHttpClient = new THttpClient(getAddress().toString(), httpClient, createTransportInterceptor());
|
||||
TProtocol tProtocol = createProtocol(tHttpClient);
|
||||
return createThriftClient(clientInterface, tProtocol, createMessageInterceptor());
|
||||
return createThriftClient(iface, tProtocol, createMessageInterceptor());
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ProxyBuilder createProxyBuilder(Class clientInterface) {
|
||||
ProxyBuilder proxyBuilder = super.createProxyBuilder(clientInterface);
|
||||
protected ProxyBuilder createProxyBuilder(Class iface) {
|
||||
ProxyBuilder proxyBuilder = super.createProxyBuilder(iface);
|
||||
proxyBuilder.setStartEventPhases(ProxyBuilder.EVENT_DISABLE);
|
||||
proxyBuilder.setEndEventPhases(ProxyBuilder.EVENT_BEFORE_CONTEXT_DESTROY);
|
||||
proxyBuilder.setErrorEventPhases(ProxyBuilder.EVENT_AFTER_CALL_END);
|
||||
return proxyBuilder;
|
||||
}
|
||||
|
||||
@ -106,14 +107,14 @@ public class THClientBuilder extends AbstractClientBuilder {
|
||||
|
||||
protected CommonInterceptor createMessageInterceptor() {
|
||||
return new CompositeInterceptor(
|
||||
new BasicCommonInterceptor(new THCMessageRequestInterceptor(), new THCMessageResponseInterceptor()),
|
||||
new ContainerCommonInterceptor(new THCMessageRequestInterceptor(), new THCMessageResponseInterceptor()),
|
||||
new ProviderEventInterceptor(getOnCallStartEventListener(), null)
|
||||
);
|
||||
}
|
||||
|
||||
protected CommonInterceptor createTransportInterceptor() {
|
||||
return new CompositeInterceptor(
|
||||
new BasicCommonInterceptor(new THCRequestInterceptor(), new THCResponseInterceptor()),
|
||||
new ContainerCommonInterceptor(new THCRequestInterceptor(), new THCResponseInterceptor()),
|
||||
new TransportEventInterceptor(getOnSendEventListener(), getOnReceiveEventListener())
|
||||
);
|
||||
}
|
||||
|
@ -55,6 +55,7 @@ public class THErrorMetadataExtender {
|
||||
metadata.putValue(MetadataProperties.ERROR_TYPE, ErrorType.PROVIDER_ERROR);
|
||||
metadata.putValue(THMetadataProperties.TH_ERROR_TYPE, TErrorType.TRANSPORT);
|
||||
metadata.putValue(THMetadataProperties.TH_ERROR_SUBTYPE, ((THRequestInterceptionException) callErr).getErrorType());
|
||||
ContextUtils.setInterceptionErrorReason(traceData.getServiceSpan(), ((THRequestInterceptionException) callErr).getReason());
|
||||
} else {
|
||||
metadata.putValue(MetadataProperties.ERROR_TYPE, ErrorType.APPLICATION_UNKNOWN_ERROR);
|
||||
metadata.putValue(MetadataProperties.ERROR_MESSAGE, UNKNOWN_ERROR_MESSAGE);
|
||||
|
@ -14,8 +14,8 @@ public class THMetadataProperties {
|
||||
public static final String TH_CALL_MSG_TYPE = TH_PROPERTY_PREFIX + "call_msg_type";
|
||||
public static final String TH_CALL_RESULT_MSG_TYPE = TH_PROPERTY_PREFIX + "call_result_msg_type";
|
||||
|
||||
public static final String TH_TRANSPORT_REQUEST = TH_PROPERTY_PREFIX + "transport_request";
|
||||
public static final String TH_TRANSPORT_RESPONSE = TH_PROPERTY_PREFIX + "transport_response";
|
||||
|
||||
public static final String TH_TRANSPORT_RESPONSE_SET = TH_PROPERTY_PREFIX + "transport_response_set";
|
||||
|
||||
public static final String TH_ERROR_METADATA_SOURCE = TH_PROPERTY_PREFIX + "error_metadata_source";
|
||||
|
@ -2,9 +2,9 @@ package com.rbkmoney.woody.thrift.impl.http;
|
||||
|
||||
import com.rbkmoney.woody.api.AbstractServiceBuilder;
|
||||
import com.rbkmoney.woody.api.event.ServiceEventListener;
|
||||
import com.rbkmoney.woody.api.interceptor.BasicCommonInterceptor;
|
||||
import com.rbkmoney.woody.api.interceptor.CommonInterceptor;
|
||||
import com.rbkmoney.woody.api.interceptor.CompositeInterceptor;
|
||||
import com.rbkmoney.woody.api.interceptor.ContainerCommonInterceptor;
|
||||
import com.rbkmoney.woody.api.interceptor.ContextInterceptor;
|
||||
import com.rbkmoney.woody.api.proxy.InstanceMethodCaller;
|
||||
import com.rbkmoney.woody.api.proxy.MethodCallTracer;
|
||||
@ -80,24 +80,25 @@ public class THServiceBuilder extends AbstractServiceBuilder<Servlet> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ProxyBuilder createProxyBuilder(Class clientInterface) {
|
||||
ProxyBuilder proxyBuilder = super.createProxyBuilder(clientInterface);
|
||||
protected ProxyBuilder createProxyBuilder(Class iface) {
|
||||
ProxyBuilder proxyBuilder = super.createProxyBuilder(iface);
|
||||
proxyBuilder.setStartEventPhases(ProxyBuilder.EVENT_BEFORE_CALL_START);
|
||||
proxyBuilder.setEndEventPhases(ProxyBuilder.EVENT_AFTER_CALL_END);
|
||||
proxyBuilder.setErrorEventPhases(ProxyBuilder.EVENT_AFTER_CALL_END);
|
||||
return proxyBuilder;
|
||||
}
|
||||
|
||||
protected CommonInterceptor createMessageInterceptor() {
|
||||
return new CompositeInterceptor(
|
||||
new BasicCommonInterceptor(new THSMessageRequestInterceptor(), new THSMessageResponseInterceptor())
|
||||
new ContainerCommonInterceptor(new THSMessageRequestInterceptor(), new THSMessageResponseInterceptor())
|
||||
);
|
||||
}
|
||||
|
||||
protected CommonInterceptor createTransportInterceptor(THErrorMetadataExtender metadataExtender) {
|
||||
TraceContext traceContext = createTraceContext();
|
||||
return new CompositeInterceptor(
|
||||
new BasicCommonInterceptor(null, new THSResponseMetadataInterceptor(metadataExtender)),
|
||||
new BasicCommonInterceptor(new THSRequestInterceptor(), new THSResponseInterceptor(true)),
|
||||
new ContainerCommonInterceptor(null, new THSResponseMetadataInterceptor(metadataExtender)),
|
||||
new ContainerCommonInterceptor(new THSRequestInterceptor(), new THSResponseInterceptor(true)),
|
||||
new ContextInterceptor(
|
||||
traceContext,
|
||||
new TransportEventInterceptor(getOnReceiveEventListener(), null)
|
||||
@ -106,7 +107,7 @@ public class THServiceBuilder extends AbstractServiceBuilder<Servlet> {
|
||||
}
|
||||
|
||||
protected TraceContext createTraceContext() {
|
||||
return TraceContext.forServer(getIdGenerator(), () -> {
|
||||
return TraceContext.forServer(() -> {
|
||||
}, getOnSendEventListener(), getErrorListener());
|
||||
|
||||
}
|
||||
@ -121,8 +122,8 @@ public class THServiceBuilder extends AbstractServiceBuilder<Servlet> {
|
||||
protected Servlet createThriftServlet(TProcessor tProcessor, CommonInterceptor servletInterceptor, THErrorMetadataExtender metadataExtender) {
|
||||
CompositeInterceptor protInterceptor = new CompositeInterceptor(
|
||||
createMessageInterceptor(),
|
||||
new BasicCommonInterceptor(null, new THSResponseMetadataInterceptor(metadataExtender)),
|
||||
new BasicCommonInterceptor(null, new THSResponseInterceptor(false))
|
||||
new ContainerCommonInterceptor(null, new THSResponseMetadataInterceptor(metadataExtender)),
|
||||
new ContainerCommonInterceptor(null, new THSResponseInterceptor(false))
|
||||
);
|
||||
TProtocolFactory tProtocolFactory = wrapProtocolFactory(new TCompactProtocol.Factory(), protInterceptor);
|
||||
return new TServlet(tProcessor, tProtocolFactory, servletInterceptor);
|
||||
|
@ -1,6 +1,5 @@
|
||||
package com.rbkmoney.woody.thrift.impl.http.event;
|
||||
|
||||
import com.rbkmoney.woody.api.event.ClientEvent;
|
||||
import com.rbkmoney.woody.api.event.ClientEventListener;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -8,13 +7,12 @@ import org.slf4j.LoggerFactory;
|
||||
/**
|
||||
* Created by vpankrashkin on 12.05.16.
|
||||
*/
|
||||
public class ClientEventLogListener implements ClientEventListener {
|
||||
public class ClientEventLogListener implements ClientEventListener<THClientEvent> {
|
||||
private final Logger log = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@Override
|
||||
public void notifyEvent(ClientEvent event1) {
|
||||
public void notifyEvent(THClientEvent event) {
|
||||
try {
|
||||
THClientEvent event = (THClientEvent) event1;
|
||||
switch (event.getEventType()) {
|
||||
case CALL_SERVICE:
|
||||
log.info("CLIENT Event: {}, Span [{}-{}-{}], [{}, Type: {}], Time: {}", event.getEventType(), event.getTraceId(), event.getSpanId(), event.getParentId(), event.getCallName(), event.getCallType(), event.getTimeStamp());
|
||||
|
@ -0,0 +1,56 @@
|
||||
package com.rbkmoney.woody.thrift.impl.http.event;
|
||||
|
||||
import com.rbkmoney.woody.api.event.ClientEventListener;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpRequestBase;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Created by vpankrashkin on 12.05.16.
|
||||
*/
|
||||
public class HttpClientEventLogListener implements ClientEventListener<THClientEvent> {
|
||||
private final Logger log = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@Override
|
||||
public void notifyEvent(THClientEvent event) {
|
||||
try {
|
||||
|
||||
switch (event.getEventType()) {
|
||||
case CLIENT_SEND:
|
||||
HttpRequestBase httpRequest = event.getTransportRequest();
|
||||
if (httpRequest != null) {
|
||||
log.info("CLIENT Event: {}, {}", event.getEventType(), buildRequestLog(httpRequest));
|
||||
}
|
||||
break;
|
||||
case CLIENT_RECEIVE:
|
||||
HttpResponse httpResponse = event.getTransportResponse();
|
||||
if (httpResponse != null) {
|
||||
log.info("CLIENT Event: {}, {}", event.getEventType(), buildResponseLog(httpResponse));
|
||||
}
|
||||
break;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Event processing failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
private String buildRequestLog(HttpRequestBase requestBase) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("HttpRequest:")
|
||||
.append(requestBase.toString()).append(", Headers:").append(Arrays.toString(requestBase.getAllHeaders()));
|
||||
|
||||
return sb.toString();
|
||||
|
||||
}
|
||||
|
||||
private String buildResponseLog(HttpResponse httpResponse) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("HttpResponse:")
|
||||
.append(httpResponse.getStatusLine().toString()).append(", Headers:").append(Arrays.toString(httpResponse.getAllHeaders()));
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
package com.rbkmoney.woody.thrift.impl.http.event;
|
||||
|
||||
import com.rbkmoney.woody.api.event.ServiceEventListener;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.Collection;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Created by vpankrashkin on 12.05.16.
|
||||
*/
|
||||
public class HttpServiceEventLogListener implements ServiceEventListener<THServiceEvent> {
|
||||
private final Logger log = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@Override
|
||||
public void notifyEvent(THServiceEvent event) {
|
||||
try {
|
||||
switch (event.getEventType()) {
|
||||
case SERVICE_RECEIVE:
|
||||
HttpServletRequest request = event.getTransportRequest();
|
||||
if (request != null) {
|
||||
log.info("SERVER Event: {}, {}", event.getEventType(), buildRequestLog(request));
|
||||
}
|
||||
break;
|
||||
case SERVICE_RESULT:
|
||||
HttpServletResponse response = event.getTransportResponse();
|
||||
if (response != null) {
|
||||
log.info("SERVER Event: {}, {}", event.getEventType(), buildResponseLog(response));
|
||||
}
|
||||
break;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to process event", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private String buildRequestLog(HttpServletRequest httpRequest) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("HttpRequest:")
|
||||
.append(httpRequest.getMethod()).append(" ")
|
||||
.append(httpRequest.getProtocol())
|
||||
.append(", RemoteHost: ").append(httpRequest.getRemoteHost())
|
||||
.append(", Headers:");
|
||||
Enumeration<String> headers = httpRequest.getHeaderNames();
|
||||
sb.append('[');
|
||||
for (String headerName; headers.hasMoreElements(); ) {
|
||||
headerName = headers.nextElement();
|
||||
Enumeration<String> vals = httpRequest.getHeaders(headerName);
|
||||
for (String val; vals.hasMoreElements(); ) {
|
||||
val = vals.nextElement();
|
||||
sb.append(headerName).append(": ").append(val);
|
||||
if (vals.hasMoreElements())
|
||||
sb.append(", ");
|
||||
}
|
||||
if (headers.hasMoreElements()) {
|
||||
sb.append(", ");
|
||||
}
|
||||
}
|
||||
sb.append(']');
|
||||
|
||||
return sb.toString();
|
||||
|
||||
}
|
||||
|
||||
private String buildResponseLog(HttpServletResponse httpResponse) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("HttpResponse:")
|
||||
.append(httpResponse.getStatus())
|
||||
.append(", Headers:");
|
||||
Collection<String> headers = httpResponse.getHeaderNames();
|
||||
sb.append('[');
|
||||
for (Iterator<String> it = headers.iterator(); it.hasNext(); ) {
|
||||
String header = it.next();
|
||||
sb.append(' ').append(header).append(": ").append(httpResponse.getHeader(header));
|
||||
if (it.hasNext())
|
||||
sb.append(", ");
|
||||
}
|
||||
sb.append(']');
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
package com.rbkmoney.woody.thrift.impl.http.event;
|
||||
|
||||
import com.rbkmoney.woody.api.event.ServiceEvent;
|
||||
import com.rbkmoney.woody.api.event.ServiceEventListener;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -8,13 +7,12 @@ import org.slf4j.LoggerFactory;
|
||||
/**
|
||||
* Created by vpankrashkin on 12.05.16.
|
||||
*/
|
||||
public class ServiceEventLogListener implements ServiceEventListener {
|
||||
public class ServiceEventLogListener implements ServiceEventListener<THServiceEvent> {
|
||||
private final Logger log = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@Override
|
||||
public void notifyEvent(ServiceEvent event1) {
|
||||
public void notifyEvent(THServiceEvent event) {
|
||||
try {
|
||||
THServiceEvent event = (THServiceEvent) event1;
|
||||
switch (event.getEventType()) {
|
||||
case CALL_HANDLER:
|
||||
log.info("SERVER Event: {}, Span [{}-{}-{}], [{}, Type: {}], Time: {}", event.getEventType(), event.getTraceId(), event.getSpanId(), event.getParentId(), event.getCallName(), event.getCallType(), event.getTimeStamp());
|
||||
|
@ -1,9 +1,12 @@
|
||||
package com.rbkmoney.woody.thrift.impl.http.event;
|
||||
|
||||
import com.rbkmoney.woody.api.event.ClientEvent;
|
||||
import com.rbkmoney.woody.api.trace.ContextUtils;
|
||||
import com.rbkmoney.woody.api.trace.TraceData;
|
||||
import com.rbkmoney.woody.thrift.impl.http.TErrorType;
|
||||
import com.rbkmoney.woody.thrift.impl.http.THMetadataProperties;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpRequestBase;
|
||||
|
||||
/**
|
||||
* Created by vpankrashkin on 06.05.16.
|
||||
@ -32,4 +35,12 @@ public class THClientEvent extends ClientEvent {
|
||||
public String getThriftResponseMessage() {
|
||||
return getActiveSpan().getMetadata().getValue(THMetadataProperties.TH_RESPONSE_MESSAGE);
|
||||
}
|
||||
|
||||
public HttpRequestBase getTransportRequest() {
|
||||
return ContextUtils.getMetadataParameter(getActiveSpan(), HttpRequestBase.class, THMetadataProperties.TH_TRANSPORT_REQUEST);
|
||||
}
|
||||
|
||||
public HttpResponse getTransportResponse() {
|
||||
return ContextUtils.getMetadataParameter(getActiveSpan(), HttpResponse.class, THMetadataProperties.TH_TRANSPORT_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,14 @@
|
||||
package com.rbkmoney.woody.thrift.impl.http.event;
|
||||
|
||||
import com.rbkmoney.woody.api.event.ServiceEvent;
|
||||
import com.rbkmoney.woody.api.trace.ContextUtils;
|
||||
import com.rbkmoney.woody.api.trace.TraceData;
|
||||
import com.rbkmoney.woody.thrift.impl.http.TErrorType;
|
||||
import com.rbkmoney.woody.thrift.impl.http.THMetadataProperties;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* Created by vpankrashkin on 06.05.16.
|
||||
*/
|
||||
@ -32,4 +36,12 @@ public class THServiceEvent extends ServiceEvent {
|
||||
public String getThriftResponseMessage() {
|
||||
return getActiveSpan().getMetadata().getValue(THMetadataProperties.TH_RESPONSE_MESSAGE);
|
||||
}
|
||||
|
||||
public HttpServletRequest getTransportRequest() {
|
||||
return ContextUtils.getMetadataParameter(getActiveSpan(), HttpServletRequest.class, THMetadataProperties.TH_TRANSPORT_REQUEST);
|
||||
}
|
||||
|
||||
public HttpServletResponse getTransportResponse() {
|
||||
return ContextUtils.getMetadataParameter(getActiveSpan(), HttpServletResponse.class, THMetadataProperties.TH_TRANSPORT_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ package com.rbkmoney.woody.thrift.impl.http.interceptor;
|
||||
|
||||
import com.rbkmoney.woody.api.interceptor.RequestInterceptor;
|
||||
import com.rbkmoney.woody.api.trace.*;
|
||||
import com.rbkmoney.woody.thrift.impl.http.THMetadataProperties;
|
||||
import com.rbkmoney.woody.thrift.impl.http.transport.THttpHeader;
|
||||
import com.rbkmoney.woody.thrift.impl.http.transport.UrlStringEndpoint;
|
||||
import org.apache.http.client.methods.HttpRequestBase;
|
||||
|
||||
@ -24,7 +26,7 @@ public class THCRequestInterceptor implements RequestInterceptor {
|
||||
}
|
||||
|
||||
private boolean interceptUrlConnection(ClientSpan clientSpan, HttpURLConnection connection, Object... contextParams) {
|
||||
extendMetadata(clientSpan, connection.getURL().toString());
|
||||
extendMetadata(clientSpan, connection.getURL().toString(), connection);
|
||||
ArrayList<String[]> headers = prepareClientHeaders(clientSpan);
|
||||
for (int i = 0; i < headers.size(); ++i) {
|
||||
connection.setRequestProperty(headers.get(i)[0], headers.get(i)[1]);
|
||||
@ -34,7 +36,7 @@ public class THCRequestInterceptor implements RequestInterceptor {
|
||||
|
||||
protected boolean interceptRequestBase(ClientSpan clientSpan, HttpRequestBase requestBase, Object... contextParams) {
|
||||
URL url = ContextUtils.getContextParameter(URL.class, contextParams, 0);
|
||||
extendMetadata(clientSpan, url == null ? null : url.toString());
|
||||
extendMetadata(clientSpan, url == null ? null : url.toString(), requestBase);
|
||||
ArrayList<String[]> headers = prepareClientHeaders(clientSpan);
|
||||
for (int i = 0; i < headers.size(); ++i) {
|
||||
requestBase.setHeader(headers.get(i)[0], headers.get(i)[1]);
|
||||
@ -42,16 +44,17 @@ public class THCRequestInterceptor implements RequestInterceptor {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void extendMetadata(ClientSpan clientSpan, String url) {
|
||||
private void extendMetadata(ClientSpan clientSpan, String url, Object request) {
|
||||
clientSpan.getMetadata().putValue(MetadataProperties.CALL_ENDPOINT, new UrlStringEndpoint(url));
|
||||
clientSpan.getMetadata().putValue(THMetadataProperties.TH_TRANSPORT_REQUEST, request);
|
||||
}
|
||||
|
||||
private ArrayList<String[]> prepareClientHeaders(ClientSpan clientSpan) {
|
||||
Span span = clientSpan.getSpan();
|
||||
ArrayList<String[]> headers = new ArrayList<>();
|
||||
headers.add(new String[]{"x-rbk-trace-id", span.getTraceId()});
|
||||
headers.add(new String[]{"x-rbk-span-id", span.getId()});
|
||||
headers.add(new String[]{"x-rbk-parent-id", span.getParentId()});
|
||||
headers.add(new String[]{THttpHeader.TRACE_ID.getKeyValue(), span.getTraceId()});
|
||||
headers.add(new String[]{THttpHeader.SPAN_ID.getKeyValue(), span.getId()});
|
||||
headers.add(new String[]{THttpHeader.PARENT_ID.getKeyValue(), span.getParentId()});
|
||||
|
||||
return headers;
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ public class THCResponseInterceptor implements ResponseInterceptor {
|
||||
try {
|
||||
clientSpan.getMetadata().putValue(THMetadataProperties.TH_RESPONSE_STATUS, connection.getResponseCode());
|
||||
clientSpan.getMetadata().putValue(THMetadataProperties.TH_RESPONSE_MESSAGE, connection.getResponseMessage());
|
||||
clientSpan.getMetadata().putValue(THMetadataProperties.TH_TRANSPORT_RESPONSE, connection);
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
return interceptError(clientSpan, "Failed to get response data", e);
|
||||
@ -37,6 +38,8 @@ public class THCResponseInterceptor implements ResponseInterceptor {
|
||||
protected boolean interceptResponseBase(ClientSpan clientSpan, HttpResponse response) {
|
||||
clientSpan.getMetadata().putValue(THMetadataProperties.TH_RESPONSE_STATUS, response.getStatusLine().getStatusCode());
|
||||
clientSpan.getMetadata().putValue(THMetadataProperties.TH_RESPONSE_MESSAGE, response.getStatusLine().getReasonPhrase());
|
||||
clientSpan.getMetadata().putValue(THMetadataProperties.TH_TRANSPORT_RESPONSE, response);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -6,14 +6,19 @@ import com.rbkmoney.woody.thrift.impl.http.transport.TTransportErrorType;
|
||||
* Created by vpankrashkin on 11.05.16.
|
||||
*/
|
||||
public class THRequestInterceptionException extends RuntimeException {
|
||||
private TTransportErrorType errorType;
|
||||
private final TTransportErrorType errorType;
|
||||
private final Object reason;
|
||||
|
||||
public THRequestInterceptionException(TTransportErrorType transportErrorType) {
|
||||
super();
|
||||
public THRequestInterceptionException(TTransportErrorType transportErrorType, Object reason) {
|
||||
errorType = transportErrorType;
|
||||
this.reason = reason;
|
||||
}
|
||||
|
||||
public TTransportErrorType getErrorType() {
|
||||
return errorType;
|
||||
}
|
||||
|
||||
public Object getReason() {
|
||||
return reason;
|
||||
}
|
||||
}
|
||||
|
@ -20,8 +20,8 @@ public class THSMessageRequestInterceptor implements RequestInterceptor<TMessage
|
||||
}
|
||||
|
||||
public THSMessageRequestInterceptor(Runnable eventListener) {
|
||||
this.eventListener = eventListener == null ? () -> {
|
||||
} : eventListener;
|
||||
this.eventListener = eventListener != null ? eventListener : () -> {
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -23,9 +23,17 @@ public class THSRequestInterceptor implements RequestInterceptor {
|
||||
}
|
||||
|
||||
protected boolean interceptHttpRequest(TraceData traceData, HttpServletRequest request, Object... contextParams) {
|
||||
String errMethod = chechRequestMethod(request);
|
||||
if (errMethod != null) {
|
||||
return interceptRequest(traceData, new THRequestInterceptionException(TTransportErrorType.BAD_REQUEST_TYPE, errMethod));
|
||||
}
|
||||
String errContentType = checkContentType(request);
|
||||
if (errContentType != null) {
|
||||
return interceptError(traceData, new THRequestInterceptionException(TTransportErrorType.BAD_CONTENT_TYPE, errContentType));
|
||||
}
|
||||
THttpHeader errHeader = setSpanHeaders(traceData.getServiceSpan(), request);
|
||||
if (errHeader != null) {
|
||||
return interceptError(traceData, new THRequestInterceptionException(TTransportErrorType.BAD_TRACE_HEADERS));
|
||||
return interceptError(traceData, new THRequestInterceptionException(TTransportErrorType.BAD_TRACE_HEADERS, errHeader));
|
||||
}
|
||||
extendMetadata(traceData.getServiceSpan(), request, contextParams);
|
||||
return true;
|
||||
@ -51,6 +59,16 @@ public class THSRequestInterceptor implements RequestInterceptor {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected String chechRequestMethod(HttpServletRequest request) {
|
||||
String reqMethod = request.getMethod();
|
||||
return "POST".equals(reqMethod) ? null : reqMethod;
|
||||
}
|
||||
|
||||
private String checkContentType(HttpServletRequest request) {
|
||||
String cType = request.getContentType();
|
||||
return "application/x-thrift".equalsIgnoreCase(cType) ? null : cType;
|
||||
}
|
||||
|
||||
private void extendMetadata(ServiceSpan serviceSpan, HttpServletRequest request, Object... contextParams) {
|
||||
String queryString = request.getQueryString();
|
||||
StringBuffer sb = request.getRequestURL();
|
||||
@ -59,9 +77,10 @@ public class THSRequestInterceptor implements RequestInterceptor {
|
||||
}
|
||||
serviceSpan.getMetadata().putValue(MetadataProperties.CALL_ENDPOINT, new UrlStringEndpoint(sb.toString()));
|
||||
HttpServletResponse response = ContextUtils.getContextParameter(HttpServletResponse.class, contextParams, 0);
|
||||
if (response != null) {
|
||||
serviceSpan.getMetadata().putValue(THMetadataProperties.TH_TRANSPORT_RESPONSE, response);
|
||||
}
|
||||
|
||||
serviceSpan.getMetadata().putValue(THMetadataProperties.TH_TRANSPORT_REQUEST, request);
|
||||
serviceSpan.getMetadata().putValue(THMetadataProperties.TH_TRANSPORT_RESPONSE, response);
|
||||
|
||||
}
|
||||
|
||||
private String getSpanHeader(String name, HttpServletRequest request) {
|
||||
|
@ -9,15 +9,18 @@ import com.rbkmoney.woody.thrift.impl.http.transport.THttpHeader;
|
||||
import com.rbkmoney.woody.thrift.impl.http.transport.TTransportErrorType;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Created by vpankrashkin on 29.04.16.
|
||||
*/
|
||||
public class THSResponseInterceptor implements ResponseInterceptor {
|
||||
public static final String THRFIT_TRANSPORT_ERROR_MSG = "thrift transport error";
|
||||
public static final String THRFIT_PROTOCOL_ERROR_MSG = "thrift protocol error";
|
||||
public static final String UNKNOWN_PROVIDER_ERROR_MSG = "unknown provider error";
|
||||
public static final String BAD_REQUEST_HEADERS_MSG = "bad request headers";
|
||||
public static final Function<Object, String> THRFIT_TRANSPORT_ERROR_FUNC = obj -> "thrift transport error";
|
||||
public static final Function<Object, String> THRFIT_PROTOCOL_ERROR_FUNC = obj -> "thrift protocol error";
|
||||
public static final Function<Object, String> UNKNOWN_PROVIDER_ERROR_FUNC = obj -> "unknown provider error";
|
||||
public static final Function<String, String> BAD_CONTENT_TYPE_FUNC = cType -> "content type wrong/missing";
|
||||
public static final Function<THttpHeader, String> BAD_REQUEST_HEADERS_FUNC = tHttpHeader -> (tHttpHeader == null ? "Trace header" : tHttpHeader.getKeyValue()) + " missing";
|
||||
public static final Function<String, String> BAD_REQUEST_METHOD_FUNC = rewMethod -> "http method wrong";
|
||||
boolean isUseContext;
|
||||
|
||||
public THSResponseInterceptor(boolean isUseContext) {
|
||||
@ -79,33 +82,41 @@ public class THSResponseInterceptor implements ResponseInterceptor {
|
||||
TTransportErrorType tTransportErrorType = ContextUtils.getMetadataParameter(serviceSpan, TTransportErrorType.class, THMetadataProperties.TH_ERROR_SUBTYPE);
|
||||
if (tTransportErrorType != null) {
|
||||
switch (tTransportErrorType) {
|
||||
case BAD_REQUEST_TYPE:
|
||||
responseStatus = 405;
|
||||
errThriftValue = BAD_REQUEST_METHOD_FUNC.apply(ContextUtils.getInterceptionErrorReason(serviceSpan, String.class));
|
||||
break;
|
||||
case BAD_TRACE_HEADERS:
|
||||
responseStatus = 400;
|
||||
errThriftValue = BAD_REQUEST_HEADERS_FUNC.apply(ContextUtils.getInterceptionErrorReason(serviceSpan, THttpHeader.class));
|
||||
break;
|
||||
case BAD_CONTENT_TYPE:
|
||||
responseStatus = 403;
|
||||
errThriftValue = BAD_REQUEST_HEADERS_MSG;
|
||||
responseStatus = 415;
|
||||
errThriftValue = BAD_CONTENT_TYPE_FUNC.apply(ContextUtils.getInterceptionErrorReason(serviceSpan, String.class));
|
||||
break;
|
||||
default:
|
||||
responseStatus = 403;
|
||||
errThriftValue = THRFIT_TRANSPORT_ERROR_MSG;
|
||||
errThriftValue = THRFIT_TRANSPORT_ERROR_FUNC.apply(ContextUtils.getInterceptionErrorReason(serviceSpan, Object.class));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
responseStatus = 403;
|
||||
errThriftValue = THRFIT_TRANSPORT_ERROR_MSG;
|
||||
errThriftValue = THRFIT_TRANSPORT_ERROR_FUNC.apply(ContextUtils.getInterceptionErrorReason(serviceSpan, Object.class));
|
||||
}
|
||||
break;
|
||||
case PROTOCOL:
|
||||
responseStatus = 406;
|
||||
errThriftValue = THRFIT_PROTOCOL_ERROR_MSG;
|
||||
errThriftValue = THRFIT_PROTOCOL_ERROR_FUNC.apply(ContextUtils.getInterceptionErrorReason(serviceSpan, Object.class));
|
||||
break;
|
||||
case UNKNOWN:
|
||||
default:
|
||||
responseStatus = 410;
|
||||
errThriftValue = UNKNOWN_PROVIDER_ERROR_MSG;
|
||||
errThriftValue = UNKNOWN_PROVIDER_ERROR_FUNC.apply(ContextUtils.getInterceptionErrorReason(serviceSpan, Object.class));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
responseStatus = 410;
|
||||
errThriftValue = UNKNOWN_PROVIDER_ERROR_MSG;
|
||||
errThriftValue = UNKNOWN_PROVIDER_ERROR_FUNC.apply(ContextUtils.getInterceptionErrorReason(serviceSpan, Object.class));
|
||||
}
|
||||
break;
|
||||
case APPLICATION_UNKNOWN_ERROR:
|
||||
|
@ -82,9 +82,8 @@ public class AbstractTest {
|
||||
}, new TCompactProtocol.Factory());
|
||||
}
|
||||
|
||||
protected <T> Servlet createThrftRPCService(Class<T> iface, T handler, IdGenerator idGenerator, ServiceEventListener eventListener) {
|
||||
protected <T> Servlet createThrftRPCService(Class<T> iface, T handler, ServiceEventListener eventListener) {
|
||||
THServiceBuilder serviceBuilder = new THServiceBuilder();
|
||||
serviceBuilder.withIdGenerator(idGenerator);
|
||||
serviceBuilder.withEventListener(eventListener);
|
||||
return serviceBuilder.build(iface, handler);
|
||||
}
|
||||
|
@ -1,17 +1,16 @@
|
||||
package com.rbkmoney.woody.thrift.impl.http;
|
||||
|
||||
import com.rbkmoney.woody.api.event.ClientEventListener;
|
||||
import com.rbkmoney.woody.api.event.CompositeClientEventListener;
|
||||
import com.rbkmoney.woody.api.event.CompositeServiceEventListener;
|
||||
import com.rbkmoney.woody.rpc.Owner;
|
||||
import com.rbkmoney.woody.rpc.OwnerService;
|
||||
import com.rbkmoney.woody.rpc.test_error;
|
||||
import com.rbkmoney.woody.thrift.impl.http.event.ClientEventListenerImpl;
|
||||
import com.rbkmoney.woody.thrift.impl.http.event.ClientEventLogListener;
|
||||
import com.rbkmoney.woody.thrift.impl.http.event.ServiceEventListenerImpl;
|
||||
import com.rbkmoney.woody.thrift.impl.http.event.ServiceEventLogListener;
|
||||
import com.rbkmoney.woody.thrift.impl.http.event.*;
|
||||
import org.apache.thrift.TException;
|
||||
import org.apache.thrift.transport.TTransportException;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import javax.servlet.Servlet;
|
||||
@ -21,14 +20,17 @@ import static java.lang.System.out;
|
||||
/**
|
||||
* Created by vpankrashkin on 12.05.16.
|
||||
*/
|
||||
@Ignore
|
||||
|
||||
public class TestChildRequests extends AbstractTest {
|
||||
|
||||
ClientEventListenerImpl clientEventListener = new ClientEventListenerImpl();
|
||||
ServiceEventListenerImpl serviceEventListener = new ServiceEventListenerImpl();
|
||||
ClientEventListener clientEventLogListener = new CompositeClientEventListener(
|
||||
new ClientEventLogListener(),
|
||||
new HttpClientEventLogListener()
|
||||
);
|
||||
|
||||
OwnerService.Iface client1 = createThriftRPCClient(OwnerService.Iface.class, new IdGeneratorStub(), new ClientEventLogListener(), getUrlString("/rpc"));
|
||||
OwnerService.Iface client2 = createThriftRPCClient(OwnerService.Iface.class, new IdGeneratorStub(), new ClientEventLogListener(), getUrlString("/rpc"));
|
||||
OwnerService.Iface client1 = createThriftRPCClient(OwnerService.Iface.class, new IdGeneratorStub(), clientEventLogListener, getUrlString("/rpc"));
|
||||
OwnerService.Iface client2 = createThriftRPCClient(OwnerService.Iface.class, new IdGeneratorStub(), clientEventLogListener, getUrlString("/rpc"));
|
||||
OwnerService.Iface handler = new OwnerServiceStub() {
|
||||
@Override
|
||||
public Owner getErrOwner(int id) throws TException, test_error {
|
||||
@ -47,7 +49,10 @@ public class TestChildRequests extends AbstractTest {
|
||||
}
|
||||
};
|
||||
|
||||
Servlet servlet = createThrftRPCService(OwnerService.Iface.class, handler, new IdGeneratorStub(), new ServiceEventLogListener());
|
||||
Servlet servlet = createThrftRPCService(OwnerService.Iface.class, handler, new CompositeServiceEventListener<>(
|
||||
new ServiceEventLogListener(),
|
||||
new HttpServiceEventLogListener()
|
||||
));
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
|
@ -1,7 +1,7 @@
|
||||
package com.rbkmoney.woody.thrift.impl.http;
|
||||
|
||||
import com.rbkmoney.woody.api.event.CallType;
|
||||
import com.rbkmoney.woody.api.event.ClientEvent;
|
||||
import com.rbkmoney.woody.api.event.ClientEventListener;
|
||||
import com.rbkmoney.woody.api.event.ErrorType;
|
||||
import com.rbkmoney.woody.api.generator.IdGenerator;
|
||||
import com.rbkmoney.woody.rpc.Owner;
|
||||
@ -45,8 +45,7 @@ public class TestClientEventHandling extends AbstractTest {
|
||||
public void testExpectedError() {
|
||||
addServlet(createMutableTervlet(), "/");
|
||||
|
||||
OwnerService.Iface client = (OwnerService.Iface) createThriftRPCClient(OwnerService.Iface.class, new IdGeneratorStub(), (ClientEvent clientEvent) -> {
|
||||
THClientEvent thClientEvent = (THClientEvent) clientEvent;
|
||||
OwnerService.Iface client = createThriftRPCClient(OwnerService.Iface.class, new IdGeneratorStub(), (ClientEventListener<THClientEvent>) (THClientEvent thClientEvent) -> {
|
||||
switch (thClientEvent.getEventType()) {
|
||||
case CALL_SERVICE:
|
||||
assertArrayEquals(new Object[]{0}, thClientEvent.getCallArguments());
|
||||
@ -92,8 +91,7 @@ public class TestClientEventHandling extends AbstractTest {
|
||||
public void testGetOwnerOK() {
|
||||
addServlet(createMutableTervlet(), "/");
|
||||
|
||||
OwnerService.Iface client = createThriftRPCClient(OwnerService.Iface.class, new IdGeneratorStub(), (ClientEvent clientEvent) -> {
|
||||
THClientEvent thClientEvent = (THClientEvent) clientEvent;
|
||||
OwnerService.Iface client = createThriftRPCClient(OwnerService.Iface.class, new IdGeneratorStub(), (ClientEventListener<THClientEvent>) (THClientEvent thClientEvent) -> {
|
||||
switch (thClientEvent.getEventType()) {
|
||||
case CALL_SERVICE:
|
||||
assertArrayEquals(new Object[]{1}, thClientEvent.getCallArguments());
|
||||
@ -134,8 +132,7 @@ public class TestClientEventHandling extends AbstractTest {
|
||||
public void testUnexpectedError() {
|
||||
addServlet(createMutableTervlet(), "/");
|
||||
|
||||
OwnerService.Iface client = createThriftRPCClient(OwnerService.Iface.class, new IdGeneratorStub(), (ClientEvent clientEvent) -> {
|
||||
THClientEvent thClientEvent = (THClientEvent) clientEvent;
|
||||
OwnerService.Iface client = createThriftRPCClient(OwnerService.Iface.class, new IdGeneratorStub(), (ClientEventListener<THClientEvent>) (THClientEvent thClientEvent) -> {
|
||||
switch (thClientEvent.getEventType()) {
|
||||
case CALL_SERVICE:
|
||||
assertArrayEquals(new Object[]{0}, thClientEvent.getCallArguments());
|
||||
|
@ -35,7 +35,7 @@ public class TestEventOrder extends AbstractTest {
|
||||
}
|
||||
};
|
||||
|
||||
Servlet servlet = createThrftRPCService(OwnerService.Iface.class, handler, new IdGeneratorStub(), serviceEventListener);
|
||||
Servlet servlet = createThrftRPCService(OwnerService.Iface.class, handler, serviceEventListener);
|
||||
|
||||
OwnerService.Iface client = createThriftRPCClient(OwnerService.Iface.class, new IdGeneratorStub(), clientEventListener, getUrlString("/rpc"));
|
||||
|
||||
|
@ -1,12 +1,10 @@
|
||||
package com.rbkmoney.woody.thrift.impl.http;
|
||||
|
||||
import com.rbkmoney.woody.api.event.ClientEvent;
|
||||
import com.rbkmoney.woody.api.event.ClientEventListener;
|
||||
import com.rbkmoney.woody.api.event.ServiceEvent;
|
||||
import com.rbkmoney.woody.api.event.ServiceEventListener;
|
||||
import com.rbkmoney.woody.rpc.Owner;
|
||||
import com.rbkmoney.woody.rpc.OwnerService;
|
||||
import com.rbkmoney.woody.rpc.TestHttp;
|
||||
import com.rbkmoney.woody.thrift.impl.http.event.ClientEventListenerImpl;
|
||||
import com.rbkmoney.woody.thrift.impl.http.event.ServiceEventListenerImpl;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.thrift.TException;
|
||||
import org.apache.thrift.protocol.TCompactProtocol;
|
||||
@ -41,13 +39,7 @@ public class TestLoadThriftRPCClient {
|
||||
context.addServlet(defaultServ, "/default");
|
||||
|
||||
THServiceBuilder serviceBuilder = new THServiceBuilder();
|
||||
serviceBuilder.withIdGenerator(new IdGeneratorStub());
|
||||
serviceBuilder.withEventListener(new ServiceEventListener() {
|
||||
@Override
|
||||
public void notifyEvent(ServiceEvent event) {
|
||||
|
||||
}
|
||||
});
|
||||
serviceBuilder.withEventListener(new ServiceEventListenerImpl());
|
||||
Servlet rpcServlet = serviceBuilder.build(OwnerService.Iface.class, new OwnerServiceImpl());
|
||||
ServletHolder rpcServ = new ServletHolder("rpc", rpcServlet);
|
||||
context.addServlet(defaultServ, "/rpc");
|
||||
@ -146,12 +138,7 @@ public class TestLoadThriftRPCClient {
|
||||
clientBuilder.withAddress(new URI(url));
|
||||
clientBuilder.withHttpClient(HttpClientBuilder.create().build());
|
||||
clientBuilder.withIdGenerator(new IdGeneratorStub());
|
||||
clientBuilder.withEventListener(new ClientEventListener() {
|
||||
@Override
|
||||
public void notifyEvent(ClientEvent event) {
|
||||
|
||||
}
|
||||
});
|
||||
clientBuilder.withEventListener(new ClientEventListenerImpl());
|
||||
|
||||
return clientBuilder.build(OwnerService.Iface.class);
|
||||
}
|
||||
|
@ -1,12 +1,11 @@
|
||||
package com.rbkmoney.woody.thrift.impl.http.event;
|
||||
|
||||
import com.rbkmoney.woody.api.event.ClientEvent;
|
||||
import com.rbkmoney.woody.api.event.ClientEventListener;
|
||||
|
||||
/**
|
||||
* Created by vpankrashkin on 12.05.16.
|
||||
*/
|
||||
public class ClientEventListenerImpl implements ClientEventListener {
|
||||
public class ClientEventListenerImpl implements ClientEventListener<THClientEvent> {
|
||||
private ClientActionListener eventActionListener;
|
||||
|
||||
public ClientEventListenerImpl() {
|
||||
@ -21,7 +20,7 @@ public class ClientEventListenerImpl implements ClientEventListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyEvent(ClientEvent event) {
|
||||
public void notifyEvent(THClientEvent event) {
|
||||
switch (event.getEventType()) {
|
||||
case CALL_SERVICE:
|
||||
if (eventActionListener != null)
|
||||
|
@ -1,12 +1,11 @@
|
||||
package com.rbkmoney.woody.thrift.impl.http.event;
|
||||
|
||||
import com.rbkmoney.woody.api.event.ServiceEvent;
|
||||
import com.rbkmoney.woody.api.event.ServiceEventListener;
|
||||
|
||||
/**
|
||||
* Created by vpankrashkin on 12.05.16.
|
||||
*/
|
||||
public class ServiceEventListenerImpl implements ServiceEventListener {
|
||||
public class ServiceEventListenerImpl implements ServiceEventListener<THServiceEvent> {
|
||||
private volatile ServiceActionListener eventActionListener;
|
||||
|
||||
public ServiceEventListenerImpl() {
|
||||
@ -21,7 +20,7 @@ public class ServiceEventListenerImpl implements ServiceEventListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyEvent(ServiceEvent event) {
|
||||
public void notifyEvent(THServiceEvent event) {
|
||||
switch (event.getEventType()) {
|
||||
case CALL_HANDLER:
|
||||
if (eventActionListener != null)
|
||||
|
@ -3,7 +3,8 @@ namespace java com.rbkmoney.woody.rpc
|
||||
typedef i32 int // We can use typedef to get pretty names for the types we are using
|
||||
struct Owner {
|
||||
1:int id,
|
||||
2:string name
|
||||
2:string name,
|
||||
3:optional string value;
|
||||
}
|
||||
|
||||
exception test_error {
|
||||
|
Loading…
Reference in New Issue
Block a user