diff --git a/fe/fe-core/src/main/java/org/apache/doris/httpv2/HttpServer.java b/fe/fe-core/src/main/java/org/apache/doris/httpv2/HttpServer.java index 88ec1a1b9f93e8d..23be5a1e01b86f8 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/httpv2/HttpServer.java +++ b/fe/fe-core/src/main/java/org/apache/doris/httpv2/HttpServer.java @@ -28,6 +28,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.web.servlet.ServletComponentScan; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; +import org.springframework.context.annotation.EnableAspectJAutoProxy; import java.util.HashMap; import java.util.Map; @@ -35,6 +36,7 @@ @SpringBootApplication @EnableConfigurationProperties @ServletComponentScan +@EnableAspectJAutoProxy public class HttpServer extends SpringBootServletInitializer { private int port; private int httpsPort; diff --git a/fe/fe-core/src/main/java/org/apache/doris/tools/WatchLockMonitoringAspect.java b/fe/fe-core/src/main/java/org/apache/doris/tools/WatchLockMonitoringAspect.java new file mode 100644 index 000000000000000..9d2d1cb34ccefca --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/tools/WatchLockMonitoringAspect.java @@ -0,0 +1,68 @@ +// 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.doris.tools; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.springframework.stereotype.Component; + +@Component +@Aspect +public class WatchLockMonitoringAspect { + private static final Logger LOG = LogManager.getLogger(WatchLockMonitoringAspect.class); + private static final long THRESHOLD_NS = 10_000_000_000L; // 10 seconds in nanoseconds + + private Object logLockAction(String action, String lockType, ProceedingJoinPoint joinPoint, long startTime) throws Throwable { + String threadName = Thread.currentThread().getName(); + try { + return joinPoint.proceed(); + } finally { + long endTime = System.nanoTime(); + long duration = endTime - startTime; + String durationMessage = String.format("%s lock %s by thread %s: held for %d ns", lockType, action, threadName, duration); + + if (duration > THRESHOLD_NS) { + LOG.warn(durationMessage + " - Thread info: " + getThreadInfo()); + } else { + LOG.info(durationMessage); + } + } + } + + private String getThreadInfo() { + Thread currentThread = Thread.currentThread(); + return String.format("Thread ID: %d, Name: %s, State: %s, Priority: %d", + currentThread.getId(), currentThread.getName(), currentThread.getState(), currentThread.getPriority()); + } + + @Around("execution(* java.util.concurrent.locks.ReentrantReadWriteLock$ReadLock.lock(..))") + public Object monitorReadLockLock(ProceedingJoinPoint joinPoint) throws Throwable { + long startTime = System.nanoTime(); + return logLockAction("acquired", "Read", joinPoint, startTime); + } + + @Around("execution(* java.util.concurrent.locks.ReentrantReadWriteLock$WriteLock.lock(..))") + public Object monitorWriteLockLock(ProceedingJoinPoint joinPoint) throws Throwable { + long startTime = System.nanoTime(); + return logLockAction("acquired", "Write", joinPoint, startTime); + } + +}