-
Notifications
You must be signed in to change notification settings - Fork 1.4k
如何实现手工埋点和日志监控
HaojunRen edited this page May 31, 2024
·
12 revisions
① 自定义注入Header,实现StrategyHeadersInjector,允许同时注入多个,每个类里允许多个Header
public class MyStrategyHeadersInjector implements StrategyHeadersInjector {
@Override
public List<HeadersInjectorEntity> getHeadersInjectorEntityList() {
return Arrays.asList(
new HeadersInjectorEntity(HeadersInjectorType.TRANSMISSION, Arrays.asList("test1")),
new HeadersInjectorEntity(HeadersInjectorType.TRACER, Arrays.asList("test2")),
new HeadersInjectorEntity(HeadersInjectorType.ALL, Arrays.asList("test3")));
}
}
参数含义
- HeadersInjectorType.TRANSMISSION表示作用于传递,上面的代码表示对名称为“test1”的Header将自动传递到下游服务
- HeadersInjectorType.TRACER表示作用于调用链,上面的代码表示对名称为“test2”的Header将自动输出埋点到调用链和告警
- HeadersInjectorType.ALL表示同时作用于上述量项,不需要一一设定
在配置类里@Bean方式进行Header注入类创建
@Bean
public StrategyHeadersInjector strategyHeadersInjector() {
return new MyStrategyHeadersInjector();
}
② 自定义调用链上下文参数输出到调用链,继承DefaultStrategyTracerAdapter
// 自定义调用链上下文参数的创建
// 对于getTraceId和getSpanId方法,在OpenTracing等调用链中间件引入的情况下,由调用链中间件决定,在这里定义不会起作用;在OpenTracing等调用链中间件未引入的情况下,在这里定义才有效,下面代码中表示从Http Header中获取,并全链路传递
// 对于getCustomizationMap方法,表示输出到调用链中的定制化业务参数,可以同时输出到日志和OpenTracing等调用链中间件,下面代码中表示从Http Header中获取,并全链路传递
public class MyStrategyTracerAdapter extends DefaultStrategyTracerAdapter {
@Override
public String getTraceId() {
return StringUtils.isNotEmpty(strategyContextHolder.getHeader(DiscoveryConstant.TRACE_ID)) ? strategyContextHolder.getHeader(DiscoveryConstant.TRACE_ID) : StringUtils.EMPTY;
}
@Override
public String getSpanId() {
return StringUtils.isNotEmpty(strategyContextHolder.getHeader(DiscoveryConstant.SPAN_ID)) ? strategyContextHolder.getHeader(DiscoveryConstant.SPAN_ID) : StringUtils.EMPTY;
}
@Override
public Map<String, String> getCustomizationMap() {
Map<String, String> customizationMap = new LinkedHashMap<String, String>();
customizationMap.put("mobile", StringUtils.isNotEmpty(strategyContextHolder.getHeader("mobile")) ? strategyContextHolder.getHeader("mobile") : StringUtils.EMPTY);
customizationMap.put("user", StringUtils.isNotEmpty(strategyContextHolder.getHeader("user")) ? strategyContextHolder.getHeader("user") : StringUtils.EMPTY);
return customizationMap;
}
}
在配置类里@Bean方式进行调用链类创建,覆盖框架内置的调用链适配器
@Bean
public StrategyTracerAdapter strategyTracerAdapter() {
return new MyStrategyTracerAdapter();
}
注意事项
“自定义注入Header输出到调用链”和“自定义调用链上下文参数输出到调用链”的区别
- 前者只适用于Header埋点,后者不仅适用于Header埋点,也适用于其它参数埋点
- 前者一般适用于中间件再次封装的使用场景,允许多个,后者一般适用于最终业务的使用场景,只允许一个
③ 自定义类方法上入参和出参输出到调用链,实现ServiceStrategyMonitorAdapter,允许多个
// 自定义类方法上入参和出参输出到调用链
// parameterMap格式:
// key为入参名
// value为入参值
public class MyServiceStrategyMonitorAdapter implements ServiceStrategyMonitorAdapter {
@Override
public Map<String, String> getCustomizationMap(ServiceStrategyMonitorInterceptor interceptor, MethodInvocation invocation, Map<String, Object> parameterMap, Object returnValue) {
Map<String, String> customizationMap = new LinkedHashMap<String, String>();
customizationMap.put(DiscoveryConstant.PARAMETER, parameterMap.toString());
customizationMap.put(DiscoveryConstant.RETURN, returnValue != null ? returnValue.toString() : null);
return customizationMap;
}
}
在配置类里@Bean方式进行监控适配类创建
@Bean
public ServiceStrategyMonitorAdapter serviceStrategyMonitorAdapter() {
return new MyServiceStrategyMonitorAdapter();
}
④ 自定义方法输出到调用链,通过在带有@RestController或者@ServiceStrategy注解的类的方法头部上增加如下注解,即忽略该方法埋点输出、日志输出、告警输出
@ServiceMonitorIgnore
⑤ 业务方法上获取TraceId和SpanId
public class MyClass {
@Autowired
private StrategyMonitorContext strategyMonitorContext;
public void doXXX() {
String traceId = strategyMonitorContext.getTraceId();
String spanId = strategyMonitorContext.getSpanId();
...
}
}
对于全链路监控功能的开启和关闭,需要通过如下开关做控制
# 启动和关闭监控,一旦关闭,调用链和日志输出都将关闭。缺失则默认为false
spring.application.strategy.monitor.enabled=true
# 启动和关闭告警,一旦关闭,蓝绿灰度上下文输出都将关闭。缺失则默认为false
spring.application.strategy.alarm.enabled=true
# 启动和关闭日志输出。缺失则默认为false
spring.application.strategy.logger.enabled=true
# 日志输出中,是否显示MDC前面的Key。缺失则默认为true
spring.application.strategy.logger.mdc.key.shown=true
# 启动和关闭Debug日志打印,注意:每调用一次都会打印一次,会对性能有所影响,建议压测环境和生产环境关闭。缺失则默认为false
spring.application.strategy.logger.debug.enabled=true
# 启动和关闭调用链输出。缺失则默认为false
spring.application.strategy.tracer.enabled=true
# 启动和关闭调用链的蓝绿灰度信息以独立的Span节点输出,如果关闭,则蓝绿灰度信息输出到原生的Span节点中(SkyWalking不支持原生模式)。缺失则默认为true
spring.application.strategy.tracer.separate.span.enabled=true
# 启动和关闭调用链的蓝绿灰度规则策略信息输出。缺失则默认为true
spring.application.strategy.tracer.rule.output.enabled=true
# 启动和关闭调用链的异常信息是否以详细格式输出。缺失则默认为false
spring.application.strategy.tracer.exception.detail.output.enabled=true
# 启动和关闭类方法上入参和出参输出到调用链。缺失则默认为false
spring.application.strategy.tracer.method.context.output.enabled=true
# 显示在调用链界面上蓝绿灰度Span的名称,建议改成具有公司特色的框架产品名称。缺失则默认为NEPXION
spring.application.strategy.tracer.span.value=NEPXION
# 显示在调用链界面上蓝绿灰度Span Tag的插件名称,建议改成具有公司特色的框架产品的描述。缺失则默认为Nepxion Discovery
spring.application.strategy.tracer.span.tag.plugin.value=Nepxion Discovery
# 启动和关闭Sentinel调用链上规则在Span上的输出。缺失则默认为true
spring.application.strategy.tracer.sentinel.rule.output.enabled=true
# 启动和关闭Sentinel调用链上方法入参在Span上的输出。缺失则默认为false
spring.application.strategy.tracer.sentinel.args.output.enabled=true
蓝绿灰度埋点日志,通过MDC的%X{n-d-service-xyz}方式输出,目前支持11个参数,使用者可以根据实际使用场景进行裁剪,具体参考如下logback.xml配置
<!-- Logback configuration. See http://logback.qos.ch/manual/index.html -->
<configuration scan="true" scanPeriod="10 seconds">
<!-- Simple file output -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- Encoder defaults to ch.qos.logback.classic.encoder.PatternLayoutEncoder -->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %5p ${PID:- } --- [%15.15t] %X{trace-id} %X{span-id} %X{n-d-service-group} %X{n-d-service-type} %X{n-d-service-app-id} %X{n-d-service-id} %X{n-d-service-address} %X{n-d-service-version} %X{n-d-service-region} %X{n-d-service-env} %X{n-d-service-zone} %-40.40logger{39} : %msg%n</pattern>
<!-- <pattern>discovery %d{yyyy-MM-dd HH:mm:ss.SSS} %level [%thread] %X{trace-id} %X{span-id} %X{n-d-service-group} %X{n-d-service-type} %X{n-d-service-app-id} %X{n-d-service-id} %X{n-d-service-address} %X{n-d-service-version} %X{n-d-service-region} %X{n-d-service-env} %X{n-d-service-zone} %logger{10} [%file:%line] - %msg%n</pattern> -->
<charset>UTF-8</charset>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>log/discovery-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxFileSize>50MB</maxFileSize>
</rollingPolicy>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<!-- Safely log to the same file from multiple JVMs. Degrades performance! -->
<prudent>true</prudent>
</appender>
<appender name="FILE_ASYNC" class="ch.qos.logback.classic.AsyncAppender">
<discardingThreshold>0</discardingThreshold>
<queueSize>512</queueSize>
<appender-ref ref="FILE" />
</appender>
<!-- Console output -->
<conversionRule conversionWord="levelColor" converterClass="com.nepxion.discovery.common.logback.LevelColorConverter" />
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- Encoder defaults to ch.qos.logback.classic.encoder.PatternLayoutEncoder -->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %levelColor(%5p) %magenta(${PID:- }) --- [%15.15t] %levelColor(%X{trace-id}) %levelColor(%X{span-id}) %levelColor(%X{n-d-service-group}) %levelColor(%X{n-d-service-type}) %levelColor(%X{n-d-service-app-id}) %levelColor(%X{n-d-service-id}) %levelColor(%X{n-d-service-address}) %levelColor(%X{n-d-service-version}) %levelColor(%X{n-d-service-region}) %levelColor(%X{n-d-service-env}) %levelColor(%X{n-d-service-zone}) %cyan(%-40.40logger{39}) : %msg%n</pattern>
</encoder>
<!-- Only log level WARN and above -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
</appender>
<!-- For loggers in the these namespaces, log at all levels. -->
<logger name="pedestal" level="ALL" />
<logger name="hammock-cafe" level="ALL" />
<logger name="user" level="ALL" />
<root level="INFO">
<appender-ref ref="FILE_ASYNC" />
<appender-ref ref="STDOUT" />
</root>
</configuration>
上述格式支持输出彩色日志,帮助分辨和定位失败的测试用例
- 彩色日志配色方案,参考:https://logback.qos.ch/manual/layouts.html#coloring
- 编辑器需要打开相关开启ANSI颜色渲染的开关
- Windows终端默认不能显示ANSI颜色,需要在注册表HKEY_CURRENT_USER\Console中新建一个DWORD类型的值VirtualTerminalLevel,数值为1
- 彩色Logo显示方案
- 编辑器通过System.setProperty("nepxion.banner.shown.ansi.mode", "true")进行开启
- 命令行通过java -jar -Dnepxion.banner.shown.ansi.mode=true进行开启
2017-2050 ©Nepxion Studio Apache License
- 如何对接Foundation基础平台实施收敛集成
- 如何对接DevOps运维平台实施流量管控
- 如何部署对接DevOps运维平台的控制台
- 如何对接DevOps运维平台执行半自动化蓝绿灰度发布
- 如何使用DevOps运维平台对接的公共接口
- 如何设计全链路智能编排高级蓝绿灰度发布界面
- 如何实现Windows10下GraalVM本地镜像化
- 蓝绿灰度发布
- 流量染色
- 隔离路由
- 故障转移
- 多活单元化
- 限流熔断降级权限
- 网关动态路由
- 可观测监控
- 如何操作配置中心
- 如何理解框架开关配置
- 如何理解规则策略里内容格式配置
- 如何操作网关和服务的蓝绿灰度发布规则策略配置
- 如何操作网关动态路由规则策略配置
- 如何操作Sentinel规则策略配置
- 如何实施规则策略配置和业务配置在配置中心的合并和分离
- 如何理解自动扫描目录
- 如何自定义流量管控
- 如何自定义实现组合式的防护
- 如何自定义高级配置订阅功能
- 如何自定义订阅框架事件
- 如何自定义解决业务自身跨线程上下文切换的问题
- 如何自定义重用框架内置的Swagger模块
- 如何自定义Header全链路传递
- 如何遵循Nepxion Discovery网关标准实现对其它网关全链路流量管控的二次开发
- 如何遵循Nepxion Discovery服务标准实现对消息队列等其它中间件全链路流量管控的二次开发