简体   繁体   中英

How to send message over websocket in log4j2 plugin?

The custom log4j plugin is initialized before the websocket configuration which makes it impossible to autowire spring boot's SimpMessagingTemplate. I have tried to get the class from Application context as well which did not work out. How do I approach this?

Custom plugin class:

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

The below code does not seem to work. How do I approach this?

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

If you are using Spring Boot, it initializes logging multiple times. Only the very first will not have access to Spring properties. If you can provide a different configuration file that logs those events to a different destination you could then let Log4j retrieve the values for you using the Spring Lookup.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM