是否可以在没有@Observed的情况下使用@Scheduled,并且无需在每个任务中尝试捕获并且仍然具有traceId?

问题描述 投票:0回答:1

我的目标是在计划方法上仅使用 @Scheduled 注释,并且跟踪应该自动发生(无论是 log.info() 还是异常)。

我尝试通过创建自定义 TaskDecorator 来实现这一点,但它不起作用。

调度程序配置:

@Configuration
@RequiredArgsConstructor
@EnableScheduling
public class SchedulerConfiguration {
    private final ObservationRegistry observationRegistry;

    @Value("${spring.task.scheduling.pool.size}")
    private Integer taskSchedulingPoolSize;

    @Bean
    public TaskScheduler taskScheduler() {
        ConcurrentTaskScheduler scheduler = new ConcurrentTaskScheduler(new ScheduledThreadPoolExecutor(taskSchedulingPoolSize));
        scheduler.setTaskDecorator(new ExecutorTaskDecorator(observationRegistry));
        scheduler.setErrorHandler(new ExceptionHandler());

        return scheduler;
    }
}

观察配置:

@Configuration
public class ObservationConfiguration {
    @Bean
    ObservedAspect observedAspect(ObservationRegistry observationRegistry) {
        return new ObservedAspect(observationRegistry);
    }
}

异常处理程序:

@Slf4j
public class ExceptionHandler implements ErrorHandler {
    @Override
    public void handleError(Throwable t) {
        log.error("Task threw an exception: {}", t.getMessage(), t);
    }
}
@Scheduled(initialDelay = 0, fixedDelay = 1000")
public void start() {
   throw new RunTimeException("test");
}

任务装饰器的第一种方法:

public class ExecutorTaskDecorator implements TaskDecorator {
    private final ObservationRegistry observationRegistry;

    public ExecutorTaskDecorator(ObservationRegistry observationRegistry) {
        this.observationRegistry = observationRegistry;
    }

    @Override
    public Runnable decorate(Runnable runnable) {
        return Observation.createNotStarted("task.run", observationRegistry)
                .observe(() -> runnable::run);
    }
}

任务装饰器的第二种方法:

public class ExecutorTaskDecorator implements TaskDecorator {
    @Override
    public Runnable decorate(Runnable runnable) {
        return runWithObserved(runnable);
    }

    @Observed
    private Runnable runWithObserved(Runnable runnable) {
        return () -> runnable.run();
    }
}

这两种方法都不起作用。

TraceId 和 SpanId 仅当我将 @Observed 添加到

start()
方法并用 try catch 块包装时才会发生。

我正在使用 spring boot 3.1.3、spring-boot-starter-actuator (3.1.3) 和 micrometer-tracing-bridge-brave (1.1.4)。

我错过了什么吗? 甚至可以这样使用它吗? 对于 HTTP 请求,一切正常。

spring-boot spring-boot-actuator micrometer spring-micrometer micrometer-tracing
1个回答
0
投票

感谢 @m-deinum 的建议,我使用方面完成了这项工作。

@Aspect
@Component
@RequiredArgsConstructor
@Slf4j
public class ScheduledAspect {
    private final ObservationRegistry observationRegistry;

    @Pointcut("@annotation(org.springframework.scheduling.annotation.Scheduled)")
    public void annotatedWithScheduled() {}

    @Around("annotatedWithScheduled()")
    public Object wrapScheduled(ProceedingJoinPoint pjp) {
        var methodName = pjp.getSignature().getDeclaringTypeName() + "." + pjp.getSignature().getName();

        return Observation.createNotStarted(methodName, observationRegistry)
                .observe(() -> proceed(pjp));
    }

    private Object proceed(ProceedingJoinPoint pjp) {
        try {
            return pjp.proceed();
        } catch (Throwable t) {
            log.error("Task threw an exception: {}", t.getMessage(), t);
        }
        return null;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.