1. 기능 소개
구현 논리: 일반적인 상황에서 코드는 예외가 발생한 예외를 처리합니다. 이 기사에서는 로그를 인쇄할 때, 또한 비정상적인 정보는 Slack 채널로 전송됩니다. 개발 또는 운영 및 유지 관리 담당자는 Slack 계정을 생성하고 채널에 가입하여 실시간으로 비정상적인 정보에 대한 알림을 받을 수 있습니다.
2. Slack 소개
Slack 데스크톱/노트북 컴퓨터, 모바일 기기에서 단일 애플리케이션으로, 웹 애플리케이션으로 사용할 수 있는 웹 기반 실시간 커뮤니케이션 도구입니다. 기본적으로 이곳은 개인 채팅 및 협업 공간입니다. 많은 회사에서 이메일/비공개 포럼/채팅룸을 기본 내부 텍스트 기반 커뮤니케이션 채널로 대체했습니다.
채팅 그룹 + 대규모 도구 통합 + 파일 통합 + 통합 검색으로 이해될 수 있습니다. 2014년 말 현재 Slack은 이메일, 문자 메시지, Google 드라이브, Twitter, Trello, Asana, GitHub 등 65개의 도구와 서비스를 통합하여 다양한 단편화된 기업 커뮤니케이션과 협업을 통합할 수 있습니다. 몇 가지 중요한 개념:
Workspace: 꽤 작업 공간이므로 사용자는 다양한 작업 공간에 참여하거나 만들 수 있습니다. 작업 공간의 이름과 URL은 회사 이름이 됩니다.
Channel: 채널은 서로 다른 팀이나 주제로 나눌 수 있으며, 채널 내 구성원이 채널에서 정보를 공유하는 WeChat과 동일하게 이해될 수도 있습니다.
3. 사전 준비
slack 구성
계정을 만들고 로그인하세요. 앱을 사용하거나 브라우저로 웹 버전에 로그인할 수 있습니다.
나만의 워크스페이스를 만들고, 초대도 가능합니다. 다른 사람들이 작업 공간에 참여하도록 합니다.
채널을 만들고 동료를 초대하여 채널에 메시지를 보낼 수 있으며, 채널에 참여하는 모든 사람이 메시지를 볼 수 있습니다.
작업 공간에 애플리케이션 추가 Incoming WebHook을 선택하세요. 채널을 등록하고 Webhook URL을 저장한 후 팔로우하세요. 프로그램은 Webhook을 통해 구현되어 채널에 메시지를 보냅니다.
pom.
Urlencode를 통해 웹훅에 대한 요청을 시작하세요.<dependencies>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
<dependency>
<groupId>commons-configuration</groupId>
<artifactId>commons-configuration</artifactId>
<version>1.10</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
</dependencies>
SlackUtil testpackage com.yy.operation;
import com.yy.common.CommonThreadFactory;
import com.yy.common.ConnUtil;
import org.apache.commons.lang.StringUtils;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.concurrent.*;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* @author :Max
* @date :Created in 2022/8/26 下午12:54
* @description:
*/
public class SlackUtil {
private static final Logger logger = Logger.getLogger(SlackUtil.class.getCanonicalName());
private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private static final String SEND_USER_NAME ="运维机器人";
private static int MAX_RETRY =3;
/**
* 线程池 抛弃策略DiscardPolicy:这种策略,会默默的把新来的这个任务给丢弃;不会得到通知
*/
private static ExecutorService executor = new ThreadPoolExecutor(10,30,60,TimeUnit.MILLISECONDS,new ArrayBlockingQueue<Runnable>(200),new CommonThreadFactory("Slack"), new ThreadPoolExecutor.DiscardPolicy());
private static String MSG_FORMAT ="payload='{'"channel": "{0}", "username": "{1}", "text": "{2}", "icon_emoji": ":ghost:"'}'" ;
/**
* 保存的Webhook URL ,需要初始化
*/
private static String WEBHOOK_URL ;
private static boolean SLACK_ABLE;
public static void setSlackConfig(String webhookUrl){
WEBHOOK_URL = webhookUrl;
SLACK_ABLE = true;
}
/**
* slack异步发消息,保证不能影响到主功能
* @param channel
* @param msg
*/
public static void send(final String channel, final String msg){
if(!SLACK_ABLE){
return;
}
if(StringUtils.isBlank(msg)){
return;
}
executor.submit(new Runnable() {
@Override
public void run() {
try {
SlackUtil.send(channel,sdf.format(System.currentTimeMillis())+" "+msg,MAX_RETRY);
} catch (Exception e) {
logger.log(Level.SEVERE, e.getMessage(), e);
}
}
});
}
/**
* 如果slask发消息失败,会最多尝试发三次,三次都失败,会打印异常信息
* @param channel
* @param msg
* @param retry
* @throws Exception
*/
public static void send(String channel, String msg, int retry) throws Exception {
if(msg.indexOf(""")>=0 ||msg.indexOf("{")>=0 ||msg.indexOf("}")>=0){
msg =msg.replace(""","'").replace("{","[").replace("}","]");
}
String payload = MessageFormat.format(MSG_FORMAT, channel,SEND_USER_NAME,msg);
String result = ConnUtil.getContentByPostWithUrlencode(WEBHOOK_URL,payload);
logger.info("result:"+result);
if(StringUtils.isEmpty(result) ||!result.startsWith("ok")){
--retry;
if(retry>0){
try {
TimeUnit.SECONDS.sleep(retry*5);
} catch (InterruptedException e) {
e.printStackTrace();
}
send(channel,msg,retry);
}else{
throw new Exception("Fail to send slack:"+result+"\nmsg:"+msg);
}
}
}
}
성공적으로 전송되면 채널에서 정보를 볼 수 있습니다.
2 . 인쇄 로그 클래스 재작성
공통 예외 로깅 처리
package com.yy.common; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.HttpClientBuilder; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.util.logging.Level; import java.util.logging.Logger; /** * @author :Max * @date :Created in 2022/8/26 下午1:44 * @description: */ public class ConnUtil { private static final Logger logger = Logger.getLogger(ConnUtil.class.getCanonicalName()); public static String getContentByPostWithUrlencode(String url,String msg){ StringEntity entity = new StringEntity(msg, "UTF-8"); entity.setContentEncoding("UTF-8"); entity.setContentType(" application/x-www-form-urlencoded"); HttpClient httpClient = HttpClientBuilder.create().build(); HttpPost request = new HttpPost(url); request.setEntity(entity); HttpResponse response = null; try { response = httpClient.execute(request); HttpEntity responseEntity = response.getEntity(); if (responseEntity != null) { InputStream instream = responseEntity.getContent(); BufferedReader reader = new BufferedReader(new InputStreamReader(instream)); StringBuffer contents = new StringBuffer(); String line = null; while ((line = reader.readLine()) != null) { contents.append(line); contents.append("\n"); } return contents.toString(); } } catch (Exception ex) { logger.log(Level.SEVERE, ex.getMessage(), ex); } return null; } }
인쇄 로그 캡슐화 방법 재작성
package com.yy.test; import com.yy.common.SlackChannelEnum; import com.yy.operation.SlackUtil; import org.junit.Assert; import org.junit.Test; import java.util.concurrent.TimeUnit; /** * @author :Max * @date :Created in 2022/8/28 下午2:37 * @description: */ public class SlackTest { static { SlackUtil.setSlackConfig("https://hooks.slack.com/services/*******"); } @Test public void test(){ SlackUtil.send(SlackChannelEnum.EXCEPTION.channel,"test ~"); try { TimeUnit.MINUTES.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } Assert.assertTrue(true); } }
public class LoggerTest { private static final Logger logger = Logger.getLogger(LoggerTest.class.getCanonicalName()); @Test public void test() { try { int i = 1 / 0; } catch (Exception e) { logger.log(Level.SEVERE, e.getMessage(), e); } } }테스트 로그 클래스로그 클래스가 정의되면 호출되는 코드는 변경할 필요가 없습니다. 예외 알람 기능이 저렴한 비용으로 통합되었습니다
package com.yy.operation;
import com.yy.common.SlackChannelEnum;
import org.apache.commons.lang.StringUtils;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.text.MessageFormat;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
/**
* @author Max
* @date :Created in 2022/8/4 下午5:14
* @description:
*/
public class CommonLogger {
private Logger logger;
private CommonLogger(String className) {
logger = Logger.getLogger(className);
}
private static String SERVER;
private static String EXCEPTION_ALARM_FORMAT = "EXCEPTION 发生异常!\n环境 :{0}\n信息 :{1}\n详情 :{2}";
private static String WARNING_ALARM_FORMAT = "WARNING 发生告警!\n环境 :{0}\n信息 :{1}";
private static String SEVERE_ALARM_FORMAT = "SEVERE 发生告警!\n环境 :{0}\n信息 :{1}";
private static String LOG_ALARM_FORMAT = "LOG 发生告警!\n环境 :{0}\n信息 :{1}";
private static String USER_BEHAVIOR_FORMAT = "CUSTOMER \n环境 :{0}\n信息 :{1}";
static {
try{
InetAddress ip4 = Inet4Address.getLocalHost();
SERVER = ip4.getHostAddress();
}catch (Exception e){
SERVER ="undefined server";
}
}
public static CommonLogger getLogger(String name) {
return new CommonLogger(name);
}
/**
* Print exception information, send slack
*
* @param level
* @param msg
* @param e
*/
public void log(Level level, String msg, Throwable e) {
if(StringUtils.isBlank(msg)){
return;
}
msg =dolog(level,msg, e);
msg = MessageFormat.format(EXCEPTION_ALARM_FORMAT, SERVER, formatMsg(msg), getErrmessage(e));
SlackUtil.send(SlackChannelEnum.EXCEPTION.channel, msg);
}
/**
* Print user behavior information, send slack
*
* @param msg
*/
public void userBehaviorInfo(String msg) {
if(StringUtils.isBlank(msg)){
return;
}
msg =dolog(Level.INFO,msg);
msg = MessageFormat.format(USER_BEHAVIOR_FORMAT, SERVER, formatMsg(msg));
SlackUtil.send(SlackChannelEnum.EXCEPTION.channel, msg);
}
public String formatMsg(String msg){
StringBuilder source =new StringBuilder(logger.getName());
msg=transferMsgSource(source,msg);
return source.toString()+" "+msg;
}
/**
* Print warning severe information, send slack
*
* @param msg
*/
public void severe(String msg) {
if(StringUtils.isBlank(msg)){
return;
}
msg = dolog(Level.SEVERE,msg);
msg = MessageFormat.format(SEVERE_ALARM_FORMAT, SERVER, formatMsg(msg));
SlackUtil.send(SlackChannelEnum.EXCEPTION.channel, msg);
}
/**
* Print warning severe information, send slack
*
* @param msg
*/
public void warning(String msg) {
if(StringUtils.isBlank(msg)){
return;
}
msg = dolog(Level.WARNING,msg);
msg = MessageFormat.format(WARNING_ALARM_FORMAT, SERVER, formatMsg(msg));
SlackUtil.send(SlackChannelEnum.EXCEPTION.channel, msg);
}
/**
* Print warning log information, send slack
*
* @param msg
*/
public void log(Level severe, String msg) {
if(StringUtils.isBlank(msg)){
return;
}
msg =dolog(severe,msg);
msg = MessageFormat.format(LOG_ALARM_FORMAT, SERVER, formatMsg(msg));
SlackUtil.send(SlackChannelEnum.EXCEPTION.channel, msg);
}
public static String getErrmessage(Throwable t) {
return getThrowable(t);
}
public void info(String msg) {
dolog(Level.INFO,msg);
}
public void fine(String msg) {
logger.fine(msg);
}
public void setLevel(Level level) {
logger.setLevel(level);
}
public String dolog(Level level, String msg) {
return dolog(level,msg,null);
}
/**
*
* @param level
* @param msg
* @param thrown
* @return msg="["+currentThread.getName()+"] "+a.getMethodName()+" "+msg;
*/
public String dolog(Level level, String msg, Throwable thrown) {
LogRecord lr = new LogRecord(level, msg);
lr.setLevel(level);
if(thrown!=null){
lr.setThrown(thrown);
}
Thread currentThread = Thread.currentThread();
StackTraceElement[] temp=currentThread.getStackTrace();
StackTraceElement a=(StackTraceElement)temp[3];
lr.setThreadID((int) currentThread.getId());
lr.setSourceClassName(logger.getName());
lr.setSourceMethodName(a.getMethodName());
lr.setLoggerName(logger.getName());
logger.log(lr);
return "["+currentThread.getName()+"] "+a.getMethodName()+" "+msg;
}
public static String getThrowable(Throwable e) {
String throwable = "";
if (e != null) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
pw.println();
e.printStackTrace(pw);
pw.close();
throwable = sw.toString();
}
return throwable;
}
public static String transferMsgSource(StringBuilder source,String msg){
if(msg.indexOf(" ")>0){
String threadName = msg.substring(0,msg.indexOf(" "))+ " ";
msg=msg.substring(threadName.length());
source.insert(0,threadName);
if(msg.indexOf(" ")>0) {
String method = msg.substring(0, msg.indexOf(" "));
source.append( "." + method);
msg = msg.substring(method.length()+1);
}
}
return msg;
}
}
테스트 결과, 비정상적인 정보가 채널에 인쇄되어 개발 및 운영 담당자가 쉽게 찾을 수 있습니다5. 최적화 및 확장 아이디어
인쇄만 가능하지 않습니다 예외 로그를 인쇄할 뿐만 아니라 재충전 등과 같은 사용자의 일부 주요 동작도 인쇄합니다. 여러 채널을 설정하여 다양한 테마의 메시지를 보낼 수 있습니다.
- 개발자가 시간 내에 Slack을 확인할 수 없는 경우 , 이메일을 통합할 수도 있습니다. 메일클락(mailclark) 애플리케이션을 Slack에 추가할 수 있습니다(별도 요금). 구성 후 채널의 정보를 활성화할 수 있으며 수신자는 Slack 계정을 만들 필요가 없습니다. . 구체적인 구성은 링크를 참고해주세요.
- 기타 코드
package com.yy.operation; import java.text.MessageFormat; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; import java.util.logging.Logger; public class LoggerUtil { private static Logger curLogger = Logger.getLogger(LoggerUtil.class.getCanonicalName()); private static ConcurrentHashMap<String, CommonLogger> loggers = new ConcurrentHashMap<String, CommonLogger>(); public static CommonLogger getLogger(Class<?> clazz) { String className = clazz.getCanonicalName(); CommonLogger logger = loggers.get(className); if (logger == null) { logger = CommonLogger.getLogger(className); curLogger.fine(MessageFormat.format("Register logger for {0}", className)); loggers.put(className, logger); } return logger; } }
public class LoggerTest { private static final Logger logger = Logger.getLogger(LoggerTest.class.getCanonicalName()); @Test public void test() { try { int i = 1 / 0; } catch (Exception e) { logger.log(Level.SEVERE, e.getMessage(), e); } } }
위 내용은 Slack을 기반으로 JAVA에서 이상 로그 알람을 구현하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

