【问题标题】:How to send message over websocket in log4j2 plugin?如何在 log4j2 插件中通过 websocket 发送消息?
【发布时间】:2023-03-29 20:23:02
【问题描述】:

自定义 log4j 插件在 websocket 配置之前初始化,这使得无法自动装配 spring boot 的 SimpMessagingTemplate。我也尝试从应用程序上下文中获取类,但没有成功。我该如何处理?

自定义插件类:

@SuppressWarnings("deprecation")
@Plugin(category = "Core", name = "AmtAppender", elementType = "appender")
public class AmtAppender extends AbstractAppender implements ApplicationContextAware{
    private final Logger logger = LogManager.getLogger(this.getClass().getName());
    private final ReadWriteLock lock = new ReentrantReadWriteLock();
    private final Lock readLock = lock.readLock();
    private static MongoTemplate mongotemplate;
    private static MongoDbFactory mongodbfactory;
    private String alertcollection=null;
    private AMTBaseProcessor amtBaseProcessor=null;
    private final String DEFAULT_APP_CONFIG_LOCATION = "/application.properties";
    LogQueueDataDTO logdata=new LogQueueDataDTO();
    DateTimeFormatter dateformat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneId.systemDefault());
    private ApplicationContext applicationContext;
    
    protected AmtAppender(final String name, final Filter filter, final Layout<? extends Serializable> layout,
                final boolean ignoreExceptions) {
            super(name,filter,layout,ignoreExceptions);
      }
    
    
    @PluginFactory
    public static AmtAppender createAppender(
      @PluginAttribute("name") String name, 
      @PluginElement("Filter") Filter filter,
      @PluginElement("Layout") Layout<? extends Serializable> layout,
      @PluginAttribute("ignoreExceptions") boolean ignoreExceptions    
      ) {
        return new AmtAppender(name, filter,layout,ignoreExceptions);
    }
    
    private Properties getApplicationProperties() {
         Properties prop = new Properties();
            try {               
                 Resource resource;             
                 resource = new ClassPathResource(DEFAULT_APP_CONFIG_LOCATION);                              
                 prop = PropertiesLoaderUtils.loadProperties(resource);
                 return prop;
            }
            catch (Exception e) {
                 logger.info("IOException in getApplicationProperties() ::"+e);
            }
            return null;
    }
    
    void setMongoTemplate(){         
            Properties prop = getApplicationProperties();
           mongodbfactory=new SimpleMongoDbFactory(new MongoClientURI(prop.getProperty("spring.data.mongodb.uri.alarm")));
            mongotemplate = new MongoTemplate(mongodbfactory);  
        }
     
    private String getAlertCollection() {
         try {
         Properties prop =getApplicationProperties();       
         alertcollection=prop.getProperty("appender.alertCollection");
         if(alertcollection==null)
         logger.info("Alert collection in application properties file is null");
         }
         catch(Exception e) {
             logger.info("Exception :: {}", e);
         }
         return alertcollection;         
     }
    
    @Override   
    public void append(LogEvent event) {
        this.readLock.lock();
        
        if(applicationContext==null) {
            getContext();
        }
        
        try{            
            String datetime=dateformat.format(new Date().toInstant()).toString();
            logdata.setMessage(event.getLevel().name()+" "+datetime+" "+event.getThreadName()+" "+event.getSource().getFileName()+" "+event.getSource().getMethodName()+" :: "+event.getSource().getLineNumber()+" "+event.getMessage().getFormat());
            if(event.getLevel().name().equals("ERROR") ||event.getLevel().name().equals("FATAL") ||event.getLevel().name().equals("WARN")){     
                LogDataProcessorDTO logDataProcessorDTO=amtBaseProcessor.getLogDataProcessorDTO(logdata, true, false);
                mongotemplate.save(logDataProcessorDTO.getProcessedLogData(),alertcollection);  
                getContext().getBean(SimpMessagingTemplate.class).convertAndSend("/websocket/data", logDataProcessorDTO);
            }
            
            }
        catch(Exception e){
            logger.info("Exception in append() ::"+e);  
        }
        finally{
            this.readLock.unlock();
        }
        
    }


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    } 

    public ApplicationContext getContext() {
        return applicationContext;
    }
}

下面的代码似乎不起作用。我该如何处理?

getContext().getBean(SimpMessagingTemplate.class).convertAndSend("/websocket/data", logDataProcessorDTO);

【问题讨论】:

    标签: java spring spring-boot plugins websocket


    【解决方案1】:

    如果您使用的是 Spring Boot,它会多次初始化日志记录。只有第一个将无法访问 Spring 属性。如果您可以提供不同的配置文件将这些事件记录到不同的目的地,那么您可以让 Log4j 使用 Spring Lookup 为您检索值。

    【讨论】:

    • 提供不同的配置文件是什么意思?请详细说明。
    • 第一次初始化日志是在 Spring 启动之前,所以使用“普通”的 log4j 方法(即 log4j2.xml)配置日志。使用 logging.config 属性指定 Spring 应该在 bootstrap.yml 中使用的第二个日志记录配置。
    猜你喜欢
    • 1970-01-01
    • 2023-03-15
    • 1970-01-01
    • 2021-07-29
    • 2019-12-23
    • 1970-01-01
    • 2014-07-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多