Skip to content

Commit

Permalink
enhance(monitor): add druid monitor (#1088)
Browse files Browse the repository at this point in the history
* add druid monitor

* add druid monitor

* format

* add back connection cluster name

* format

* format

* format

* format

* format

* review

* review

* rename

* review

---------

Co-authored-by: ungreat <[email protected]>
  • Loading branch information
ungreat and ungreat authored Dec 14, 2023
1 parent bf0f943 commit 9816be0
Show file tree
Hide file tree
Showing 12 changed files with 943 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -336,4 +336,58 @@ public static Boolean checkPort(String port) {
return matcher.matches();
}

public static String removeWhitespace(String input) {
if (input == null) {
return null;
}
return input.replaceAll("\\s+", "");
}

public static String getBriefSql(String sql, Integer maxLength) {
if (sql == null) {
return null;
}
if (maxLength == 0) {
return "";
}
if (maxLength < 50) {
return sql.substring(0, maxLength);
}

final int sqlLength = sql.length();
if (sqlLength <= maxLength) {
return sql;
}
String lowerCaseSql = sql.toLowerCase();
final String from = "from";
final String omit = "...";
int fromIndex = lowerCaseSql.indexOf(from);
// tree part
if (fromIndex != -1) {
int partLength = maxLength / 3;
int fromPartEnd = Math.min(fromIndex + partLength, sqlLength);
String middle = sql.substring(fromIndex, fromPartEnd);
if (sqlLength - fromPartEnd <= partLength) {
// means end part not need compress
int beginPartEndPox = maxLength - (sqlLength - fromIndex);
String beginPart = sql.substring(0, beginPartEndPox - omit.length()) + omit;
return beginPart + sql.substring(fromIndex, sqlLength);
}
if (fromIndex <= partLength) {
int endPartLength = maxLength - fromPartEnd;
String endPart = omit + sql.substring(sqlLength - endPartLength + omit.length(), sqlLength);
return sql.substring(0, fromPartEnd) + endPart;
}
String beginPart = sql.substring(0, partLength - omit.length()) + omit;
int endPartLength = maxLength - (beginPart.length() + middle.length());
String endPart = omit + sql.substring(sqlLength - endPartLength + omit.length(), sqlLength);
return beginPart + middle + endPart;
} else {
int partLength = maxLength / 2;
String start = sql.substring(0, partLength - omit.length());
String end = sql.substring(sqlLength - partLength);
return start + "..." + end;
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -316,4 +316,40 @@ public void removeFirstStart_Null() {
String result = StringUtils.removeFirstStart(null, "hedll", "gret");
Assert.assertNull(result);
}

@Test
public void test_from_close_begin_getBriefSql() {
String sql =
"select * as asasdjadnjabdasdahjdknkqndjbjfbcdcxvnsdwqjdnjwqdnscasndknadjbascbadnasndqwbdqwbjd from t_user where id=1";
String briefSql = StringUtils.getBriefSql(sql, 70);
System.out.println(briefSql);
Assert.assertEquals(briefSql.length(), 70);
}

@Test
public void test_from_close_end_getBriefSql() {
String sql =
"select * from t_user where id=1 and name='asasdjadnjabdasdahjdknkqndjbjfbcdcxvnsdqjdnjwqdnscasndknadjbascbadnasndqwbdqwbjd'";
String briefSql = StringUtils.getBriefSql(sql, 70);
System.out.println(briefSql);
Assert.assertEquals(briefSql.length(), 70);
}

@Test
public void test_from_close_middle_getBriefSql() {
String sql =
"select * as asasdjadnjabdasdahjdknkqndjbjfbcdcxvnsdwqjdnjwqdnscasndknadjbascbadnasndqwbdqwbjd from t_user where id=1 and name='asasdjadnjabdasdahjdknkqndjbjfbcdcxvnsdqjdnjwqdnscasndknadjbascbadnasndqwbdqwbjd'";
String briefSql = StringUtils.getBriefSql(sql, 70);
System.out.println(briefSql);
Assert.assertEquals(briefSql.length(), 70);
}

@Test
public void test_no_fromgetBriefSql() {
String sql =
"insert into test_db (id,version,name) values(1,0,'awsdajsdashbdhabdhabshdbashdbashbdjhasbdhasbdhnczhdqwbdba')";
String briefSql = StringUtils.getBriefSql(sql, 50);
System.out.println(briefSql);
Assert.assertEquals(briefSql.length(), 50);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,17 @@ public final class AlarmEventNames {
private AlarmEventNames() {}

public static final String SYSTEM_CONFIG_CHANGED = "SYSTEM_CONFIG_CHANGED";

/**
* Druid alarm
*/
public static final String SQL_TOO_LONG_SQL_PARAMETERS = "SQL_TOO_LONG_SQL_PARAMETERS";
public static final String SQL_TOO_LONG_EXECUTE_TIME = "SQL_TOO_LONG_EXECUTE_TIME";
public static final String SQL_EXECUTE_ERROR = "SQL_EXECUTE_ERROR";
public static final String METHOD_TOO_LONG_EXECUTE_TIME = "METHOD_TOO_LONG_EXECUTE_TIME";
public static final String METHOD_TOO_MUCH_JDBC_EXECUTE_COUNT = "METHOD_TOO_MUCH_JDBC_EXECUTE_COUNT";
public static final String DRUID_MONITOR_ERROR = "DRUID_MONITOR_ERROR";
public static final String DRUID_WAIT_THREAD_COUNT_MORE_THAN_0 = "DRUID_WAIT_THREAD_COUNT_MORE_THAN_0";
public static final String DRUID_ACTIVE_COUNT_MORE_THAN_80_PERCENT = "DRUID_ACTIVE_COUNT_MORE_THAN_80_PERCENT";

}
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,9 @@ class AlarmService {
public AlarmService() {
ServiceLoader<AlarmEventListener> load = ServiceLoader.load(AlarmEventListener.class);
Iterator<AlarmEventListener> iterator = load.iterator();
log.info("AlarmEventListener has next:" + iterator.hasNext());
while (iterator.hasNext()) {
AlarmEventListener next = iterator.next();
log.info("AlarmEventListener:" + next.getClass().getName() + "have been loaded");
log.debug("AlarmEventListener:" + next.getClass().getName() + "have been loaded");
listeners.add(next);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ spring:
enabled: true
slow-sql-millis: 1000
log-slow-sql: true
merge-sql: true
jpa:
open-in-view: false
sql:
Expand Down
40 changes: 40 additions & 0 deletions server/odc-server/src/main/resources/log4j2.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
<Property name="API_LOG_PATTERN">
[%date{yyyy-MM-dd HH:mm:ss.SSS}][%thread][%X{traceId},%X{spanId},%X{requestId}][%level]: %message%n
</Property>
<Property name="MONITOR_PATTERN">
[%date{yyyy-MM-dd HH:mm:ss.SSS}][%level]: %message%n
</Property>
</Properties>

<Appenders>
Expand Down Expand Up @@ -65,6 +68,34 @@
<Policies>
<SizeBasedTriggeringPolicy size="100MB"/>
</Policies>
<DefaultRolloverStrategy max="20">
<Delete basePath="${LOG_DIRECTORY}" maxDepth="2">
<IfFileName glob="*.log*"/>
<IfLastModified age="7d"/>
</Delete>
</DefaultRolloverStrategy>
</RollingFile>

<RollingFile name="OdcSQLMonitorFileAppender" fileName="${LOG_DIRECTORY}/sql-monitor.log"
filePattern="${LOG_DIRECTORY}/sql-monitor-%d{yyyy-MM-dd}-%i.log">
<PatternLayout pattern="${MONITOR_PATTERN}"/>
<Policies>
<SizeBasedTriggeringPolicy size="100MB"/>
</Policies>
<DefaultRolloverStrategy max="20">
<Delete basePath="${LOG_DIRECTORY}" maxDepth="2">
<IfFileName glob="*.log*"/>
<IfLastModified age="7d"/>
</Delete>
</DefaultRolloverStrategy>
</RollingFile>

<RollingFile name="OdcMethodMonitorFileAppender" fileName="${LOG_DIRECTORY}/method-monitor.log"
filePattern="${LOG_DIRECTORY}/method-monitor-%d{yyyy-MM-dd}-%i.log">
<PatternLayout pattern="${MONITOR_PATTERN}"/>
<Policies>
<SizeBasedTriggeringPolicy size="100MB"/>
</Policies>
<DefaultRolloverStrategy max="20">
<Delete basePath="${LOG_DIRECTORY}" maxDepth="2">
<IfFileName glob="*.log*"/>
Expand Down Expand Up @@ -469,6 +500,15 @@
<Logger name="com.oceanbase.odc.core.alarm.AlarmService" level="INFO" additivity="false">
<AppenderRef ref="OdcAlarmFileAppender" />
</Logger>

<Logger name="SqlMonitorLogger" additivity="false" level="INFO">
<AppenderRef ref="OdcSQLMonitorFileAppender"/>
</Logger>

<Logger name="MethodMonitorLogger" additivity="false" level="INFO">
<AppenderRef ref="OdcMethodMonitorFileAppender"/>
</Logger>

<!-- 导入导出程序日志输出 -->
<Logger name="DataTransferLogger" additivity="false" level="INFO">
<AppenderRef ref="LoadDumpInfoRoutingAppender"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import com.alibaba.druid.support.spring.stat.DruidStatInterceptor;
import com.oceanbase.odc.common.concurrent.ExecutorUtils;
import com.oceanbase.odc.common.util.SystemUtils;
import com.oceanbase.odc.config.jpa.EnhancedJpaRepository;
Expand Down Expand Up @@ -94,6 +95,11 @@ public PlatformTransactionManager metadbTransactionManager(
return new JpaTransactionManager(Objects.requireNonNull(metadbEntityManagerFactory.getObject()));
}

@Bean
public DruidStatInterceptor druidStatInterceptor() {
return new DruidStatInterceptor();
}

@Primary
@Bean(name = "metadbSqlSessionFactory")
@DependsOn("metadbMigrate")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ public void refreshSysConfig() {
}

@Scheduled(fixedRate = SHORT_VALIDATE_INTERVAL_MS)
private void clearExpiredTask() {
public void clearExpiredTask() {
SensitiveColumnScanningResultCache.getInstance().clearExpiredTaskInfo();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright (c) 2023 OceanBase.
*
* Licensed 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 com.oceanbase.odc.config.druid;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface DruidMonitor {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright (c) 2023 OceanBase.
*
* Licensed 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 com.oceanbase.odc.config.druid;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.alibaba.druid.support.spring.stat.DruidStatInterceptor;

@Aspect
@Component
public class DruidMonitorAspect {

private final DruidStatInterceptor druidStatInterceptor;

@Autowired
public DruidMonitorAspect(DruidStatInterceptor druidStatInterceptor) {
this.druidStatInterceptor = druidStatInterceptor;
}

@Pointcut("within(@org.springframework.stereotype.Controller *) || within(@org.springframework.web.bind.annotation.RestController *)")
public void controllerMethods() {}

@Around("@annotation(DruidMonitor)")
public Object aroundDruidMonitor(ProceedingJoinPoint joinPoint) throws Throwable {
return druidStatInterceptor.invoke(new JointPointMethodInvocationAdapter(joinPoint));
}

@Around("controllerMethods()")
public Object aroundDruidMonitorClass(ProceedingJoinPoint joinPoint) throws Throwable {
return druidStatInterceptor.invoke(new JointPointMethodInvocationAdapter(joinPoint));
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright (c) 2023 OceanBase.
*
* Licensed 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 com.oceanbase.odc.config.druid;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Method;

import org.aopalliance.intercept.MethodInvocation;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;

class JointPointMethodInvocationAdapter implements MethodInvocation {
private final ProceedingJoinPoint joinPoint;
private final MethodSignature methodSignature;
private final Method method;

public JointPointMethodInvocationAdapter(ProceedingJoinPoint joinPoint) {
this.joinPoint = joinPoint;
this.methodSignature = (MethodSignature) joinPoint.getSignature();
this.method = methodSignature.getMethod();
}

@Override
public Object proceed() throws Throwable {
return joinPoint.proceed();
}

@Override
public Object getThis() {
return joinPoint.getThis();
}

@Override
public Object[] getArguments() {
return joinPoint.getArgs();
}

@Override
public Method getMethod() {
return method;
}

@Override
public AccessibleObject getStaticPart() {
return method;
}
}
Loading

0 comments on commit 9816be0

Please sign in to comment.