Design Log Monitor System Prototype — 2. Spring Boot
Continue with Design Log Monitor System Prototype For Spring MVC
1. Practice
1-1. 1. Log format
You can define yours own team log format.
Name | Remark |
---|---|
requestID | uuid |
timestamp | log record time |
level | log level |
message | log message |
app | application name |
module | module name |
operation label | custom annotation label or request uri |
accountId | account id |
accountType | account type |
status | response status code |
elapsed | the number of milliseconds elapsed for the execution of logging event |
error | full error message |
thread id | |
Class name | |
package.class | Used to output the category of the logging event |
line number | Used to output the line number from where the logging request was issued |
This is the log pattern layout example in logback.xml:
1 |
[app] [%-5p] [%d{yyyy-MM-dd HH:mm:ss,SSS}] [-%-4r] [%t] [%X{MDC.RequestID}] [%X{MDC.AccountId}:%X{MDC.AccountType}] [%X{MDC.Elapsed}] [%logger{128}-%M:%L] - %m%n |
1-2. 2. Generate RequestID
You can use UUID as RequestID as will. I am using snowflake ID in my project.
Add a filter to add RequestID in the header and transmit it in the request.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
/* * Copyright (c) 2016-2018 Mobabel.net * * All rights reserved. */ package net.mobabel.nova.service.monitoring; import static net.mobabel.nova.service.monitoring.Constants.MDC_CLIENT_IP_KEY; import static net.mobabel.nova.service.monitoring.Constants.MDC_UUID_REQUEST_ID_KEY; import static net.mobabel.nova.service.monitoring.Constants.REQUEST_ID_HEADER; import static net.mobabel.nova.core.util.Inet4Address.getRemortIP; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import net.mobabel.nova.core.util.UuidUtil; import org.apache.commons.lang3.StringUtils; import org.slf4j.MDC; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; @Component public class LogMDCFilter extends OncePerRequestFilter { @Override protected void doFilterInternal( final HttpServletRequest request, final HttpServletResponse response, final FilterChain chain ) throws java.io.IOException, ServletException { try { final String token = extractToken( request ); final String clientIP = getRemortIP( request ); MDC.put( MDC_UUID_REQUEST_ID_KEY, token ); MDC.put( MDC_CLIENT_IP_KEY, clientIP ); if (!StringUtils.isEmpty( REQUEST_ID_HEADER )) { response.addHeader( REQUEST_ID_HEADER, token ); } chain.doFilter( request, response ); } finally { MDC.remove( MDC_UUID_REQUEST_ID_KEY ); MDC.remove( MDC_CLIENT_IP_KEY ); } } private String extractToken( final HttpServletRequest request ) { final String token; if (!StringUtils.isEmpty( REQUEST_ID_HEADER ) && !StringUtils.isEmpty( request.getHeader( REQUEST_ID_HEADER ) )) { token = request.getHeader( REQUEST_ID_HEADER ); } else { token = UuidUtil.getId() + ""; } return token; } @Override protected boolean isAsyncDispatch( final HttpServletRequest request ) { return false; } @Override protected boolean shouldNotFilterErrorDispatch() { return false; } } |
in MvcWebConfig
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
@Configuration @EnableWebMvc public class MvcWebConfig implements WebMvcConfigurer { @Bean public FilterRegistrationBean LogMDCFilterRegistrationBean() { FilterRegistrationBean registrationBean = new FilterRegistrationBean(); LogMDCFilter logMDCFilter = new LogMDCFilter(); registrationBean.setFilter(logMDCFilter); registrationBean.setOrder(2); return registrationBean; } |
In logback.xml pattern layout:
1 |
[%X{MDC.RequestID}] |
3. MDC
what is MDC: Mapped Diagnostic Context ?
1-3. 3. AOP or Interceptor Implementation
In your application.yml define some value for AOP.
1 2 3 4 5 6 7 |
monitor: operation_logging: log_requests: true included_packages: controller: net.mobabel.nova.manager.controller service: net.mobabel.nova.service.domain repository: net.mobabel.nova.repository |
1-3-1. 3.1 AOP for Repository
Show me the code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
/* * Copyright (c) 2016-2018 Mobabel.net * * All rights reserved. */ package net.mobabel.nova.service.monitoring.aspect; import static net.mobabel.nova.service.monitoring.Constants.MDC_ACCOUNT_ID; import static net.mobabel.nova.service.monitoring.Constants.MDC_ACCOUNT_TYPE; import static net.mobabel.nova.service.monitoring.Constants.MDC_EXECUTION_LASTED; import static net.mobabel.nova.service.monitoring.Constants.MDC_OPERATION_LABEL; import static net.mobabel.nova.service.monitoring.MonitorUtils.extractBasicAccount; import static net.mobabel.nova.service.monitoring.MonitorUtils.extractMethodFullName; import static net.mobabel.nova.service.monitoring.MonitorUtils.extractMethodName; import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.util.List; import javax.servlet.http.HttpServletRequest; import net.mobabel.nova.core.util.Logger; import net.mobabel.nova.model.authc.BasicAccount; import net.mobabel.nova.service.monitoring.MonitorUtils; import net.mobabel.nova.service.monitoring.NotLogOperation; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.slf4j.MDC; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; @Aspect @Component public class RepositoryAspect { protected Logger logger = Logger.getLogger( this.getClass() ); @Value( "${monitor.operation_logging.log_requests:false}" ) private boolean opsLogRequestsEnable; @Value( "#{'${monitor.operation_logging.included_packages.repository}'.split(',')}" ) private List<String> opsIncludedPackages; @Pointcut( "@annotation(net.mobabel.nova.service.monitoring.LogOperation)" ) public void logPointCut() { } @Pointcut( "execution(public * net.mobabel.nova.repository..*.add*(..))" + " || execution(public * net.mobabel.nova.repository..*.save*(..))" + " || execution(public * net.mobabel.nova.repository..*.edit*(..))" + " || execution(public * net.mobabel.nova.repository..*.update*(..))" + " || execution(public * net.mobabel.nova.repository..*.delete*(..))" + " || execution(public * net.mobabel.nova.repository..*.remove*(..))" + " || execution(public * net.mobabel.nova.repository..*.list*(..))" + " || execution(public * net.mobabel.nova.repository..*.get*(..))" + " || execution(public * net.mobabel.nova.repository..*.find*(..))" + " || execution(public * net.mobabel.nova.repository..*.search*(..))" + " || execution(public * net.mobabel.nova.repository..*.is*(..))" + " || execution(public * net.mobabel.nova.repository..*.has*(..))" ) public void domainPointCut() { } @Pointcut( "@annotation(net.mobabel.nova.service.monitoring.NotLogOperation)" ) public void notLogPointCut() { } @Before( "logPointCut()" ) public void doBefore( JoinPoint joinPoint ) { } @Around( "(" + "domainPointCut()" + "|| logPointCut()" + ")" + "&& !notLogPointCut()" ) public Object doAround( ProceedingJoinPoint joinPoint ) throws Throwable { MethodSignature methodSignature = (MethodSignature) joinPoint.getStaticPart().getSignature(); Method method = methodSignature.getMethod(); final String packageName = method.getDeclaringClass().getPackage().getName(); Throwable errorProduced = null; Object result = null; if (opsIncludedPackages == null || opsIncludedPackages.stream().anyMatch( packageName::startsWith )) { try { long start = System.currentTimeMillis(); result = joinPoint.proceed(); long end = System.currentTimeMillis(); long time = end - start; MDC.put( MDC_EXECUTION_LASTED, Long.toString( time ) ); } catch (Throwable t) { errorProduced = t; throw t; } finally { if (opsLogRequestsEnable) { String methodName; try { if (errorProduced != null) { methodName = extractMethodFullName(joinPoint) ; logger.error( "[repository][{}]|[{}]", methodName, errorProduced.getClass().getSimpleName() ); } else { methodName = extractMethodName(joinPoint) ; logger.info( "[repository][{}]|[]", methodName ); } } finally { } } MDC.remove( MDC_EXECUTION_LASTED ); } } else { result = joinPoint.proceed(); } return result; } @AfterReturning( returning = "object", pointcut = "logPointCut()" ) public void doAfterReturning( Object object ) { } @After( "logPointCut()" ) public void doAfter( JoinPoint joinPoint ) { } @AfterThrowing( pointcut = "logPointCut()", throwing = "e" ) public void doAfterThrowing( JoinPoint joinPoint, Throwable e ) { } } |
1-3-2. 3.2 AOP for Service
Show me the code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
/* * Copyright (c) 2016-2018 Mobabel.net * * All rights reserved. */ package net.mobabel.nova.service.monitoring.aspect; import static net.mobabel.nova.service.monitoring.Constants.MDC_ACCOUNT_ID; import static net.mobabel.nova.service.monitoring.Constants.MDC_ACCOUNT_TYPE; import static net.mobabel.nova.service.monitoring.Constants.MDC_EXECUTION_LASTED; import static net.mobabel.nova.service.monitoring.Constants.MDC_OPERATION_LABEL; import static net.mobabel.nova.service.monitoring.MonitorUtils.extractBasicAccount; import static net.mobabel.nova.service.monitoring.MonitorUtils.extractMethodFullName; import static net.mobabel.nova.service.monitoring.MonitorUtils.extractMethodName; import java.lang.reflect.Method; import java.util.List; import javax.servlet.http.HttpServletRequest; import net.mobabel.nova.core.util.Logger; import net.mobabel.nova.model.authc.BasicAccount; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.slf4j.MDC; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; @Aspect @Component public class ServiceAspect { protected Logger logger = Logger.getLogger( this.getClass() ); @Value( "${monitor.operation_logging.log_requests:false}" ) private boolean opsLogRequestsEnable; @Value( "#{'${monitor.operation_logging.included_packages.service}'.split(',')}" ) private List<String> opsIncludedPackages; @Pointcut( "@annotation(net.mobabel.nova.service.monitoring.LogOperation)" ) public void logPointCut() { } @Pointcut( "execution(public * net.mobabel.nova.service.domain..*.add*(..))" + " || execution(public * net.mobabel.nova.service.domain..*.save*(..))" + " || execution(public * net.mobabel.nova.service.domain..*.edit*(..))" + " || execution(public * net.mobabel.nova.service.domain..*.update*(..))" + " || execution(public * net.mobabel.nova.service.domain..*.delete*(..))" + " || execution(public * net.mobabel.nova.service.domain..*.remove*(..))" + " || execution(public * net.mobabel.nova.service.domain..*.list*(..))" + " || execution(public * net.mobabel.nova.service.domain..*.get*(..))" + " || execution(public * net.mobabel.nova.service.domain..*.find*(..))" + " || execution(public * net.mobabel.nova.service.domain..*.search*(..))" + " || execution(public * net.mobabel.nova.service.domain..*.is*(..))" + " || execution(public * net.mobabel.nova.service.domain..*.has*(..))" ) public void domainPointCut() { } @Pointcut( "@annotation(net.mobabel.nova.service.monitoring.NotLogOperation)" ) public void notLogPointCut() { } @Before( "logPointCut()" ) public void doBefore( JoinPoint joinPoint ) { } @Around( "(" + "domainPointCut()" + "|| logPointCut()" + ")" + "&& !notLogPointCut()" ) public Object doAround( ProceedingJoinPoint joinPoint ) throws Throwable { MethodSignature methodSignature = (MethodSignature) joinPoint.getStaticPart().getSignature(); Method method = methodSignature.getMethod(); final String packageName = method.getDeclaringClass().getPackage().getName(); Throwable errorProduced = null; Object result = null; if (opsIncludedPackages == null || opsIncludedPackages.stream().anyMatch( packageName::startsWith )) { BasicAccount basicAccount = extractBasicAccount(); final String operationName = extractOperationName(); try { if (basicAccount != null) { MDC.put( MDC_ACCOUNT_ID, Long.toString( basicAccount.getId() ) ); MDC.put( MDC_ACCOUNT_TYPE, Integer.toString( basicAccount.getAccountType() ) ); } long start = System.currentTimeMillis(); result = joinPoint.proceed(); long end = System.currentTimeMillis(); long time = end - start; MDC.put( MDC_EXECUTION_LASTED, Long.toString( time ) ); } catch (Throwable t) { errorProduced = t; throw t; } finally { if (opsLogRequestsEnable) { String methodName; try { MDC.put( MDC_OPERATION_LABEL, operationName ); if (errorProduced != null) { methodName = extractMethodFullName( joinPoint ); logger.error( "[service][{}][{}]|[{}]", operationName, methodName, errorProduced.getClass().getSimpleName() ); } else { methodName = extractMethodName( joinPoint ); logger.info( "[service][{}][{}]|[]", operationName, methodName ); } } finally { MDC.remove( MDC_OPERATION_LABEL ); } } MDC.remove( MDC_ACCOUNT_ID ); MDC.remove( MDC_ACCOUNT_TYPE ); MDC.remove( MDC_EXECUTION_LASTED ); } } else { result = joinPoint.proceed(); } return result; } @AfterReturning( returning = "object", pointcut = "logPointCut()" ) public void doAfterReturning( Object object ) { } @After( "logPointCut()" ) public void doAfter( JoinPoint joinPoint ) { } @AfterThrowing( pointcut = "logPointCut()", throwing = "e" ) public void doAfterThrowing( JoinPoint joinPoint, Throwable e ) { } private String extractOperationName() { try { ServletRequestAttributes servletRequestAttributes = ( (ServletRequestAttributes) RequestContextHolder.getRequestAttributes() ); if (servletRequestAttributes != null) { HttpServletRequest request = servletRequestAttributes.getRequest(); return request.getRequestURI(); } } catch (Exception ignore) { } return ""; } } |
1-3-3. 3.3 AOP for Controller
ControllerAspect
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 |
/* * Copyright (c) 2016-2018 Mobabel.net * * All rights reserved. */ package net.mobabel.nova.service.monitoring.aspect; import net.mobabel.nova.core.basic.Re; import net.mobabel.nova.core.util.Logger; import net.mobabel.nova.model.authc.BasicAccount; import net.mobabel.nova.service.monitoring.MonitorUtils; import net.mobabel.nova.service.monitoring.NotLogOperation; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.aspectj.lang.reflect.MethodSignature; import org.slf4j.MDC; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.util.List; import static net.mobabel.nova.service.monitoring.Constants.*; import static net.mobabel.nova.service.monitoring.MonitorUtils.extractBasicAccount; import static net.mobabel.nova.service.monitoring.MonitorUtils.extractOperationName; @Aspect @Component public class ControllerAspect { protected Logger logger = Logger.getLogger( this.getClass() ); @Value( "${monitor.operation_logging.log_requests:false}" ) private boolean opsLogRequestsEnable; @Value( "#{'${monitor.operation_logging.included_packages.controller}'.split(',')}" ) private List<String> opsIncludedPackages; @Pointcut( "@annotation(net.mobabel.nova.service.monitoring.LogOperation)" ) public void logPointCut() { } @Pointcut( "@annotation(net.mobabel.nova.service.monitoring.NotLogOperation)" ) public void notLogPointCut() { } @Before( "logPointCut()" ) public void doBefore( JoinPoint joinPoint ) { } @Around( "(" + "@annotation(org.springframework.web.bind.annotation.RequestMapping)" + "|| @annotation(org.springframework.web.bind.annotation.GetMapping)" + "|| @annotation(org.springframework.web.bind.annotation.PostMapping)" + "|| @annotation(org.springframework.web.bind.annotation.PutMapping)" + "|| @annotation(org.springframework.web.bind.annotation.DeleteMapping)" + "|| @annotation(org.springframework.web.bind.annotation.PatchMapping)" + "|| logPointCut()" + ")" + "&& !notLogPointCut()" ) public Object doAround( ProceedingJoinPoint joinPoint ) throws Throwable { MethodSignature methodSignature = (MethodSignature) joinPoint.getStaticPart().getSignature(); Method method = methodSignature.getMethod(); final String packageName = method.getDeclaringClass().getPackage().getName(); Throwable errorProduced = null; Object result = null; if (opsIncludedPackages == null || opsIncludedPackages.stream().anyMatch( packageName::startsWith )) { Object[] args = joinPoint.getArgs(); final String operationName = extractOperationName( method ); BasicAccount basicAccount = extractBasicAccount( args ); try { if (basicAccount != null) { MDC.put( MDC_ACCOUNT_ID, Long.toString( basicAccount.getId() ) ); MDC.put( MDC_ACCOUNT_TYPE, Integer.toString( basicAccount.getAccountType() ) ); } long start = System.currentTimeMillis(); if (opsLogRequestsEnable) { logger.info( "[controller][{}][]|[]", operationName ); } result = joinPoint.proceed(); long end = System.currentTimeMillis(); long time = end - start; MDC.put( MDC_EXECUTION_LASTED, Long.toString( time ) ); } catch (Throwable t) { errorProduced = t; throw t; } finally { if (opsLogRequestsEnable) { if (operationName != null) { try { MDC.put( MDC_OPERATION_LABEL, operationName ); StringBuilder sbArgs = extractArguments( method, args ); if (errorProduced != null) { logger.error( "[controller][{}][{}]|[{}]", operationName, sbArgs.toString(), errorProduced.getClass().getSimpleName() ); } else if (result != null && result instanceof ResponseEntity) { logger.info( "[controller][{}][{}]|[{}]", operationName, sbArgs.toString(), ( (ResponseEntity<?>) result ).getStatusCodeValue() ); } else if (result != null && result instanceof Re) { logger.info( "[controller][{}][{}]|[{}]", operationName, sbArgs.toString(), ( (Re) result ).getCode() ); } else { logger.info( "[controller][{}][{}]|[]", operationName, sbArgs.toString() ); } } finally { MDC.remove( MDC_OPERATION_LABEL ); } } } MDC.remove( MDC_ACCOUNT_ID ); MDC.remove( MDC_ACCOUNT_TYPE ); MDC.remove( MDC_EXECUTION_LASTED ); } } else { result = joinPoint.proceed(); } return result; } @AfterReturning( returning = "object", pointcut = "logPointCut()" ) public void doAfterReturning( Object object ) { } @After( "logPointCut()" ) public void doAfter( JoinPoint joinPoint ) { } @AfterThrowing( pointcut = "logPointCut()", throwing = "e" ) public void doAfterThrowing( JoinPoint joinPoint, Throwable e ) { } private StringBuilder extractArguments( Method method, Object[] args ) { StringBuilder sb = new StringBuilder(); try { Parameter[] parameters = method.getParameters(); boolean added = false; if (parameters != null && parameters.length > 0) { sb.append( ": " ); for (int i = 0; i < parameters.length; i++) { Parameter parameter = parameters[i]; if (parameter.getAnnotation( NotLogOperation.class ) == null && args[i] != null) { if (parameter.getType().isPrimitive() || parameter.getType().isEnum() || CharSequence.class.isAssignableFrom( parameter.getType() )) { if (added) { sb.append( ";" ); } sb.append( parameter.getName() ); sb.append( "=" ); sb.append( args[i].toString() ); added = true; } else if (parameter.getType().isArray() && ( parameter.getType().getComponentType().isPrimitive() || parameter.getType().getComponentType().isEnum() || CharSequence.class.isAssignableFrom( parameter.getType().getComponentType() ) )) { if (added) { sb.append( ";" ); } sb.append( parameter.getName() ); sb.append( "=" ); sb.append( MonitorUtils.join( ",", (Object[]) args[i] ) ); added = true; } } } } } catch (Exception e) { logger.error( "Error extracting arguments from method", e ); } return sb; } } |
2. Test
In the test, a blog edit request was executed, and all related logs were collected here:
1 2 3 4 5 6 7 8 |
[mgr] [INFO ] [2018-12-03 14:22:47,634] [-79463] [http-apr-8080-exec-1] [259708060346486784] [1:0] [] [ControllerLogInterceptor:55] - [controller][/blog/post/edit][]|[] [mgr] [DEBUG] [2018-12-03 14:22:47,835] [-79664] [http-apr-8080-exec-1] [259708060346486784] [1:0] [] [edit:159] - ==> Preparing: update blog_posts set parent_id = ?, title = ?, summary = ?, content = ? where id = ? [mgr] [DEBUG] [2018-12-03 14:22:47,838] [-79667] [http-apr-8080-exec-1] [259708060346486784] [1:0] [] [edit:159] - <== Updates: 1 [mgr] [INFO ] [2018-12-03 14:22:47,839] [-79668] [http-apr-8080-exec-1] [259708060346486784] [1:0] [86] [RepositoryAspect:55] - [repository][edit()]|[] [mgr] [DEBUG] [2018-12-03 14:22:47,839] [-79668] [http-apr-8080-exec-1] [259708060346486784] [1:0] [] [PreparedStatementPool:160] - {conn-10001, pstmt-20004} exit cache [mgr] [DEBUG] [2018-12-03 14:22:47,840] [-79669] [http-apr-8080-exec-1] [259708060346486784] [1:0] [] [PreparedStatementPool:129] - {conn-10001, pstmt-20025} enter cache [mgr] [INFO ] [2018-12-03 14:22:47,842] [-79671] [http-apr-8080-exec-1] [259708060346486784] [1:0] [194] [ServiceAspect:55] - [service][/blog/post/edit.do][edit()]|[] [mgr] [INFO ] [2018-12-03 14:22:47,844] [-79673] [http-apr-8080-exec-1] [259708060346486784] [:] [210] [ControllerLogInterceptor:55] - [controller][/blog/post/edit][]|[] |
Take one line and map the content to the log format table:
1 |
[mgr] [INFO ] [2018-12-03 14:22:47,842] [-79671] [http-apr-8080-exec-1] [259708060346486784] [1:0] [194] [ServiceAspect:55] - [service][/blog/post/edit.do][edit()]|[] |
Name | Content |
---|---|
requestID | 259708060346486784 |
timestamp | 2018-12-03 14:22:47,842 |
level | INFO |
message | [service][/blog/post/edit.do][edit()]|[] |
app | mgr |
module | service |
operation label | /blog/post/edit.do |
accountId | 1:0 |
accountType | 1:0 |
status | |
elapsed | 194 |
error | — available in error |
thread id | 79671 |
Class name | ServiceAspect |
package.class | — available in error |
line number | — available in error |
3. ELK
TODO