Study/Java

에러 로그를 웹에서 json으로 호출해서 확인하기 (logback appender 만들기)

Bluesky_ 2019. 1. 22. 06:58
반응형

서버 개발자가 로그를 보는건 그냥 서버들어가서 확인하면 된다.

하지만 프론트 개발자와 협업을 하는 경우 서버 로그 확인 요청을 받는 경우가 종종 있다.

이런 경우 웹에서 바로 로그를 확인하면 좋을 것 같아 만들어보았다.

Logback의 appender를 사용한 방법이다.

logback은 appender로 로그를 처리하는 방식을 관리한다.

여러가지 방식의 appender를 logback이 제공해주지만 기본 제공해주는 appender 중엔 웹 요청으로 응답을 처리하는 appender는 없다.

custom appender를 하나 만들어준다.

public class BlueskyLogbackAppender<E> extends UnsynchronizedAppenderBase<E> { 	 	private BlueskyLogbackAppenderService<E> blueskyLogbackAppenderService; 	 	@Setter 	private Encoder<E> encoder; 	 	public BlueskyLogbackAppender(BlueskyLogbackAppenderService<E> blueskyLogbackAppenderService) { 		this.blueskyLogbackAppenderService = blueskyLogbackAppenderService; 	}  	@Override 	protected void append(E eventObject) { 		if (!isStarted()) { 			return; 		} 		blueskyLogbackAppenderService.addLog(eventObject, new String(encoder.encode(eventObject))); 	}  }

해당 appender는 append 실행 시 지정된 service의 메소드를 수행한다.

해당 서비스를 구현한다.

public class BlueskyLogbackAppenderService<E> { 	 	private static final int queueSize = 500;  	@Getter 	private Queue<LogObject<E>> logQueue = new LinkedBlockingQueue<>(queueSize); 	 	public void addLog(E eventObject, String logMessage) { 		if (logQueue.size() >= queueSize) { 			logQueue.remove(); 		} 		logQueue.offer(new LogObject<E>(eventObject, logMessage)); 	} 	 	@Data 	@AllArgsConstructor 	public static class LogObject<E> { 		E eventObject; 		String logMessage; 	} } 

해당 서비스는 로컬 queue에 로그 내용을 담는 기능을 제공하고 500개가 초과하면 가장 오래된 로그를 비우고 추가하는 식으로 동작한다.

이제 기존 logback 설정에 위 custom appender를 추가한다.

@Configuration public class BlueskyLogbackConfig implements InitializingBean { 	 	@Bean 	public BlueskyLogbackAppenderService<ILoggingEvent> blueskyLogbackAppenderService() { 		return new BlueskyLogbackAppenderService<ILoggingEvent>(); 	}  	@Override 	public void afterPropertiesSet() throws Exception { 		LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();  		BlueskyLogbackAppender<ILoggingEvent> blueskyLogbackAppender = new BlueskyLogbackAppender<>(blueskyLogbackAppenderService());  		blueskyLogbackAppender.setContext(loggerContext); 		blueskyLogbackAppender.setName("blueskyLogbackAppender"); 		RollingFileAppender<ILoggingEvent> appender = (RollingFileAppender<ILoggingEvent>) loggerContext.getLogger("ROOT").getAppender("FILE"); 		blueskyLogbackAppender.setEncoder(appender == null ? new PatternLayoutEncoder() : appender.getEncoder()); 		 		blueskyLogbackAppender.start(); 		loggerContext.getLogger("ROOT").addAppender(blueskyLogbackAppender); 		 	}  	 }

위의 경우 logback.xml에 FILE이란 이름의 appender가 있는 경우 해당 appender의 encoder를 사용하는 설정이다.

파일로 남기는 로그의 로그 패턴을 그대로 사용하기 위해 가져왔다.

이제 log 가 발생할 때마다 blueskyLogbackAppenderService에 queue가 쌓이게 된다.

쌓아놓은 queue를 확인하는 호출 주소를 추가한다.

@RestController public class BlueskyLogbackDevCheckController {  	@Autowired 	private BlueskyLogbackAppenderService<ILoggingEvent> blueskyLogbackAppenderService; 	 	@GetMapping(value = "/logView", produces = MediaType.APPLICATION_JSON_VALUE) 	public List<String> logview() { 		return blueskyLogbackAppenderService.getLogQueue().stream().map(queue -> queue.getLogMessage().replaceAll(CoreConstants.LINE_SEPARATOR, "").replaceAll("\t", "")).collect(Collectors.toList()); 	}  } 

json으로 응답하는 것으로 설명을 했지만 appender는 이벤트 기반이기 때문에 특정 로그가 발생하면 메일로 알려준다거나 하는 식의 모니터링을 만들어 사용하는 방법이 실제론 더 효율적인 사용이 되지 않을까 싶다.

반응형