이 기사에서는 Java 프로젝트 관리, 구축 자동화 및 종속성 해상도에 Maven 및 Gradle을 사용하여 접근 방식과 최적화 전략을 비교합니다.

이 기사에서는 Maven 및 Gradle과 같은 도구를 사용하여 적절한 버전 및 종속성 관리로 사용자 정의 Java 라이브러리 (JAR Files)를 작성하고 사용하는 것에 대해 설명합니다.

이 기사는 카페인 및 구아바 캐시를 사용하여 자바에서 다단계 캐싱을 구현하여 응용 프로그램 성능을 향상시키는 것에 대해 설명합니다. 구성 및 퇴거 정책 관리 Best Pra와 함께 설정, 통합 및 성능 이점을 다룹니다.

이 기사는 캐싱 및 게으른 하중과 같은 고급 기능을 사용하여 객체 관계 매핑에 JPA를 사용하는 것에 대해 설명합니다. 잠재적 인 함정을 강조하면서 성능을 최적화하기위한 설정, 엔티티 매핑 및 모범 사례를 다룹니다. [159 문자]

Java의 클래스 로딩에는 부트 스트랩, 확장 및 응용 프로그램 클래스 로더가있는 계층 적 시스템을 사용하여 클래스로드, 링크 및 초기화 클래스가 포함됩니다. 학부모 위임 모델은 핵심 클래스가 먼저로드되어 사용자 정의 클래스 LOA에 영향을 미치도록합니다.


핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

안전한 시험 브라우저
안전한 시험 브라우저는 온라인 시험을 안전하게 치르기 위한 보안 브라우저 환경입니다. 이 소프트웨어는 모든 컴퓨터를 안전한 워크스테이션으로 바꿔줍니다. 이는 모든 유틸리티에 대한 액세스를 제어하고 학생들이 승인되지 않은 리소스를 사용하는 것을 방지합니다.

맨티스BT
Mantis는 제품 결함 추적을 돕기 위해 설계된 배포하기 쉬운 웹 기반 결함 추적 도구입니다. PHP, MySQL 및 웹 서버가 필요합니다. 데모 및 호스팅 서비스를 확인해 보세요.

Eclipse용 SAP NetWeaver 서버 어댑터
Eclipse를 SAP NetWeaver 애플리케이션 서버와 통합합니다.

SublimeText3 영어 버전
권장 사항: Win 버전, 코드 프롬프트 지원!

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)
