Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
S
smart_gov_platform
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
赵啸非
smart_gov_platform
Commits
26bc5640
Commit
26bc5640
authored
Aug 22, 2022
by
赵啸非
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
修改访问日志添加
parent
8dd17521
Changes
8
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
92 additions
and
38 deletions
+92
-38
base-manager/src/main/java/com/mortals/xhx/base/framework/aspect/WebLogAspect.java
...a/com/mortals/xhx/base/framework/aspect/WebLogAspect.java
+76
-4
common-lib/pom.xml
common-lib/pom.xml
+6
-0
common-lib/src/main/java/com/mortals/xhx/common/keys/QueueKey.java
...b/src/main/java/com/mortals/xhx/common/keys/QueueKey.java
+1
-1
common-lib/src/main/java/com/mortals/xhx/module/MessageProducer.java
...src/main/java/com/mortals/xhx/module/MessageProducer.java
+2
-2
smart-gateway/pom.xml
smart-gateway/pom.xml
+1
-5
smart-gateway/src/main/java/com/mortals/xhx/base/framework/filter/AccessLogFilter.java
...om/mortals/xhx/base/framework/filter/AccessLogFilter.java
+2
-2
smart-gateway/src/main/java/com/mortals/xhx/base/framework/filter/GatewayResponseFilter.java
...tals/xhx/base/framework/filter/GatewayResponseFilter.java
+1
-8
smart-gateway/src/main/java/com/mortals/xhx/base/framework/filter/GlobalLogFilter.java
...om/mortals/xhx/base/framework/filter/GlobalLogFilter.java
+3
-16
No files found.
base-manager/src/main/java/com/mortals/xhx/base/framework/aspect/WebLogAspect.java
View file @
26bc5640
package
com.mortals.xhx.base.framework.aspect
;
package
com.mortals.xhx.base.framework.aspect
;
import
cn.hutool.core.date.DateUtil
;
import
cn.hutool.core.net.NetUtil
;
import
cn.hutool.core.util.IdUtil
;
import
com.alibaba.fastjson.JSON
;
import
com.alibaba.fastjson.JSON
;
import
com.alibaba.fastjson.JSONObject
;
import
com.alibaba.fastjson.JSONObject
;
import
com.mortals.framework.util.DateUtils
;
import
com.mortals.framework.util.DateUtils
;
import
com.mortals.xhx.common.pdu.access.AccessLogPdu
;
import
com.mortals.xhx.module.MessageProducer
;
import
lombok.extern.slf4j.Slf4j
;
import
lombok.extern.slf4j.Slf4j
;
import
org.aspectj.lang.JoinPoint
;
import
org.aspectj.lang.JoinPoint
;
import
org.aspectj.lang.annotation.AfterReturning
;
import
org.aspectj.lang.annotation.AfterReturning
;
...
@@ -10,9 +15,12 @@ import org.aspectj.lang.annotation.Aspect;
...
@@ -10,9 +15,12 @@ import org.aspectj.lang.annotation.Aspect;
import
org.aspectj.lang.annotation.Before
;
import
org.aspectj.lang.annotation.Before
;
import
org.aspectj.lang.annotation.Pointcut
;
import
org.aspectj.lang.annotation.Pointcut
;
import
org.slf4j.MDC
;
import
org.slf4j.MDC
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.context.annotation.Profile
;
import
org.springframework.context.annotation.Profile
;
import
org.springframework.core.annotation.Order
;
import
org.springframework.core.annotation.Order
;
import
org.springframework.stereotype.Component
;
import
org.springframework.stereotype.Component
;
import
org.springframework.util.ObjectUtils
;
import
org.springframework.web.context.request.RequestContextHolder
;
import
org.springframework.web.context.request.RequestContextHolder
;
import
org.springframework.web.context.request.ServletRequestAttributes
;
import
org.springframework.web.context.request.ServletRequestAttributes
;
import
org.springframework.web.util.ContentCachingRequestWrapper
;
import
org.springframework.web.util.ContentCachingRequestWrapper
;
...
@@ -36,6 +44,11 @@ import java.util.Map;
...
@@ -36,6 +44,11 @@ import java.util.Map;
@Profile
({
"default"
,
"develop"
,
"test"
})
@Profile
({
"default"
,
"develop"
,
"test"
})
public
class
WebLogAspect
{
public
class
WebLogAspect
{
@Value
(
"${spring.application.name:gateway}"
)
private
String
appName
;
@Autowired
private
MessageProducer
messageProducer
;
private
static
final
String
TRACE_ID
=
"traceId"
;
private
static
final
String
TRACE_ID
=
"traceId"
;
private
static
final
String
SPAN_ID
=
"spanId"
;
private
static
final
String
SPAN_ID
=
"spanId"
;
private
static
final
String
PSPAN_ID
=
"pspanId"
;
private
static
final
String
PSPAN_ID
=
"pspanId"
;
...
@@ -58,6 +71,7 @@ public class WebLogAspect {
...
@@ -58,6 +71,7 @@ public class WebLogAspect {
HttpServletRequest
request
=
attributes
.
getRequest
();
HttpServletRequest
request
=
attributes
.
getRequest
();
// log.debug("请求路径 {} ,进入方法 {}", request.getRequestURI(), joinPoint.getSignature().getDeclaringTypeName() + ":" + joinPoint.getSignature().getName());
// log.debug("请求路径 {} ,进入方法 {}", request.getRequestURI(), joinPoint.getSignature().getDeclaringTypeName() + ":" + joinPoint.getSignature().getName());
MDC
.
put
(
"req"
,
getRequestInfo
(
request
).
toJSONString
());
MDC
.
put
(
"req"
,
getRequestInfo
(
request
).
toJSONString
());
MDC
.
put
(
"reqParams"
,
getRequestInfoParams
(
request
).
toJSONString
());
MDC
.
put
(
"startTime"
,
String
.
valueOf
(
System
.
currentTimeMillis
()));
MDC
.
put
(
"startTime"
,
String
.
valueOf
(
System
.
currentTimeMillis
()));
}
}
...
@@ -78,14 +92,46 @@ public class WebLogAspect {
...
@@ -78,14 +92,46 @@ public class WebLogAspect {
long
takeTime
=
(
System
.
currentTimeMillis
()
-
Long
.
parseLong
(
startTime
));
long
takeTime
=
(
System
.
currentTimeMillis
()
-
Long
.
parseLong
(
startTime
));
if
(
result
instanceof
String
)
{
if
(
result
instanceof
String
)
{
log
.
info
(
" \n 请求路径:{} 耗时:{}ms \n traceId:{} pspanId:{} spanId:{} \n 请求报文:{} \n 响应报文:{}"
log
.
debug
(
" \n 请求路径:{} 耗时:{}ms \n traceId:{} pspanId:{} spanId:{} \n 请求报文:{} \n 响应报文:{}"
,
request
.
getRequestURI
(),
takeTime
,
traceId
,
pspanId
,
spanId
,
map
.
getOrDefault
(
"req"
,
""
),
result
);
,
request
.
getRequestURI
(),
takeTime
,
traceId
,
pspanId
,
spanId
,
map
.
getOrDefault
(
"req"
,
""
),
result
);
}
else
{
}
else
{
log
.
info
(
" \n 请求路径:{} 耗时:{}ms \n traceId:{} pspanId:{} spanId:{} \n 请求报文:{} \n 响应报文:{}"
log
.
debug
(
" \n 请求路径:{} 耗时:{}ms \n traceId:{} pspanId:{} spanId:{} \n 请求报文:{} \n 响应报文:{}"
,
request
.
getRequestURI
(),
takeTime
,
traceId
,
pspanId
,
spanId
,
map
.
getOrDefault
(
"req"
,
""
),
JSON
.
toJSONString
(
result
));
,
request
.
getRequestURI
(),
takeTime
,
traceId
,
pspanId
,
spanId
,
map
.
getOrDefault
(
"req"
,
""
),
JSON
.
toJSONString
(
result
));
}
}
if
(!
ObjectUtils
.
isEmpty
(
pspanId
)
&&
!
ObjectUtils
.
isEmpty
(
spanId
))
{
//paspId
spanId
=
String
.
valueOf
(
Integer
.
parseInt
(
spanId
)
+
1
);
pspanId
=
spanId
;
}
AccessLogPdu
accessLogPdu
=
new
AccessLogPdu
();
accessLogPdu
.
initAttrValue
();
accessLogPdu
.
setAppName
(
appName
);
accessLogPdu
.
setTraceID
(
traceId
==
null
?
IdUtil
.
objectId
()
:
traceId
);
accessLogPdu
.
setPspanId
(
Integer
.
parseInt
(
pspanId
));
accessLogPdu
.
setSpanId
(
Integer
.
parseInt
(
spanId
));
accessLogPdu
.
setSchemaData
(
request
.
getScheme
());
accessLogPdu
.
setHostName
(
NetUtil
.
getLocalHostName
());
accessLogPdu
.
setUri
(
request
.
getRequestURI
());
accessLogPdu
.
setTargetServer
(
request
.
getServletPath
());
accessLogPdu
.
setRequestIp
(
request
.
getRemoteAddr
());
accessLogPdu
.
setUa
(
request
.
getHeader
(
"User-Agent"
));
accessLogPdu
.
setRequestTime
(
DateUtil
.
parseTime
(
startTime
));
accessLogPdu
.
setLogTime
(
new
Date
());
accessLogPdu
.
setMethod
(
request
.
getMethod
());
accessLogPdu
.
setResponseTime
(
new
Date
());
accessLogPdu
.
setDuration
(
takeTime
);
accessLogPdu
.
setRequestData
(
map
.
getOrDefault
(
"reqParams"
,
""
));
if
(
result
instanceof
String
)
{
accessLogPdu
.
setResponseData
(
result
.
toString
());
}
else
{
accessLogPdu
.
setResponseData
(
JSON
.
toJSONString
(
result
));
}
messageProducer
.
syncAccessSend
(
accessLogPdu
);
}
}
}
}
...
@@ -118,4 +164,30 @@ public class WebLogAspect {
...
@@ -118,4 +164,30 @@ public class WebLogAspect {
}
}
return
requestInfo
;
return
requestInfo
;
}
}
/**
* 读取请求信息,如果是表单则转换为json
*/
private
JSONObject
getRequestInfoParams
(
HttpServletRequest
req
)
{
JSONObject
requestInfo
=
new
JSONObject
();
try
{
if
(
req
.
getQueryString
()
!=
null
)
{
requestInfo
.
put
(
"queryString"
,
URLDecoder
.
decode
(
req
.
getQueryString
(),
"UTF-8"
));
}
if
(
req
instanceof
ContentCachingRequestWrapper
)
{
ContentCachingRequestWrapper
wrapper
=
(
ContentCachingRequestWrapper
)
req
;
String
bodyStr
=
new
String
(
wrapper
.
getContentAsByteArray
(),
StandardCharsets
.
UTF_8
);
if
(
bodyStr
.
startsWith
(
"{"
))
{
JSONObject
jsonObject
=
JSON
.
parseObject
(
bodyStr
);
requestInfo
.
put
(
"requestBody"
,
jsonObject
);
}
}
}
catch
(
Exception
e
)
{
log
.
error
(
"解析请求失败"
,
e
);
requestInfo
.
put
(
"parseError"
,
e
.
getMessage
());
}
return
requestInfo
;
}
}
}
common-lib/pom.xml
View file @
26bc5640
...
@@ -24,6 +24,12 @@
...
@@ -24,6 +24,12 @@
<artifactId>
mortals-framework-springcloud
</artifactId>
<artifactId>
mortals-framework-springcloud
</artifactId>
</dependency>
</dependency>
<!-- 实现对 RabbitMQ 的自动化配置 -->
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-amqp
</artifactId>
</dependency>
<!-- <dependency>
<!-- <dependency>
<groupId>io.sentry</groupId>
<groupId>io.sentry</groupId>
<artifactId>sentry-spring-boot-starter</artifactId>
<artifactId>sentry-spring-boot-starter</artifactId>
...
...
smart-gateway/src/main/java/com/mortals/xhx/common/key
/QueueKey.java
→
common-lib/src/main/java/com/mortals/xhx/common/keys
/QueueKey.java
View file @
26bc5640
package
com.mortals.xhx.common.key
;
package
com.mortals.xhx.common.key
s
;
/**
/**
* rabbit 队列key定义
* rabbit 队列key定义
...
...
smart-gateway/src/main/java/com/mortals/xhx/base/framework/servic
e/MessageProducer.java
→
common-lib/src/main/java/com/mortals/xhx/modul
e/MessageProducer.java
View file @
26bc5640
package
com.mortals.xhx.
base.framework.servic
e
;
package
com.mortals.xhx.
modul
e
;
import
com.alibaba.fastjson.JSON
;
import
com.alibaba.fastjson.JSON
;
import
com.mortals.xhx.common.key.QueueKey
;
import
com.mortals.xhx.common.key
s
.QueueKey
;
import
com.mortals.xhx.common.pdu.access.AccessLogPdu
;
import
com.mortals.xhx.common.pdu.access.AccessLogPdu
;
import
org.springframework.amqp.rabbit.core.RabbitTemplate
;
import
org.springframework.amqp.rabbit.core.RabbitTemplate
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Autowired
;
...
...
smart-gateway/pom.xml
View file @
26bc5640
...
@@ -95,11 +95,7 @@
...
@@ -95,11 +95,7 @@
<artifactId>
spring-cloud-starter-loadbalancer
</artifactId>
<artifactId>
spring-cloud-starter-loadbalancer
</artifactId>
</dependency>
</dependency>
<!-- 实现对 RabbitMQ 的自动化配置 -->
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-amqp
</artifactId>
</dependency>
<!-- <dependency>
<!-- <dependency>
...
...
smart-gateway/src/main/java/com/mortals/xhx/base/framework/filter/AccessLogFilter.java
View file @
26bc5640
...
@@ -3,7 +3,7 @@ package com.mortals.xhx.base.framework.filter;
...
@@ -3,7 +3,7 @@ package com.mortals.xhx.base.framework.filter;
import
cn.hutool.core.net.NetUtil
;
import
cn.hutool.core.net.NetUtil
;
import
cn.hutool.core.util.ObjectUtil
;
import
cn.hutool.core.util.ObjectUtil
;
import
com.mortals.framework.util.StringUtils
;
import
com.mortals.framework.util.StringUtils
;
import
com.mortals.xhx.
base.framework.servic
e.MessageProducer
;
import
com.mortals.xhx.
modul
e.MessageProducer
;
import
com.mortals.xhx.common.pdu.access.AccessLogPdu
;
import
com.mortals.xhx.common.pdu.access.AccessLogPdu
;
import
com.mortals.xhx.common.utils.IpUtils
;
import
com.mortals.xhx.common.utils.IpUtils
;
import
lombok.extern.slf4j.Slf4j
;
import
lombok.extern.slf4j.Slf4j
;
...
@@ -94,7 +94,7 @@ public class AccessLogFilter implements GlobalFilter, Ordered {
...
@@ -94,7 +94,7 @@ public class AccessLogFilter implements GlobalFilter, Ordered {
accessLogPdu
.
setAppName
(
appName
);
accessLogPdu
.
setAppName
(
appName
);
accessLogPdu
.
setTraceID
(
headers
.
getOrDefault
(
TRACE_ID
,
""
));
accessLogPdu
.
setTraceID
(
headers
.
getOrDefault
(
TRACE_ID
,
""
));
accessLogPdu
.
setPspanId
(
Integer
.
parseInt
(
headers
.
getOrDefault
(
PSPAN_ID
,
"0"
)));
accessLogPdu
.
setPspanId
(
Integer
.
parseInt
(
headers
.
getOrDefault
(
PSPAN_ID
,
"0"
)));
accessLogPdu
.
setSpanId
(
Integer
.
parseInt
(
headers
.
getOrDefault
(
SPAN_ID
,
"
0
"
)));
accessLogPdu
.
setSpanId
(
Integer
.
parseInt
(
headers
.
getOrDefault
(
SPAN_ID
,
"
1
"
)));
accessLogPdu
.
setSchemaData
(
request
.
getURI
().
getScheme
());
accessLogPdu
.
setSchemaData
(
request
.
getURI
().
getScheme
());
accessLogPdu
.
setHostName
(
NetUtil
.
getLocalHostName
());
accessLogPdu
.
setHostName
(
NetUtil
.
getLocalHostName
());
accessLogPdu
.
setUri
(
requestPath
);
accessLogPdu
.
setUri
(
requestPath
);
...
...
smart-gateway/src/main/java/com/mortals/xhx/base/framework/filter/GatewayResponseFilter.java
View file @
26bc5640
package
com.mortals.xhx.base.framework.filter
;
package
com.mortals.xhx.base.framework.filter
;
import
cn.hutool.extra.servlet.ServletUtil
;
import
com.alibaba.fastjson.JSON
;
import
com.mortals.framework.util.StringUtils
;
import
com.mortals.framework.util.StringUtils
;
import
com.mortals.xhx.
base.framework.servic
e.MessageProducer
;
import
com.mortals.xhx.
modul
e.MessageProducer
;
import
lombok.extern.slf4j.Slf4j
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.codec.Charsets
;
import
org.apache.commons.codec.Charsets
;
import
org.reactivestreams.Publisher
;
import
org.reactivestreams.Publisher
;
import
org.slf4j.MDC
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.cloud.gateway.filter.GatewayFilterChain
;
import
org.springframework.cloud.gateway.filter.GatewayFilterChain
;
...
@@ -20,15 +17,11 @@ import org.springframework.core.io.buffer.DefaultDataBufferFactory;
...
@@ -20,15 +17,11 @@ import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import
org.springframework.http.HttpStatus
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.http.server.reactive.ServerHttpResponse
;
import
org.springframework.http.server.reactive.ServerHttpResponse
;
import
org.springframework.http.server.reactive.ServerHttpResponseDecorator
;
import
org.springframework.http.server.reactive.ServerHttpResponseDecorator
;
import
org.springframework.stereotype.Component
;
import
org.springframework.util.ObjectUtils
;
import
org.springframework.web.server.ServerWebExchange
;
import
org.springframework.web.server.ServerWebExchange
;
import
reactor.core.publisher.Flux
;
import
reactor.core.publisher.Flux
;
import
reactor.core.publisher.Mono
;
import
reactor.core.publisher.Mono
;
import
java.nio.charset.Charset
;
import
java.nio.charset.Charset
;
import
java.util.List
;
import
java.util.Map
;
import
static
org
.
springframework
.
cloud
.
gateway
.
support
.
ServerWebExchangeUtils
.
ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR
;
import
static
org
.
springframework
.
cloud
.
gateway
.
support
.
ServerWebExchangeUtils
.
ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR
;
...
...
smart-gateway/src/main/java/com/mortals/xhx/base/framework/filter/GlobalLogFilter.java
View file @
26bc5640
package
com.mortals.xhx.base.framework.filter
;
package
com.mortals.xhx.base.framework.filter
;
import
cn.hutool.core.map.MapUtil
;
import
cn.hutool.core.net.NetUtil
;
import
cn.hutool.core.util.IdUtil
;
import
cn.hutool.core.util.IdUtil
;
import
cn.hutool.extra.servlet.ServletUtil
;
import
cn.hutool.http.HttpUtil
;
import
com.alibaba.fastjson.JSON
;
import
com.mortals.xhx.base.framework.config.CustomGatewayProperties
;
import
com.mortals.xhx.base.framework.config.CustomGatewayProperties
;
import
com.mortals.xhx.base.framework.service.MessageProducer
;
import
com.mortals.xhx.module.MessageProducer
;
import
com.mortals.xhx.common.pdu.access.AccessLogPdu
;
import
com.mortals.xhx.common.utils.IpUtils
;
import
com.sun.jndi.toolkit.url.UrlUtil
;
import
lombok.extern.slf4j.Slf4j
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.lang3.StringUtils
;
import
org.apache.commons.lang3.StringUtils
;
import
org.slf4j.MDC
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.cloud.gateway.filter.GatewayFilterChain
;
import
org.springframework.cloud.gateway.filter.GatewayFilterChain
;
...
@@ -24,18 +15,14 @@ import org.springframework.core.io.buffer.DataBufferUtils;
...
@@ -24,18 +15,14 @@ import org.springframework.core.io.buffer.DataBufferUtils;
import
org.springframework.http.MediaType
;
import
org.springframework.http.MediaType
;
import
org.springframework.http.server.reactive.ServerHttpRequest
;
import
org.springframework.http.server.reactive.ServerHttpRequest
;
import
org.springframework.stereotype.Component
;
import
org.springframework.stereotype.Component
;
import
org.springframework.util.MultiValueMap
;
import
org.springframework.web.server.ServerWebExchange
;
import
org.springframework.web.server.ServerWebExchange
;
import
org.springframework.web.util.UriComponentsBuilder
;
import
org.springframework.web.util.UriComponentsBuilder
;
import
reactor.core.publisher.Flux
;
import
reactor.core.publisher.Flux
;
import
reactor.core.publisher.Mono
;
import
reactor.core.publisher.Mono
;
import
javax.sound.midi.Track
;
import
java.net.InetAddress
;
import
java.net.URI
;
import
java.net.URI
;
import
java.nio.CharBuffer
;
import
java.nio.CharBuffer
;
import
java.nio.charset.StandardCharsets
;
import
java.nio.charset.StandardCharsets
;
import
java.util.Date
;
import
java.util.LinkedHashSet
;
import
java.util.LinkedHashSet
;
import
java.util.concurrent.atomic.AtomicReference
;
import
java.util.concurrent.atomic.AtomicReference
;
...
@@ -74,8 +61,8 @@ public class GlobalLogFilter implements GlobalFilter, Ordered {
...
@@ -74,8 +61,8 @@ public class GlobalLogFilter implements GlobalFilter, Ordered {
ServerHttpRequest
newRequest
=
exchange
.
getRequest
().
mutate
()
ServerHttpRequest
newRequest
=
exchange
.
getRequest
().
mutate
()
.
header
(
TRACE_ID
,
traceId
)
.
header
(
TRACE_ID
,
traceId
)
.
header
(
SPAN_ID
,
pspanId
.
toString
())
.
header
(
P
SPAN_ID
,
pspanId
.
toString
())
.
header
(
P
SPAN_ID
,
spanId
.
toString
())
.
header
(
SPAN_ID
,
spanId
.
toString
())
.
build
();
.
build
();
return
chain
.
filter
(
exchange
.
mutate
().
request
(
newRequest
).
build
());
return
chain
.
filter
(
exchange
.
mutate
().
request
(
newRequest
).
build
());
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment