package com.yammer.telemetry.agent.handlers; import com.google.common.base.Optional; import com.yammer.telemetry.tracing.Span; import com.yammer.telemetry.tracing.SpanHelper; import java.math.BigInteger; import java.util.concurrent.*; @SuppressWarnings("UnusedDeclaration") public class InstrumentedScheduledThreadPoolExecutor extends ScheduledThreadPoolExecutor { private ThreadLocal<Span> local = new ThreadLocal<>(); public InstrumentedScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize); } public InstrumentedScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory) { super(corePoolSize, threadFactory); } public InstrumentedScheduledThreadPoolExecutor(int corePoolSize, RejectedExecutionHandler handler) { super(corePoolSize, handler); } public InstrumentedScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory, RejectedExecutionHandler handler) { super(corePoolSize, threadFactory, handler); } @Override protected <V> RunnableScheduledFuture<V> decorateTask(Runnable runnable, RunnableScheduledFuture<V> task) { return decoratedTask(runnable, super.decorateTask(runnable, task)); } @Override protected <V> RunnableScheduledFuture<V> decorateTask(Callable<V> callable, RunnableScheduledFuture<V> task) { return decoratedTask(callable, super.decorateTask(callable, task)); } @Override protected void beforeExecute(Thread t, Runnable r) { super.beforeExecute(t, r); if (r instanceof InstrumentedRunnableScheduledFuture) { InstrumentedRunnableScheduledFuture instrumentedRunnable = (InstrumentedRunnableScheduledFuture) r; BigInteger traceId = instrumentedRunnable.getTraceId(); BigInteger spanId = instrumentedRunnable.getSpanId(); if (traceId != null && spanId != null) { Span span = SpanHelper.attachSpan(traceId, spanId, instrumentedRunnable.getName()); local.set(span); span.addAnnotation("Before", instrumentedRunnable.getName()); } } } @Override protected void afterExecute(Runnable r, Throwable t) { try { super.afterExecute(r, t); if (r instanceof InstrumentedRunnableScheduledFuture) { Span span = local.get(); if (span != null) { span.addAnnotation("After", ((InstrumentedRunnableScheduledFuture) r).getName()); span.end(); } } } finally { local.remove(); } } private <T, V> RunnableScheduledFuture<V> decoratedTask(T task, RunnableScheduledFuture<V> vRunnableScheduledFuture) { Optional<Span> currentSpan = SpanHelper.currentSpan(); if (currentSpan.isPresent()) { currentSpan.get().addAnnotation("Scheduled Task", task.getClass().getName()); return new InstrumentedRunnableScheduledFuture<>(vRunnableScheduledFuture, task.getClass().getName(), currentSpan.get().getTraceId(), currentSpan.get().getSpanId()); } return vRunnableScheduledFuture; } }