Commit ab100b50 authored by 董建华's avatar 董建华

sentry异常后钉钉备用

parents
Pipeline #956 canceled with stages
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.5</version>
<relativePath/>
<!-- lookup parent from repository -->
</parent>
<groupId>cn.quangroup</groupId>
<artifactId>spring-boot-starter-sentry-dingding</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-starter-sentry-dingding</name>
<description>sentry超时的时候钉钉备用</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<start-class></start-class>
<java.version>1.8</java.version>
<sentry.version>1.6.4</sentry.version>
<maven.compiler.plugin.version>3.6.1</maven.compiler.plugin.version>
<retrofit.version>2.4.0</retrofit.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>io.sentry</groupId>
<artifactId>sentry-logback</artifactId>
<version>${sentry.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.6</version>
</dependency>
<dependency>
<groupId>cn.quantgroup</groupId>
<artifactId>spring-boot-starter-sentry</artifactId>
<version>1.0.9</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
<scope>provided</scope>
</dependency>
<!-- okhttp start -->
<dependency>
<groupId>com.squareup.retrofit2</groupId>
<artifactId>retrofit</artifactId>
<version>${retrofit.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.61</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>1.5.8.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven.compiler.plugin.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>product</id>
<distributionManagement>
<repository>
<id>Releases</id>
<name>Releases Repository</name>
<url>http://repo.quantgroup.cn/nexus/content/repositories/lkb-releases/</url>
</repository>
</distributionManagement>
</profile>
</profiles>
</project>
package cn.quantgroup.config;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* @author :dongjianhua
* @date :Created in 2021/5/14 14:34
* @description:
* @modified By:
* @version:
*/
@Slf4j
public class DefaultDingDingExceptionHandler implements SentryExceptionHandler {
private final String dingDingHost = "https://oapi.dingtalk.com/robot/send?access_token=";
private ThrErrProProperties proProperties;
OkHttpClient client;
private final String dingDingUrl;
DefaultDingDingExceptionHandler(ThrErrProProperties proProperties) {
this.proProperties = proProperties;
this.client = new OkHttpClient();
this.dingDingUrl = dingDingHost.concat(proProperties.getDingDingToken());
}
@Override
public void handle(Exception e) {
Map<String, Object> result = new HashMap<String, Object>();
result.put("msgtype", "markdown");
Map<String, Object> markdown = new HashMap<String, Object>();
markdown.put("title", "sentry失效转钉钉告警");
markdown.put("text", e.getMessage());
result.put("markdown", markdown);
String s = JSON.toJSONString(result);
try {
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, s);
Request request = new Request.Builder()
.url(dingDingUrl)
.post(body)
.addHeader("content-type", "application/json")
.build();
Response response = client.newCall(request).execute();
} catch (IOException e2) {
}
/**
*
*/
log.info("sentry异常了现在用DIngding进行告警");
}
}
package cn.quantgroup.config;
import cn.quantgroup.sentry.config.SentryConstant;
import cn.quantgroup.sentry.config.SentryProperties;
import io.sentry.Sentry;
import io.sentry.SentryClient;
import io.sentry.SentryClientFactory;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author :dongjianhua
* @date :Created in 2021/5/14 9:53
* @description:
* @modified By:
* @version:
*/
@Slf4j
@Configuration
@EnableConfigurationProperties({SentryProperties.class,ThrErrProProperties.class})
public class SentryDingdingConfiguration {
@Autowired
private SentryProperties properties;
@Autowired
private ThrErrProProperties thrErrProProperties;
@Autowired
private SentryClient sentryClient;
@ConfigurationProperties(
prefix = "threrr"
)
@Bean("thrErrSentryClient")
public SentryClient thrErrSentryClient() {
log.info("init sentry client... dsn:{}", this.properties.getDsn());
SentryExceptionHandler sentryDingdingExceptionHandler = getSentryDingdingExceptionHandler();
SentryClientFactory sentryClientFactory = new ThrErrSentryClientFactory(sentryDingdingExceptionHandler);
SentryClient sentryClient = Sentry.init(this.properties.getDsn(), sentryClientFactory);
String[] tagArr;
String[] var3;
int var4;
int var5;
String tag;
if (StringUtils.isNotBlank(this.properties.getMdcTags())) {
tagArr = this.properties.getMdcTags().split(",");
var3 = tagArr;
var4 = tagArr.length;
for(var5 = 0; var5 < var4; ++var5) {
tag = var3[var5];
if (StringUtils.isNotBlank(tag)) {
sentryClient.addMdcTag(tag);
}
}
}
if (StringUtils.isNotBlank(this.properties.getMsgTags())) {
tagArr = this.properties.getMsgTags().split(",");
var3 = tagArr;
var4 = tagArr.length;
for(var5 = 0; var5 < var4; ++var5) {
tag = var3[var5];
if (StringUtils.isNotBlank(tag)) {
SentryConstant.addMsgTag(tag);
}
}
}
return sentryClient;
}
private SentryExceptionHandler getSentryDingdingExceptionHandler(){
String exceptionHandlerFactoryClassName = thrErrProProperties.getExceptionHandlerClassName();
if(null != exceptionHandlerFactoryClassName){
//todo 待完善自定义
}
return new DefaultDingDingExceptionHandler(thrErrProProperties);
}
}
package cn.quantgroup.config;
public interface SentryExceptionHandler {
public void handle(Exception e);
}
package cn.quantgroup.config;
import io.sentry.connection.Connection;
import io.sentry.connection.ConnectionException;
import io.sentry.connection.EventSendCallback;
import io.sentry.event.Event;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
/**
* @author :dongjianhua
* @date :Created in 2021/5/14 14:01
* @description:
* @modified By:
* @version:
*/
@Slf4j
public class ThrErrAsyncConnectionWarp implements Connection {
private final Connection connection ;
private final SentryExceptionHandler handler ;
ThrErrAsyncConnectionWarp(Connection connection,SentryExceptionHandler handler){
this.connection = connection;
this.handler = handler;
}
@Override
public void send(Event event) throws ConnectionException {
try {
log.info("要异常了");
connection.send(event);
}catch (Exception e){
handler.handle(e);
throw e;
}
}
@Override
public void addEventSendCallback(EventSendCallback eventSendCallback) {
connection.addEventSendCallback(eventSendCallback);
}
@Override
public void close() throws IOException {
connection.close();
}
}
package cn.quantgroup.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.Map;
/**
* @author :dongjianhua
* @date :Created in 2021/5/14 14:40
* @description:
* @modified By:
* @version:
*/
@ConfigurationProperties(
prefix = "threrr"
)
@Data
public class ThrErrProProperties {
private String dingDingToken;
private String exceptionHandlerClassName;
private Map<String,Object> dataProProperties;
}
package cn.quantgroup.config;
import io.sentry.SentryClient;
import io.sentry.connection.Connection;
import io.sentry.connection.LockedDownException;
import io.sentry.context.ContextManager;
import io.sentry.event.Event;
import io.sentry.event.helper.ShouldSendEventCallback;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashSet;
import java.util.Set;
/**
* @author :dongjianhua
* @date :Created in 2021/5/14 10:01
* @description:
* @modified By:
* @version:
*/
@Slf4j
public class ThrErrSentryClient extends SentryClient {
private static final Logger lockdownLogger = LoggerFactory.getLogger(ThrErrSentryClient.class.getName() + ".lockdown");
/**
* The underlying {@link Connection} to use for sending events to Sentry.
*/
private final Connection connection;
/**
* Set of callbacks that are checked before each {@link Event} is sent to Sentry.
*/
private final Set<ShouldSendEventCallback> shouldSendEventCallbacks = new HashSet<>();
/**
* Constructs a {@link SentryClient} instance using the provided connection.
* <p>
* Note that the most recently constructed instance is stored statically so it can be used with
* the static helper methods.
*
* @param connection Underlying {@link Connection} instance to use for sending events
* @param contextManager {@link ContextManager} instance to use for storing contextual data
*/
ThrErrSentryClient(Connection connection, ContextManager contextManager) {
super(connection, contextManager);
this.connection = connection;
}
/**
* Add a callback that is called before an {@link Event} is sent to Sentry.
*
* @param shouldSendEventCallback callback instance
*/
@Override
public void addShouldSendEventCallback(ShouldSendEventCallback shouldSendEventCallback) {
shouldSendEventCallbacks.add(shouldSendEventCallback);
}
/**
* Sends a built {@link Event} to the Sentry server.
*
* @param event event to send to Sentry.
*/
@Override
public void sendEvent(Event event) {
for (ShouldSendEventCallback shouldSendEventCallback : shouldSendEventCallbacks) {
if (!shouldSendEventCallback.shouldSend(event)) {
log.trace("Not sending Event because of ShouldSendEventCallback: {}", shouldSendEventCallback);
return;
}
}
try {
connection.send(event);
} catch (LockedDownException e) {
lockdownLogger.warn("The connection to Sentry is currently locked down.", e);
} catch (Exception e) {
log.error("An exception occurred while sending the event to Sentry.", e);
} finally {
getContext().setLastEventId(event.getId());
}
}
}
package cn.quantgroup.config;
import io.sentry.DefaultSentryClientFactory;
import io.sentry.SentryClient;
import io.sentry.connection.AsyncConnection;
import io.sentry.connection.Connection;
import io.sentry.dsn.Dsn;
import io.sentry.event.helper.ContextBuilderHelper;
import io.sentry.event.helper.HttpEventBuilderHelper;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author :dongjianhua
* @date :Created in 2021/5/14 10:03
* @description:
* @modified By:
* @version:
*/
@Slf4j
public class ThrErrSentryClientFactory extends DefaultSentryClientFactory {
private SentryExceptionHandler exceptionHandler;
ThrErrSentryClientFactory(SentryExceptionHandler exceptionHandler) {
this.exceptionHandler = exceptionHandler;
}
@Override
public SentryClient createSentryClient(Dsn dsn) {
SentryClient sentryClient = new ThrErrSentryClient(createConnection(dsn), getContextManager(dsn));
try {
// `ServletRequestListener` was added in the Servlet 2.4 API, and
// is used as part of the `HttpEventBuilderHelper`, see:
// https://tomcat.apache.org/tomcat-5.5-doc/servletapi/
Class.forName("javax.servlet.ServletRequestListener", false, this.getClass().getClassLoader());
sentryClient.addBuilderHelper(new HttpEventBuilderHelper());
} catch (ClassNotFoundException e) {
log.debug("The current environment doesn't provide access to servlets,"
+ " or provides an unsupported version.");
}
sentryClient.addBuilderHelper(new ContextBuilderHelper(sentryClient));
return configureSentryClient(sentryClient, dsn);
}
/**
* Encapsulates an already existing connection in an {@link AsyncConnection} and get the async options from the
* Sentry DSN.
*
* @param dsn Data Source Name of the Sentry server.
* @param connection Connection to encapsulate in an {@link AsyncConnection}.
* @return the asynchronous connection.
*/
protected Connection createAsyncConnection(Dsn dsn, Connection connection) {
int maxThreads = getAsyncThreads(dsn);
int priority = getAsyncPriority(dsn);
BlockingDeque<Runnable> queue;
int queueSize = getAsyncQueueSize(dsn);
if (queueSize == -1) {
queue = new LinkedBlockingDeque<>();
} else {
queue = new LinkedBlockingDeque<>(queueSize);
}
ExecutorService executorService = new ThreadPoolExecutor(
maxThreads, maxThreads, 0L, TimeUnit.MILLISECONDS, queue,
new DaemonThreadFactory(priority), getRejectedExecutionHandler(dsn));
boolean gracefulShutdown = getAsyncGracefulShutdownEnabled(dsn);
long shutdownTimeout = getAsyncShutdownTimeout(dsn);
ThrErrAsyncConnectionWarp warp = new ThrErrAsyncConnectionWarp(connection, exceptionHandler);
return new AsyncConnection(warp, executorService, gracefulShutdown, shutdownTimeout);
}
@SuppressWarnings("PMD.AvoidThreadGroup")
protected static final class DaemonThreadFactory implements ThreadFactory {
private static final AtomicInteger POOL_NUMBER = new AtomicInteger(1);
private final ThreadGroup group;
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix;
private final int priority;
private DaemonThreadFactory(int priority) {
SecurityManager s = System.getSecurityManager();
group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
namePrefix = "sentry-pool-" + POOL_NUMBER.getAndIncrement() + "-thread-";
this.priority = priority;
}
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
if (!t.isDaemon()) {
t.setDaemon(true);
}
if (t.getPriority() != priority) {
t.setPriority(priority);
}
return t;
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment