Rumah  >  Artikel  >  Java  >  Bagaimana untuk melaksanakan penggera log tidak normal dalam JAVA berdasarkan Slack

Bagaimana untuk melaksanakan penggera log tidak normal dalam JAVA berdasarkan Slack

王林
王林ke hadapan
2023-05-01 18:04:071421semak imbas

    1. Pengenalan Fungsi

    Logik pelaksanaan: Dalam keadaan biasa, pengecualian akan diproses dalam kod , perkara yang paling asas adalah untuk mencetak log Artikel ini akan menyedari bahawa apabila mencetak log, maklumat pengecualian akan dihantar ke saluran Slack pada masa yang sama Kakitangan pembangunan atau operasi dan penyelenggaraan boleh membuat akaun Slack dan menyertai saluran untuk menerima makluman maklumat yang tidak normal masa sebenar.

    2. Pengenalan kepada Slack

    Slack ialah alat komunikasi masa nyata berasaskan web yang boleh digunakan sebagai satu aplikasi pada komputer desktop/laptop, peranti mudah alih dan sebagai aplikasi web . Pada asasnya, ini ialah bilik sembang dan kerjasama peribadi anda. Bagi kebanyakan syarikat, ia telah menggantikan e-mel/forum peribadi/bilik sembang sebagai saluran komunikasi berasaskan teks dalaman utama.

    Ia boleh difahami sebagai kumpulan sembang + penyepaduan alat berskala besar + penyepaduan fail + carian bersatu . Sehingga penghujung 2014, Slack telah menyepadukan 65 alat dan perkhidmatan seperti e-mel, mesej teks, Google Drive, Twitter, Trello, Asana, GitHub, dll., yang boleh menghimpunkan pelbagai komunikasi dan kerjasama perusahaan yang berpecah-belah. Beberapa konsep penting:

    Ruang kerja: Cukup ruang kerja Pengguna boleh menyertai atau mencipta ruang kerja yang berbeza Banyak kali, nama dan URL ruang kerja akan menjadi nama syarikat.

    Saluran: Saluran boleh dibahagikan kepada pasukan atau topik yang berbeza, dan juga boleh difahami sebagai setara dengan WeChat, di mana ahli dalam saluran berkongsi maklumat dalam saluran.

    3. Persediaan awal

    konfigurasi kendur

    • Buat akaun dan log masuk. Anda boleh menggunakan apl atau log masuk ke versi web dengan pelayar

    • Buat ruang kerja anda sendiri dan jemput orang lain untuk menyertainya.

    • Buat saluran dan jemput rakan sekerja untuk menyertai pada masa ini, anda boleh menghantar mesej ke saluran dan semua orang yang menyertai saluran itu boleh melihat mesej itu

    • <.>
    Kerja Tambahkan aplikasi

    WebHook Masuk ke kawasan, pilih saluran dan simpan URL Webhook Kemudian, anda akan menggunakan program pelaksanaan Webhook untuk menghantar mesej ke saluran.

    Bagaimana untuk melaksanakan penggera log tidak normal dalam JAVA berdasarkan Slack

    Bagaimana untuk melaksanakan penggera log tidak normal dalam JAVA berdasarkan Slack

    Bagaimana untuk melaksanakan penggera log tidak normal dalam JAVA berdasarkan Slack

    Bagaimana untuk melaksanakan penggera log tidak normal dalam JAVA berdasarkan Slack

    pom.xml

    <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>

    4. Pelaksanaan khusus

    1. Laksanakan Slack untuk menghantar mesej

    SlackUtil Hantar mesej ke kelas alat Slack
    package 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=&#39;{&#39;"channel": "{0}", "username": "{1}", "text": "{2}", "icon_emoji": ":ghost:"&#39;}&#39;" ;
        /**
         * 保存的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(""","&#39;").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);
                }
            }
        }
    }
    Mulakan permintaan untuk membuat webhook melalui Urlencode
    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;
        }
    }
    Ujian SlackUtil
    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);
        }
    }
    Berjaya dihantar, anda boleh melihat maklumat dalam saluran

    Bagaimana untuk melaksanakan penggera log tidak normal dalam JAVA berdasarkan Slack

    2. Tulis semula kelas log cetakan

    Pengecualian biasa Pemprosesan pembalakan
    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);
            }
        }
    }
    Tulis semula kaedah merangkum pencetakan log
    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;
        }
    }
    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;
       }
    }
    Uji kelas log
    Apabila kelas log ditakrifkan, kod yang dipanggil tidak perlu ditukar, supaya ia lebih kecil Pada kos, fungsi penggera abnormal disepadukan

    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);
            }
        }
    }

    Keputusan ujian, maklumat abnormal tercetak muncul dalam saluran, yang mudah untuk kakitangan pembangunan dan operasi untuk mengesan

    Bagaimana untuk melaksanakan penggera log tidak normal dalam JAVA berdasarkan Slack

    5. Idea Pengoptimuman dan pengembangan

    • Anda bukan sahaja boleh mencetak log pengecualian, tetapi juga mencetak beberapa gelagat utama pengguna, seperti mengecas semula, dsb. Berbilang saluran boleh disediakan untuk menghantar mesej dengan tema yang berbeza

    • Kolam benang boleh dioptimumkan

    • Jika pembangun tidak dapat menyemak kelonggaran dalam masa, e-mel juga boleh disepadukan aplikasi Mailclark boleh ditambah ke Slack (yuran berasingan), selepas konfigurasi Selepas itu, maklumat dalam saluran yang dilancarkan boleh dihantar secara automatik ke mana-mana peti mel, dan penerima tidak perlu membuat akaun yang slack. . Sila rujuk pautan untuk konfigurasi tertentu.

    Kod lain

    package com.yy.common;
    import java.util.concurrent.ThreadFactory;
    import java.util.concurrent.atomic.AtomicInteger;
    /**
     * @author :Max
     * @date :Created in 2022/8/26 下午1:51
     * @description:
     */
    public class CommonThreadFactory implements ThreadFactory {
        private static final AtomicInteger poolNumber = new AtomicInteger(1);
        private final ThreadGroup group;
        private final AtomicInteger threadNumber = new AtomicInteger(1);
        private final String threadNamePrefix;
        private final String nameSpecific;
        private final boolean isDaemon;
        public CommonThreadFactory(String nameSpecific) {
            this(nameSpecifihttps://juejin.cn/post/7136858841756467230#heading-4c, false);
        }
        public CommonThreadFactory(String nameSpecific, boolean isDaemon) {
            SecurityManager s = System.getSecurityManager();
            this.group = (s != null) ? s.getThreadGroup() :
                    Thread.currentThread().getThreadGroup();
            this.threadNamePrefix = "eg-pool-" + poolNumber.getAndIncrement() + "-thread";
            this.nameSpecific = nameSpecific;
            this.isDaemon = isDaemon;
        }
        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(group, r, String.format("%s-%d-%s",
                    this.threadNamePrefix, threadNumber.getAndIncrement(), this.nameSpecific), 0);
            t.setDaemon(isDaemon);
            t.setPriority(Thread.NORM_PRIORITY);
            return t;
        }
    }
    public enum SlackChannelEnum {
        EXCEPTION("#test-example");
        public String channel;
        SlackChannelEnum(String channel) {
            this.channel = channel;
        }
    }

    Atas ialah kandungan terperinci Bagaimana untuk melaksanakan penggera log tidak normal dalam JAVA berdasarkan Slack. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

    Kenyataan:
    Artikel ini dikembalikan pada:yisu.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam