网站用哪些系统做的比较好wordpress 替换谷歌字体
网站用哪些系统做的比较好,wordpress 替换谷歌字体,地方门户网站取名,婚嫁网站模板Spring Cloud 2025.0.0 整合自定义日志注解完整教程本教程基于 Spring Cloud 2025.0.0 新特性#xff0c;包含虚拟线程、响应式编程、AOT 原生编译支持一、技术栈和架构
1.1 技术选型
Spring Cloud 2025.0.0 (代号: 2025.0.0)Spring Boot 4.0Java 21 (支持虚拟线程)响应式编程…Spring Cloud 2025.0.0 整合自定义日志注解完整教程本教程基于 Spring Cloud 2025.0.0 新特性包含虚拟线程、响应式编程、AOT 原生编译支持一、技术栈和架构1.1 技术选型Spring Cloud 2025.0.0(代号: 2025.0.0)Spring Boot 4.0Java 21(支持虚拟线程)响应式编程(WebFlux R2DBC)AOT 原生编译(GraalVM 23.0)分布式追踪(Micrometer Brave)日志收集(Logback ELK)1.2 架构图┌─────────────────────────────────────────────────────────┐ │ 自定义日志注解系统 │ ├─────────────────────────────────────────────────────────┤ │ Log注解 → 切面处理 → 日志上下文 → 异步存储 → 分布式追踪 │ │ ↑ ↑ ↑ ↑ ↑ │ │ 业务方法 虚拟线程 MDC/Reactor Elasticsearch Sleuth│ └─────────────────────────────────────────────────────────┘二、项目初始化2.1 父工程 pom.xml?xml version1.0 encodingUTF-8?projectxmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersionparentgroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-parent/artifactIdversion2025.0.0/versionrelativePath//parentgroupIdcom.example/groupIdartifactIdspring-cloud-logging/artifactIdversion1.0.0/versionpackagingpom/packagingmodulesmodulelogging-annotation/modulemodulelogging-starter/modulemoduleuser-service/modulemoduleorder-service/modulemodulegateway-service/module/modulespropertiesjava.version21/java.versionproject.build.sourceEncodingUTF-8/project.build.sourceEncodingproject.reporting.outputEncodingUTF-8/project.reporting.outputEncoding!-- Spring Cloud 版本 --spring-cloud.version2025.0.0/spring-cloud.versionspring-cloud-alibaba.version2025.0.0.0/spring-cloud-alibaba.version!-- 工具版本 --lombok.version1.18.30/lombok.versionmapstruct.version1.5.5.Final/mapstruct.versionguava.version33.0.0-jre/guava.version!-- 日志版本 --logstash-logback.version8.0/logstash-logback.versionmicrometer-tracing.version1.2.0/micrometer-tracing.version!-- GraalVM --graalvm.version23.0.0/graalvm.version/propertiesdependencyManagementdependencies!-- Spring Cloud --dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-dependencies/artifactIdversion${spring-cloud.version}/versiontypepom/typescopeimport/scope/dependency!-- Spring Cloud Alibaba --dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-alibaba-dependencies/artifactIdversion${spring-cloud-alibaba.version}/versiontypepom/typescopeimport/scope/dependency/dependencies/dependencyManagementbuildpluginManagementpluginsplugingroupIdorg.apache.maven.plugins/groupIdartifactIdmaven-compiler-plugin/artifactIdversion3.11.0/versionconfigurationsource21/sourcetarget21/targetannotationProcessorPathspathgroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdversion${lombok.version}/version/pathpathgroupIdorg.mapstruct/groupIdartifactIdmapstruct-processor/artifactIdversion${mapstruct.version}/version/path/annotationProcessorPaths/configuration/plugin!-- Spring Boot AOT Plugin --plugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactIdconfigurationimagebuilderpaketobuildpacks/builder-jammy-tiny:latest/builderenvBP_NATIVE_IMAGEtrue/BP_NATIVE_IMAGE/env/image/configuration/plugin!-- GraalVM Native Image Plugin --plugingroupIdorg.graalvm.buildtools/groupIdartifactIdnative-maven-plugin/artifactIdversion${graalvm.version}/version/plugin/plugins/pluginManagement/buildprofilesprofileidnative/idbuildpluginsplugingroupIdorg.graalvm.buildtools/groupIdartifactIdnative-maven-plugin/artifactIdexecutionsexecutionidbuild-native/idgoalsgoalcompile-no-fork/goal/goalsphasepackage/phase/execution/executions/plugin/plugins/build/profile/profiles/project三、日志注解模块 (logging-annotation)3.1 pom.xml?xml version1.0 encodingUTF-8?projectxmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsdparentgroupIdcom.example/groupIdartifactIdspring-cloud-logging/artifactIdversion1.0.0/version/parentmodelVersion4.0.0/modelVersionartifactIdlogging-annotation/artifactIddependencies!-- Spring Boot Starter --dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter/artifactId/dependency!-- AOP --dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-aop/artifactId/dependency!-- 响应式 --dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-webflux/artifactId/dependency!-- 分布式追踪 --dependencygroupIdio.micrometer/groupIdartifactIdmicrometer-tracing/artifactId/dependency!-- Lombok --dependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdoptionaltrue/optional/dependency/dependencies/project3.2 基础注解定义3.2.1 核心日志注解packagecom.example.logging.annotation;importorg.springframework.core.annotation.AliasFor;importjava.lang.annotation.*;importjava.util.concurrent.TimeUnit;/** * 自定义日志注解 * Spring Cloud 2025.0.0 新特性支持 */Target({ElementType.METHOD,ElementType.TYPE})Retention(RetentionPolicy.RUNTIME)DocumentedInheritedpublicinterfaceLoggable{/** * 模块名称 */Stringmodule()default;/** * 操作类型 */LogTypetype()defaultLogType.OTHER;/** * 操作描述 */AliasFor(value)Stringdescription()default;AliasFor(description)Stringvalue()default;/** * 是否记录方法参数 */booleanlogParams()defaulttrue;/** * 是否记录返回值 */booleanlogResult()defaulttrue;/** * 是否记录执行时间 */booleanlogTime()defaulttrue;/** * 慢查询阈值毫秒 */longslowThreshold()default1000;/** * 是否启用异步记录 */booleanasync()defaulttrue;/** * 异步记录策略 */AsyncStrategyasyncStrategy()defaultAsyncStrategy.VIRTUAL_THREAD;/** * 是否启用虚拟线程 */booleanvirtualThread()defaulttrue;/** * 日志级别 */LogLevellevel()defaultLogLevel.INFO;/** * 是否推送到日志中心 */booleanpushToCenter()defaulttrue;/** * 业务标识表达式SpEL */StringbizNo()default;/** * 是否记录堆栈信息 */booleanstackTrace()defaultfalse;/** * 日志分组 */Stringgroup()defaultdefault;/** * 操作类型枚举 */enumLogType{SELECT,// 查询INSERT,// 新增UPDATE,// 更新DELETE,// 删除IMPORT,// 导入EXPORT,// 导出LOGIN,// 登录LOGOUT,// 登出UPLOAD,// 上传DOWNLOAD,// 下载EXECUTE,// 执行CALL,// 调用OTHER// 其他}/** * 异步策略枚举 */enumAsyncStrategy{VIRTUAL_THREAD,// 虚拟线程THREAD_POOL,// 线程池REACTIVE,// 响应式IMMEDIATE// 立即执行}/** * 日志级别枚举 */enumLogLevel{TRACE,DEBUG,INFO,WARN,ERROR}}3.2.2 响应式日志注解packagecom.example.logging.annotation;importorg.springframework.core.annotation.AliasFor;importreactor.core.publisher.Flux;importreactor.core.publisher.Mono;importjava.lang.annotation.*;importjava.util.concurrent.CompletableFuture;/** * 响应式日志注解 * 支持 Reactive Streams */Target(ElementType.METHOD)Retention(RetentionPolicy.RUNTIME)DocumentedLoggablepublicinterfaceReactiveLog{/** * 是否跟踪响应式流 */booleantraceStream()defaultfalse;/** * 最大跟踪元素数量 */intmaxTraceElements()default10;/** * 响应式超时时间毫秒 */longtimeout()default30000;/** * 是否记录背压 */booleanlogBackpressure()defaultfalse;/** * 支持的类型 */Class?[]supportTypes()default{Mono.class,Flux.class,CompletableFuture.class};/** * 响应式操作类型 */ReactiveOperationoperation()defaultReactiveOperation.UNKNOWN;enumReactiveOperation{MONO_CREATE,MONO_TRANSFORM,MONO_DELAY,FLUX_STREAM,FLUX_WINDOW,FLUX_BUFFER,FUTURE_ASYNC,FUTURE_COMPLETABLE,UNKNOWN}}3.2.3 分布式追踪注解packagecom.example.logging.annotation;importorg.springframework.core.annotation.AliasFor;importjava.lang.annotation.*;/** * 分布式追踪注解 * 集成 Micrometer Tracing */Target(ElementType.METHOD)Retention(RetentionPolicy.RUNTIME)DocumentedLoggablepublicinterfaceTraceLog{/** * Span名称 */StringspanName()default;/** * 是否创建新Span */booleannewSpan()defaulttrue;/** * Span类型 */SpanKindkind()defaultSpanKind.INTERNAL;/** * 是否记录异常栈 */booleanlogStackTrace()defaulttrue;/** * 标签keyvalue格式 */String[]tags()default{};/** * 事件 */String[]events()default{};/** * 是否远程调用 */booleanremote()defaultfalse;/** * 远程服务名称 */StringremoteService()default;/** * Span类型枚举 */enumSpanKind{CLIENT,// 客户端SERVER,// 服务端PRODUCER,// 生产者CONSUMER,// 消费者INTERNAL// 内部调用}}3.2.4 性能监控注解packagecom.example.logging.annotation;importorg.springframework.core.annotation.AliasFor;importjava.lang.annotation.*;importjava.util.concurrent.TimeUnit;/** * 性能监控注解 * 集成 Micrometer Metrics */Target(ElementType.METHOD)Retention(RetentionPolicy.RUNTIME)DocumentedLoggablepublicinterfaceMetricLog{/** * 指标名称 */Stringname()default;/** * 指标描述 */Stringdescription()default;/** * 指标类型 */MetricTypetype()defaultMetricType.TIMER;/** * 是否记录分位数 */booleanpercentiles()defaulttrue;/** * 分位数值 */double[]percentileValues()default{0.5,0.95,0.99};/** * 是否记录直方图 */booleanhistogram()defaultfalse;/** * SLA配置毫秒 */long[]slas()default{10,50,100,500,1000};/** * 指标类型枚举 */enumMetricType{COUNTER,// 计数器TIMER,// 计时器GAUGE,// 仪表LONG_TASK_TIMER,// 长任务计时器DISTRIBUTION_SUMMARY// 分布摘要}}3.3 日志上下文3.3.1 日志上下文实体packagecom.example.logging.context;importlombok.Data;importlombok.experimental.Accessors;importorg.springframework.http.server.reactive.ServerHttpRequest;importorg.springframework.web.server.ServerWebExchange;importreactor.util.context.Context;importreactor.util.context.ContextView;importjava.io.Serializable;importjava.time.Duration;importjava.time.LocalDateTime;importjava.util.Map;importjava.util.concurrent.ConcurrentHashMap;importjava.util.concurrent.atomic.AtomicReference;/** * 日志上下文 * 支持虚拟线程和响应式编程 */DataAccessors(chaintrue)publicclassLogContextimplementsSerializable{privatestaticfinallongserialVersionUID1L;// 基本信息privateStringlogId;privateStringtraceId;privateStringspanId;privateStringparentSpanId;// 方法信息privateStringclassName;privateStringmethodName;privateStringsignature;// 业务信息privateStringmodule;privateStringoperation;privateStringdescription;privateStringbizNo;// 参数和结果privateObject[]args;privateObjectresult;privateThrowablethrowable;// 时间信息privateLocalDateTimestartTime;privateLocalDateTimeendTime;privateDurationduration;// 线程信息privateThreadInfothreadInfo;// 请求信息privateRequestInforequestInfo;// 扩展属性privateMapString,ObjectattributesnewConcurrentHashMap();// 响应式上下文privateReactiveContextreactiveContext;// 追踪信息privateTraceInfotraceInfo;/** * 创建日志上下文 */publicstaticLogContextcreate(){LogContextcontextnewLogContext();context.setLogId(generateLogId());context.setStartTime(LocalDateTime.now());context.setThreadInfo(ThreadInfo.capture());context.setTraceInfo(TraceInfo.capture());returncontext;}/** * 从ServerWebExchange创建 */publicstaticLogContextfromExchange(ServerWebExchangeexchange){LogContextcontextcreate();ServerHttpRequestrequestexchange.getRequest();RequestInforequestInfonewRequestInfo();requestInfo.setRequestId(request.getId());requestInfo.setMethod(request.getMethod().name());requestInfo.setUri(request.getURI().toString());requestInfo.setHeaders(newConcurrentHashMap(request.getHeaders().toSingleValueMap()));requestInfo.setQueryParams(newConcurrentHashMap(request.getQueryParams().toSingleValueMap()));requestInfo.setRemoteAddress(request.getRemoteAddress()!null?request.getRemoteAddress().getAddress().getHostAddress():);requestInfo.setUserAgent(request.getHeaders().getFirst(User-Agent));context.setRequestInfo(requestInfo);// 设置追踪信息StringtraceIdrequest.getHeaders().getFirst(X-B3-TraceId);StringspanIdrequest.getHeaders().getFirst(X-B3-SpanId);if(traceId!null){context.setTraceId(traceId);}if(spanId!null){context.setSpanId(spanId);}returncontext;}/** * 计算持续时间 */publicLogContextcalculateDuration(){if(startTime!null){this.endTimeLocalDateTime.now();this.durationDuration.between(startTime,endTime);}returnthis;}/** * 设置异常 */publicLogContextwithException(Throwablethrowable){this.throwablethrowable;returnthis;}/** * 设置结果 */publicLogContextwithResult(Objectresult){this.resultresult;returnthis;}/** * 设置响应式上下文 */publicLogContextwithReactiveContext(ContextViewcontextView){this.reactiveContextReactiveContext.from(contextView);returnthis;}/** * 添加属性 */publicLogContextaddAttribute(Stringkey,Objectvalue){this.attributes.put(key,value);returnthis;}/** * 生成日志ID */privatestaticStringgenerateLogId(){returnjava.util.UUID.randomUUID().toString().replace(-,);}/** * 线程信息 */DataAccessors(chaintrue)publicstaticclassThreadInfoimplementsSerializable{privatelongthreadId;privateStringthreadName;privatebooleanvirtual;privateThread.Statestate;privateintpriority;privatelongthreadGroupId;privateStringthreadGroupName;publicstaticThreadInfocapture(){ThreadthreadThread.currentThread();ThreadInfoinfonewThreadInfo();info.setThreadId(thread.threadId());info.setThreadName(thread.getName());info.setVirtual(thread.isVirtual());info.setState(thread.getState());info.setPriority(thread.getPriority());ThreadGroupgroupthread.getThreadGroup();if(group!null){info.setThreadGroupId(group.getId());info.setThreadGroupName(group.getName());}returninfo;}}/** * 请求信息 */DataAccessors(chaintrue)publicstaticclassRequestInfoimplementsSerializable{privateStringrequestId;privateStringmethod;privateStringuri;privateMapString,Stringheaders;privateMapString,StringqueryParams;privateStringremoteAddress;privateStringuserAgent;privateMapString,StringpathVariables;}/** * 响应式上下文 */DataAccessors(chaintrue)publicstaticclassReactiveContextimplementsSerializable{privateContextViewcontextView;privatebooleanonVirtualThread;privateStringscheduler;privatelongsubscriptionTime;privatelongrequestTime;publicstaticReactiveContextfrom(ContextViewcontextView){ReactiveContextcontextnewReactiveContext();context.setContextView(contextView);context.setOnVirtualThread(Thread.currentThread().isVirtual());context.setSubscriptionTime(System.currentTimeMillis());returncontext;}}/** * 追踪信息 */DataAccessors(chaintrue)publicstaticclassTraceInfoimplementsSerializable{privateStringtraceId;privateStringspanId;privateStringparentSpanId;privatebooleansampled;privateStringbaggage;publicstaticTraceInfocapture(){// 这里可以从MDC或ThreadLocal获取追踪信息TraceInfoinfonewTraceInfo();// 实际实现中会从Tracing API获取returninfo;}}}四、日志切面实现4.1 基础切面处理器packagecom.example.logging.aspect;importcom.example.logging.annotation.Loggable;importcom.example.logging.context.LogContext;importcom.example.logging.event.LogEvent;importcom.example.logging.service.LogService;importlombok.RequiredArgsConstructor;importlombok.extern.slf4j.Slf4j;importorg.aspectj.lang.ProceedingJoinPoint;importorg.aspectj.lang.annotation.Around;importorg.aspectj.lang.annotation.Aspect;importorg.aspectj.lang.annotation.Pointcut;importorg.aspectj.lang.reflect.MethodSignature;importorg.springframework.context.ApplicationEventPublisher;importorg.springframework.core.annotation.AnnotationUtils;importorg.springframework.expression.Expression;importorg.springframework.expression.ExpressionParser;importorg.springframework.expression.spel.standard.SpelExpressionParser;importorg.springframework.expression.spel.support.StandardEvaluationContext;importorg.springframework.stereotype.Component;importreactor.core.publisher.Flux;importreactor.core.publisher.Mono;importjava.lang.reflect.Method;importjava.time.Duration;importjava.time.Instant;importjava.util.concurrent.CompletableFuture;importjava.util.concurrent.Executors;importjava.util.concurrent.atomic.AtomicReference;/** * 日志切面处理器 * Spring Cloud 2025.0.0 新特性支持 */Slf4jAspectComponentRequiredArgsConstructorpublicclassLogAspectHandler{privatefinalApplicationEventPublishereventPublisher;privatefinalLogServicelogService;privatefinalLogExpressionEvaluatorexpressionEvaluator;// 虚拟线程执行器privatestaticfinaljava.util.concurrent.ExecutorServiceVIRTUAL_EXECUTORExecutors.newThreadPerTaskExecutor(Thread.ofVirtual().name(log-virtual-,0).factory());/** * 切入点所有Loggable注解的方法 */Pointcut(annotation(com.example.logging.annotation.Loggable))publicvoidloggablePointcut(){}/** * 环绕通知 */Around(loggablePointcut())publicObjecthandleLog(ProceedingJoinPointjoinPoint)throwsThrowable{MethodSignaturesignature(MethodSignature)joinPoint.getSignature();Methodmethodsignature.getMethod();// 获取注解配置LoggableloggableAnnotationUtils.findAnnotation(method,Loggable.class);if(loggablenull){returnjoinPoint.proceed();}// 创建日志上下文LogContextlogContextcreateLogContext(joinPoint,loggable);// 记录开始logStart(logContext,loggable);InstantstartTimeInstant.now();Objectresultnull;Throwablethrowablenull;try{// 执行目标方法resultjoinPoint.proceed();// 根据返回类型处理if(resultinstanceofMono){returnhandleMonoResult((Mono?)result,logContext,loggable,startTime);}elseif(resultinstanceofFlux){returnhandleFluxResult((Flux?)result,logContext,loggable,startTime);}elseif(resultinstanceofCompletableFuture){returnhandleFutureResult((CompletableFuture?)result,logContext,loggable,startTime);}returnresult;}catch(Throwablet){throwablet;throwt;}finally{// 处理同步结果handleSyncResult(result,throwable,logContext,loggable,startTime);}}/** * 创建日志上下文 */privateLogContextcreateLogContext(ProceedingJoinPointjoinPoint,Loggableloggable){MethodSignaturesignature(MethodSignature)joinPoint.getSignature();Methodmethodsignature.getMethod();LogContextcontextLogContext.create();context.setClassName(joinPoint.getTarget().getClass().getName());context.setMethodName(method.getName());context.setSignature(signature.toString());context.setModule(loggable.module());context.setOperation(loggable.value());context.setDescription(loggable.description());// 解析业务编号if(!loggable.bizNo().isEmpty()){StringbizNoexpressionEvaluator.evaluateBizNo(joinPoint,loggable.bizNo());context.setBizNo(bizNo);}// 记录参数if(loggable.logParams()){context.setArgs(joinPoint.getArgs());}returncontext;}/** * 处理Mono结果 */privateMono?handleMonoResult(Mono?mono,LogContextlogContext,Loggableloggable,InstantstartTime){AtomicReferenceInstantsubscribeTimenewAtomicReference(Instant.now());returnmono.contextWrite(ctx-{// 在Reactor Context中存储日志信息returnctx.put(log.context,logContext).put(log.startTime,startTime).put(log.subscribeTime,subscribeTime.get());}).doOnSubscribe(subscription-{subscribeTime.set(Instant.now());if(loggable.async()){VIRTUAL_EXECUTOR.submit(()-logService.logAsyncStart(logContext));}else{logService.logSyncStart(logContext);}}).doOnSuccess(result-{DurationdurationDuration.between(startTime,Instant.now());logContext.withResult(result).calculateDuration();if(loggable.async()){VIRTUAL_EXECUTOR.submit(()-logService.logAsyncSuccess(logContext,duration));}else{logService.logSyncSuccess(logContext,duration);}// 检查慢查询if(duration.toMillis()loggable.slowThreshold()){logService.logSlowQuery(logContext,duration,loggable.slowThreshold());}// 发布事件if(loggable.pushToCenter()){eventPublisher.publishEvent(newLogEvent(logContext,loggable));}}).doOnError(throwable-{DurationdurationDuration.between(startTime,Instant.now());logContext.withException(throwable).calculateDuration();if(loggable.async()){VIRTUAL_EXECUTOR.submit(()-logService.logAsyncError(logContext,duration,throwable));}else{logService.logSyncError(logContext,duration,throwable);}// 发布事件if(loggable.pushToCenter()){eventPublisher.publishEvent(newLogEvent(logContext,loggable));}}).doOnCancel(()-{DurationdurationDuration.between(startTime,Instant.now());if(loggable.async()){VIRTUAL_EXECUTOR.submit(()-logService.logAsyncCancel(logContext,duration));}});}/** * 处理Flux结果 */privateFlux?handleFluxResult(Flux?flux,LogContextlogContext,Loggableloggable,InstantstartTime){AtomicReferenceInstantsubscribeTimenewAtomicReference(Instant.now());AtomicReferenceIntegerelementCountnewAtomicReference(0);returnflux.contextWrite(ctx-{returnctx.put(log.context,logContext).put(log.startTime,startTime);}).doOnSubscribe(subscription-{subscribeTime.set(Instant.now());if(loggable.async()){VIRTUAL_EXECUTOR.submit(()-logService.logAsyncStart(logContext));}}).doOnNext(element-{intcountelementCount.updateAndGet(c-c1);if(loggable.async()count10){VIRTUAL_EXECUTOR.submit(()-logService.logAsyncElement(logContext,element,count));}}).doOnComplete(()-{DurationdurationDuration.between(startTime,Instant.now());logContext.calculateDuration();if(loggable.async()){VIRTUAL_EXECUTOR.submit(()-logService.logAsyncComplete(logContext,duration,elementCount.get()));}// 发布事件if(loggable.pushToCenter()){eventPublisher.publishEvent(newLogEvent(logContext,loggable));}}).doOnError(throwable-{DurationdurationDuration.between(startTime,Instant.now());logContext.withException(throwable).calculateDuration();if(loggable.async()){VIRTUAL_EXECUTOR.submit(()-logService.logAsyncError(logContext,duration,throwable));}else{logService.logSyncError(logContext,duration,throwable);}// 发布事件if(loggable.pushToCenter()){eventPublisher.publishEvent(newLogEvent(logContext,loggable));}});}/** * 处理Future结果 */privateCompletableFuture?handleFutureResult(CompletableFuture?future,LogContextlogContext,Loggableloggable,InstantstartTime){if(loggable.async()){VIRTUAL_EXECUTOR.submit(()-logService.logAsyncStart(logContext));}else{logService.logSyncStart(logContext);}returnfuture.whenComplete((result,throwable)-{DurationdurationDuration.between(startTime,Instant.now());if(throwable!null){logContext.withException(throwable).calculateDuration();if(loggable.async()){VIRTUAL_EXECUTOR.submit(()-logService.logAsyncError(logContext,duration,throwable));}else{logService.logSyncError(logContext,duration,throwable);}}else{logContext.withResult(result).calculateDuration();if(loggable.async()){VIRTUAL_EXECUTOR.submit(()-logService.logAsyncSuccess(logContext,duration));}else{logService.logSyncSuccess(logContext,duration);}// 检查慢查询if(duration.toMillis()loggable.slowThreshold()){logService.logSlowQuery(logContext,duration,loggable.slowThreshold());}}// 发布事件if(loggable.pushToCenter()){eventPublisher.publishEvent(newLogEvent(logContext,loggable));}});}/** * 处理同步结果 */privatevoidhandleSyncResult(Objectresult,Throwablethrowable,LogContextlogContext,Loggableloggable,InstantstartTime){DurationdurationDuration.between(startTime,Instant.now());logContext.calculateDuration();if(throwable!null){logContext.withException(throwable);if(loggable.async()){VIRTUAL_EXECUTOR.submit(()-logService.logAsyncError(logContext,duration,throwable));}else{logService.logSyncError(logContext,duration,throwable);}}else{logContext.withResult(result);if(loggable.async()){VIRTUAL_EXECUTOR.submit(()-logService.logAsyncSuccess(logContext,duration));}else{logService.logSyncSuccess(logContext,duration);}// 检查慢查询if(duration.toMillis()loggable.slowThreshold()){logService.logSlowQuery(logContext,duration,loggable.slowThreshold());}}// 发布事件if(loggable.pushToCenter()){eventPublisher.publishEvent(newLogEvent(logContext,loggable));}}/** * 记录开始日志 */privatevoidlogStart(LogContextcontext,Loggableloggable){switch(loggable.level()){caseTRACE:log.trace(【开始】{} - {}#{} [线程:{}],context.getOperation(),context.getClassName(),context.getMethodName(),Thread.currentThread().getName());break;caseDEBUG:log.debug(【开始】{} - {}#{},context.getOperation(),context.getClassName(),context.getMethodName());break;caseINFO:log.info(【开始】{} - {}#{},context.getOperation(),context.getClassName(),context.getMethodName());break;caseWARN:caseERROR:// 不记录开始日志break;}}}4.2 响应式切面处理器packagecom.example.logging.aspect;importcom.example.logging.annotation.ReactiveLog;importcom.example.logging.context.LogContext;importlombok.RequiredArgsConstructor;importlombok.extern.slf4j.Slf4j;importorg.aspectj.lang.ProceedingJoinPoint;importorg.aspectj.lang.annotation.Around;importorg.aspectj.lang.annotation.Aspect;importorg.aspectj.lang.reflect.MethodSignature;importorg.springframework.core.annotation.AnnotationUtils;importorg.springframework.stereotype.Component;importreactor.core.publisher.Flux;importreactor.core.publisher.Mono;importreactor.core.scheduler.Schedulers;importjava.lang.reflect.Method;importjava.time.Duration;importjava.time.Instant;importjava.util.concurrent.atomic.AtomicInteger;importjava.util.concurrent.atomic.AtomicLong;/** * 响应式日志切面 * Spring Cloud 2025.0.0 响应式增强 */Slf4jAspectComponentRequiredArgsConstructorpublicclassReactiveLogAspect{/** * 处理响应式日志 */Around(annotation(com.example.logging.annotation.ReactiveLog))publicObjecthandleReactiveLog(ProceedingJoinPointjoinPoint)throwsThrowable{MethodSignaturesignature(MethodSignature)joinPoint.getSignature();Methodmethodsignature.getMethod();ReactiveLogreactiveLogAnnotationUtils.findAnnotation(method,ReactiveLog.class);if(reactiveLognull){returnjoinPoint.proceed();}// 创建日志上下文LogContextlogContextLogContext.create();logContext.setClassName(joinPoint.getTarget().getClass().getName());logContext.setMethodName(method.getName());ObjectresultjoinPoint.proceed();if(resultinstanceofMono){returnwrapMono((Mono?)result,logContext,reactiveLog);}elseif(resultinstanceofFlux){returnwrapFlux((Flux?)result,logContext,reactiveLog);}returnresult;}/** * 包装Mono */privateMono?wrapMono(Mono?mono,LogContextcontext,ReactiveLogreactiveLog){AtomicLongsubscribeTimenewAtomicLong();AtomicLongrequestTimenewAtomicLong();returnmono.doOnSubscribe(subscription-{subscribeTime.set(System.currentTimeMillis());logReactiveStart(context,MONO,reactiveLog);}).doOnRequest(n-{requestTime.set(System.currentTimeMillis());if(reactiveLog.logBackpressure()){log.debug(【MONO】请求元素: {},n);}}).doOnNext(value-{longprocessTimeSystem.currentTimeMillis()-requestTime.get();if(reactiveLog.traceStream()){log.debug(【MONO】处理元素: {}, 耗时: {}ms,value,processTime);}}).doOnSuccess(value-{longtotalTimeSystem.currentTimeMillis()-subscribeTime.get();logReactiveSuccess(context,MONO,value,totalTime,reactiveLog);}).doOnError(throwable-{longtotalTimeSystem.currentTimeMillis()-subscribeTime.get();logReactiveError(context,MONO,throwable,totalTime,reactiveLog);}).timeout(Duration.ofMillis(reactiveLog.timeout())).onErrorResume(throwable-{log.error(【MONO】响应式超时: {}ms,reactiveLog.timeout(),throwable);returnMono.error(throwable);}).doFinally(signalType-{if(reactiveLog.traceStream()){log.debug(【MONO】最终信号: {},signalType);}});}/** * 包装Flux */privateFlux?wrapFlux(Flux?flux,LogContextcontext,ReactiveLogreactiveLog){AtomicLongsubscribeTimenewAtomicLong();AtomicIntegerelementCountnewAtomicInteger(0);AtomicLongtotalElementsnewAtomicLong(0);returnflux.doOnSubscribe(subscription-{subscribeTime.set(System.currentTimeMillis());logReactiveStart(context,FLUX,reactiveLog);}).doOnRequest(n-{if(reactiveLog.logBackpressure()){log.debug(【FLUX】请求元素: {},n);}}).doOnNext(element-{intcountelementCount.incrementAndGet();totalElements.incrementAndGet();if(reactiveLog.traceStream()countreactiveLog.maxTraceElements()){log.debug(【FLUX】元素[{}]: {},count,element);}}).doOnComplete(()-{longtotalTimeSystem.currentTimeMillis()-subscribeTime.get();logReactiveComplete(context,FLUX,elementCount.get(),totalTime,reactiveLog);}).doOnError(throwable-{longtotalTimeSystem.currentTimeMillis()-subscribeTime.get();logReactiveError(context,FLUX,throwable,totalTime,reactiveLog);}).timeout(Duration.ofMillis(reactiveLog.timeout())).onErrorResume(throwable-{log.error(【FLUX】响应式超时: {}ms,reactiveLog.timeout(),throwable);returnFlux.error(throwable);}).doFinally(signalType-{if(reactiveLog.traceStream()){log.debug(【FLUX】最终信号: {}, 总元素: {},signalType,totalElements.get());}});}privatevoidlogReactiveStart(LogContextcontext,Stringtype,ReactiveLogreactiveLog){log.info(【响应式{}】开始 - {}#{} [线程:{}],type,context.getClassName(),context.getMethodName(),Thread.currentThread().getName());}privatevoidlogReactiveSuccess(LogContextcontext,Stringtype,Objectvalue,longtotalTime,ReactiveLogreactiveLog){log.info(【响应式{}】成功 - {}#{}, 结果: {}, 耗时: {}ms,type,context.getClassName(),context.getMethodName(),value!null?value.toString():null,totalTime);}privatevoidlogReactiveComplete(LogContextcontext,Stringtype,intelementCount,longtotalTime,ReactiveLogreactiveLog){log.info(【响应式{}】完成 - {}#{}, 元素数: {}, 耗时: {}ms,type,context.getClassName(),context.getMethodName(),elementCount,totalTime);}privatevoidlogReactiveError(LogContextcontext,Stringtype,Throwablethrowable,longtotalTime,ReactiveLogreactiveLog){log.error(【响应式{}】失败 - {}#{}, 耗时: {}ms, 错误: {},type,context.getClassName(),context.getMethodName(),totalTime,throwable.getMessage(),throwable);}}五、日志服务实现5.1 日志服务接口packagecom.example.logging.service;importcom.example.logging.context.LogContext;importreactor.core.publisher.Mono;importjava.time.Duration;/** * 日志服务接口 */publicinterfaceLogService{// 同步日志voidlogSyncStart(LogContextcontext);voidlogSyncSuccess(LogContextcontext,Durationduration);voidlogSyncError(LogContextcontext,Durationduration,Throwablethrowable);// 异步日志voidlogAsyncStart(LogContextcontext);voidlogAsyncSuccess(LogContextcontext,Durationduration);voidlogAsyncError(LogContextcontext,Durationduration,Throwablethrowable);voidlogAsyncCancel(LogContextcontext,Durationduration);voidlogAsyncComplete(LogContextcontext,Durationduration,intelementCount);voidlogAsyncElement(LogContextcontext,Objectelement,intindex);// 慢查询日志voidlogSlowQuery(LogContextcontext,Durationduration,longthreshold);// 虚拟线程日志voidlogVirtualThreadMetrics();// 响应式日志MonoVoidlogReactiveStart(LogContextcontext);MonoVoidlogReactiveSuccess(LogContextcontext,Durationduration);MonoVoidlogReactiveError(LogContextcontext,Durationduration,Throwablethrowable);}5.2 日志服务实现packagecom.example.logging.service.impl;importcom.example.logging.context.LogContext;importcom.example.logging.service.LogService;importio.micrometer.core.instrument.MeterRegistry;importio.micrometer.core.instrument.Timer;importlombok.RequiredArgsConstructor;importlombok.extern.slf4j.Slf4j;importorg.springframework.beans.factory.ObjectProvider;importorg.springframework.cloud.sleuth.Tracer;importorg.springframework.stereotype.Service;importreactor.core.publisher.Mono;importreactor.core.scheduler.Schedulers;importjava.time.Duration;importjava.util.Map;importjava.util.concurrent.ConcurrentHashMap;importjava.util.concurrent.Executors;importjava.util.concurrent.TimeUnit;importjava.util.concurrent.atomic.AtomicInteger;importjava.util.concurrent.atomic.AtomicLong;/** * 日志服务实现 * 集成分布式追踪和性能指标 */Slf4jServiceRequiredArgsConstructorpublicclassDefaultLogServiceImplimplementsLogService{privatefinalMeterRegistrymeterRegistry;privatefinalObjectProviderTracertracerProvider;// 虚拟线程执行器privatefinaljava.util.concurrent.ExecutorServicevirtualExecutorExecutors.newThreadPerTaskExecutor(Thread.ofVirtual().name(log-virtual-,0).factory());// 统计信息privatefinalAtomicLongtotalLogsnewAtomicLong(0);privatefinalAtomicLongerrorLogsnewAtomicLong(0);privatefinalAtomicLongslowLogsnewAtomicLong(0);privatefinalAtomicIntegervirtualThreadCountnewAtomicInteger(0);// 计时器缓存privatefinalMapString,TimertimerCachenewConcurrentHashMap();OverridepublicvoidlogSyncStart(LogContextcontext){totalLogs.incrementAndGet();log.debug(【同步开始】{} - {}#{} [追踪ID:{}],context.getOperation(),context.getClassName(),context.getMethodName(),getTraceId());// 记录指标meterRegistry.counter(log.sync.start,module,context.getModule(),operation,context.getOperation()).increment();}OverridepublicvoidlogSyncSuccess(LogContextcontext,Durationduration){log.info(【同步成功】{} - {}#{}, 耗时: {}ms [追踪ID:{}],context.getOperation(),context.getClassName(),context.getMethodName(),duration.toMillis(),getTraceId());// 记录计时指标TimertimergetOrCreateTimer(context.getModule(),context.getOperation());timer.record(duration);// 记录成功率meterRegistry.counter(log.sync.success,module,context.getModule()).increment();}OverridepublicvoidlogSyncError(LogContextcontext,Durationduration,Throwablethrowable){errorLogs.incrementAndGet();log.error(【同步失败】{} - {}#{}, 耗时: {}ms, 错误: {} [追踪ID:{}],context.getOperation(),context.getClassName(),context.getMethodName(),duration.toMillis(),throwable.getMessage(),getTraceId(),throwable);// 记录错误指标meterRegistry.counter(log.sync.error,module,context.getModule(),exception,throwable.getClass().getSimpleName()).increment();}OverridepublicvoidlogAsyncStart(LogContextcontext){virtualExecutor.submit(()-{try{totalLogs.incrementAndGet();virtualThreadCount.incrementAndGet();log.debug(【异步开始】{} - {}#{} [虚拟线程:{}, 追踪ID:{}],context.getOperation(),context.getClassName(),context.getMethodName(),Thread.currentThread().threadId(),getTraceId());// 记录虚拟线程指标meterRegistry.gauge(log.virtual.thread.count,virtualThreadCount);meterRegistry.counter(log.async.start,module,context.getModule()).increment();}catch(Exceptione){log.error(异步开始日志记录失败,e);}});}OverridepublicvoidlogAsyncSuccess(LogContextcontext,Durationduration){virtualExecutor.submit(()-{try{log.info(【异步成功】{} - {}#{}, 耗时: {}ms [虚拟线程:{}, 追踪ID:{}],context.getOperation(),context.getClassName(),context.getMethodName(),duration.toMillis(),Thread.currentThread().threadId(),getTraceId());// 记录计时指标TimertimergetOrCreateTimer(context.getModule(),context.getOperation());timer.record(duration);// 记录成功率meterRegistry.counter(log.async.success,module,context.getModule()).increment();}catch(Exceptione){log.error(异步成功日志记录失败,e);}finally{virtualThreadCount.decrementAndGet();}});}OverridepublicvoidlogAsyncError(LogContextcontext,Durationduration,Throwablethrowable){virtualExecutor.submit(()-{try{errorLogs.incrementAndGet();log.error(【异步失败】{} - {}#{}, 耗时: {}ms, 错误: {} [虚拟线程:{}, 追踪ID:{}],context.getOperation(),context.getClassName(),context.getMethodName(),duration.toMillis(),throwable.getMessage(),Thread.currentThread().threadId(),getTraceId(),throwable);// 记录错误指标meterRegistry.counter(log.async.error,module,context.getModule(),exception,throwable.getClass().getSimpleName()).increment();}catch(Exceptione){log.error(异步错误日志记录失败,e);}finally{virtualThreadCount.decrementAndGet();}});}OverridepublicvoidlogAsyncCancel(LogContextcontext,Durationduration){virtualExecutor.submit(()-{try{log.warn(【异步取消】{} - {}#{}, 耗时: {}ms [虚拟线程:{}],context.getOperation(),context.getClassName(),context.getMethodName(),duration.toMillis(),Thread.currentThread().threadId());meterRegistry.counter(log.async.cancel,module,context.getModule()).increment();}catch(Exceptione){log.error(异步取消日志记录失败,e);}finally{virtualThreadCount.decrementAndGet();}});}OverridepublicvoidlogAsyncComplete(LogContextcontext,Durationduration,intelementCount){virtualExecutor.submit(()-{try{log.info(【异步完成】{} - {}#{}, 元素数: {}, 耗时: {}ms [虚拟线程:{}],context.getOperation(),context.getClassName(),context.getMethodName(),elementCount,duration.toMillis(),Thread.currentThread().threadId());meterRegistry.counter(log.async.complete,module,context.getModule(),elementCount,String.valueOf(elementCount)).increment();}catch(Exceptione){log.error(异步完成日志记录失败,e);}finally{virtualThreadCount.decrementAndGet();}});}OverridepublicvoidlogAsyncElement(LogContextcontext,Objectelement,intindex){virtualExecutor.submit(()-{try{if(index10){// 只记录前10个元素log.debug(【异步元素】{} - {}#{}, 元素[{}]: {} [虚拟线程:{}],context.getOperation(),context.getClassName(),context.getMethodName(),index,element!null?element.toString():null,Thread.currentThread().threadId());}}catch(Exceptione){// 忽略元素记录错误}});}OverridepublicvoidlogSlowQuery(LogContextcontext,Durationduration,longthreshold){slowLogs.incrementAndGet();virtualExecutor.submit(()-{try{log.warn(【慢查询】{} - {}#{}, 耗时: {}ms, 阈值: {}ms [追踪ID:{}],context.getOperation(),context.getClassName(),context.getMethodName(),duration.toMillis(),threshold,getTraceId());// 记录慢查询指标meterRegistry.counter(log.slow.query,module,context.getModule(),duration,String.valueOf(duration.toMillis()),threshold,String.valueOf(threshold)).increment();}catch(Exceptione){log.error(慢查询日志记录失败,e);}});}OverridepublicvoidlogVirtualThreadMetrics(){virtualExecutor.submit(()-{try{intcountvirtualThreadCount.get();intactiveThreadsThread.activeCount();log.debug(【虚拟线程统计】活跃虚拟线程: {}, 总线程: {}, 总日志: {}, 错误日志: {}, 慢查询: {},count,activeThreads,totalLogs.get(),errorLogs.get(),slowLogs.get());// 记录到指标meterRegistry.gauge(log.metrics.total,totalLogs);meterRegistry.gauge(log.metrics.errors,errorLogs);meterRegistry.gauge(log.metrics.slow,slowLogs);}catch(Exceptione){log.error(虚拟线程指标记录失败,e);}});}OverridepublicMonoVoidlogReactiveStart(LogContextcontext){returnMono.fromRunnable(()-{log.debug(【响应式开始】{} - {}#{},context.getOperation(),context.getClassName(),context.getMethodName());}).subscribeOn(Schedulers.boundedElastic()).then();}OverridepublicMonoVoidlogReactiveSuccess(LogContextcontext,Durationduration){returnMono.fromRunnable(()-{log.info(【响应式成功】{} - {}#{}, 耗时: {}ms,context.getOperation(),context.getClassName(),context.getMethodName(),duration.toMillis());}).subscribeOn(Schedulers.boundedElastic()).then();}OverridepublicMonoVoidlogReactiveError(LogContextcontext,Durationduration,Throwablethrowable){returnMono.fromRunnable(()-{log.error(【响应式失败】{} - {}#{}, 耗时: {}ms, 错误: {},context.getOperation(),context.getClassName(),context.getMethodName(),duration.toMillis(),throwable.getMessage(),throwable);}).subscribeOn(Schedulers.boundedElastic()).then();}/** * 获取或创建计时器 */privateTimergetOrCreateTimer(Stringmodule,Stringoperation){Stringkeymodule.operation;returntimerCache.computeIfAbsent(key,k-Timer.builder(log.execution.time).description(Method execution time).tag(module,module).tag(operation,operation).publishPercentiles(0.5,0.95,0.99).publishPercentileHistogram().register(meterRegistry));}/** * 获取追踪ID */privateStringgetTraceId(){try{TracertracertracerProvider.getIfAvailable();if(tracer!nulltracer.currentSpan()!null){returntracer.currentSpan().context().traceId();}}catch(Exceptione){// 忽略异常}returnN/A;}/** * 关闭资源 */publicvoidshutdown(){virtualExecutor.shutdown();try{if(!virtualExecutor.awaitTermination(5,TimeUnit.SECONDS)){virtualExecutor.shutdownNow();}}catch(InterruptedExceptione){virtualExecutor.shutdownNow();Thread.currentThread().interrupt();}log.info(日志服务关闭完成);}}六、日志自动配置6.1 自动配置类packagecom.example.logging.autoconfigure;importcom.example.logging.aspect.LogAspectHandler;importcom.example.logging.aspect.ReactiveLogAspect;importcom.example.logging.service.LogService;importcom.example.logging.service.impl.DefaultLogServiceImpl;importlombok.extern.slf4j.Slf4j;importorg.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;importorg.springframework.boot.autoconfigure.condition.ConditionalOnProperty;importorg.springframework.boot.context.properties.EnableConfigurationProperties;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.context.annotation.EnableAspectJAutoProxy;importorg.springframework.scheduling.annotation.EnableAsync;importorg.springframework.scheduling.annotation.EnableScheduling;importjava.util.concurrent.Executors;/** * 日志自动配置 */Slf4jConfigurationEnableAspectJAutoProxyEnableAsyncEnableSchedulingEnableConfigurationProperties(LogProperties.class)ConditionalOnProperty(prefixspring.logging,nameenabled,havingValuetrue,matchIfMissingtrue)publicclassLogAutoConfiguration{/** * 日志切面处理器 */BeanConditionalOnMissingBeanpublicLogAspectHandlerlogAspectHandler(){returnnewLogAspectHandler();}/** * 响应式日志切面 */BeanConditionalOnMissingBeanpublicReactiveLogAspectreactiveLogAspect(){returnnewReactiveLogAspect();}/** * 日志服务 */BeanConditionalOnMissingBeanpublicLogServicelogService(){returnnewDefaultLogServiceImpl();}/** * 虚拟线程执行器 */Bean(destroyMethodshutdown)publicjava.util.concurrent.ExecutorServicevirtualThreadExecutor(){returnExecutors.newThreadPerTaskExecutor(Thread.ofVirtual().name(global-virtual-,0).factory());}/** * 日志指标调度器 */BeanpublicLogMetricsSchedulerlogMetricsScheduler(LogServicelogService){returnnewLogMetricsScheduler(logService);}}6.2 配置属性packagecom.example.logging.autoconfigure;importlombok.Data;importorg.springframework.boot.context.properties.ConfigurationProperties;importjava.time.Duration;importjava.util.HashMap;importjava.util.Map;/** * 日志配置属性 */DataConfigurationProperties(prefixspring.logging)publicclassLogProperties{/** * 是否启用日志功能 */privatebooleanenabledtrue;/** * 是否启用异步日志 */privatebooleanasyncEnabledtrue;/** * 是否启用虚拟线程 */privatebooleanvirtualThreadEnabledtrue;/** * 是否启用响应式日志 */privatebooleanreactiveEnabledtrue;/** * 默认日志级别 */privateStringdefaultLevelINFO;/** * 慢查询阈值毫秒 */privatelongslowThreshold1000;/** * 是否记录方法参数 */privatebooleanlogParamstrue;/** * 是否记录返回值 */privatebooleanlogResulttrue;/** * 是否记录执行时间 */privatebooleanlogTimetrue;/** * 是否推送到日志中心 */privatebooleanpushToCentertrue;/** * 日志中心地址 */privateStringcenterUrlhttp://localhost:8080;/** * 连接超时时间 */privateDurationconnectTimeoutDuration.ofSeconds(5);/** * 读取超时时间 */privateDurationreadTimeoutDuration.ofSeconds(10);/** * 重试次数 */privateintretryTimes3;/** * 批量发送大小 */privateintbatchSize100;/** * 批量发送间隔 */privateDurationbatchIntervalDuration.ofSeconds(5);/** * 模块配置 */privateMapString,ModuleConfigmodulesnewHashMap();DatapublicstaticclassModuleConfig{privatebooleanenabledtrue;privateStringlevelINFO;privatebooleanasynctrue;privatebooleanvirtualThreadtrue;privatebooleanlogParamstrue;privatebooleanlogResulttrue;privatelongslowThreshold1000;}}七、日志 Starter 模块7.1 pom.xml?xml version1.0 encodingUTF-8?projectxmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsdparentgroupIdcom.example/groupIdartifactIdspring-cloud-logging/artifactIdversion1.0.0/version/parentmodelVersion4.0.0/modelVersionartifactIdlogging-starter/artifactIddependencies!-- 内部模块依赖 --dependencygroupIdcom.example/groupIdartifactIdlogging-annotation/artifactIdversion${project.version}/version/dependency!-- Spring Boot Starter --dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter/artifactId/dependency!-- AOP --dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-aop/artifactId/dependency!-- 配置处理器 --dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-configuration-processor/artifactIdoptionaltrue/optional/dependency!-- Micrometer 追踪 --dependencygroupIdio.micrometer/groupIdartifactIdmicrometer-tracing/artifactId/dependency!-- Micrometer 指标 --dependencygroupIdio.micrometer/groupIdartifactIdmicrometer-core/artifactId/dependency!-- Reactor --dependencygroupIdio.projectreactor/groupIdartifactIdreactor-core/artifactId/dependency/dependencies/project7.2 spring.factories# Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration\ com.example.logging.autoconfigure.LogAutoConfiguration # Spring Boot Configuration Processor org.springframework.boot.autoconfigure.EnableAutoConfiguration\ com.example.logging.autoconfigure.LogPropertiesConfiguration八、使用示例8.1 用户服务示例packagecom.example.user.service;importcom.example.logging.annotation.Loggable;importcom.example.logging.annotation.ReactiveLog;importcom.example.logging.annotation.TraceLog;importlombok.RequiredArgsConstructor;importlombok.extern.slf4j.Slf4j;importorg.springframework.stereotype.Service;importorg.springframework.transaction.annotation.Transactional;importreactor.core.publisher.Flux;importreactor.core.publisher.Mono;importjava.util.List;importjava.util.concurrent.CompletableFuture;importjava.util.concurrent.Executors;/** * 用户服务示例 */Slf4jServiceRequiredArgsConstructorpublicclassUserService{/** * 同步方法日志 */Loggable(module用户管理,value创建用户,typeLoggable.LogType.INSERT,bizNo#user.username)TransactionalpublicUsercreateUser(Useruser){// 业务逻辑returnuserRepository.save(user);}/** * 异步方法日志 */Loggable(module用户管理,value批量导入用户,asynctrue,virtualThreadtrue,slowThreshold5000)publicCompletableFutureListUserbatchImport(ListUserusers){returnCompletableFuture.supplyAsync(()-{// 批量处理逻辑returnuserRepository.saveAll(users);},Executors.newVirtualThreadPerTaskExecutor());}/** * 响应式方法日志 */ReactiveLog(traceStreamtrue,maxTraceElements20,timeout30000)Loggable(module用户管理,value查询用户列表,asynctrue)publicFluxUserlistUsers(intpage,intsize){returnuserRepository.findAll().skip(page*size).take(size).doOnNext(user-log.debug(处理用户: {},user.getUsername()));}/** * 分布式追踪日志 */TraceLog(spanNameuser.update,tags{userId#userId,operationupdate},remotefalse)Loggable(module用户管理,value更新用户信息,levelLoggable.LogLevel.INFO)publicMonoUserupdateUser(LonguserId,UserDTOdto){returnuserRepository.findById(userId).flatMap(user-{user.setEmail(dto.getEmail());user.setPhone(dto.getPhone());returnuserRepository.save(user);});}/** * 错误处理示例 */Loggable(module用户管理,value删除用户,levelLoggable.LogLevel.ERROR,stackTracetrue)publicvoiddeleteUser(LonguserId){try{userRepository.deleteById(userId);}catch(Exceptione){log.error(删除用户失败: {},userId,e);thrownewBusinessException(删除用户失败);}}/** * 虚拟线程示例 */Loggable(module用户管理,value并发处理用户,asynctrue,virtualThreadtrue,asyncStrategyLoggable.AsyncStrategy.VIRTUAL_THREAD)publicvoidprocessUsersConcurrently(ListLonguserIds){try(varscopenewjava.util.concurrent.StructuredTaskScope.ShutdownOnFailure()){for(LonguserId:userIds){scope.fork(()-processUser(userId));}scope.join();}catch(InterruptedExceptione){Thread.currentThread().interrupt();thrownewRuntimeException(处理中断,e);}}privateUserprocessUser(LonguserId){// 处理单个用户returnuserRepository.findById(userId).map(user-{// 业务处理returnuser;}).orElseThrow(()-newRuntimeException(用户不存在));}}九、配置示例9.1 application.ymlspring:application:name:user-service# 日志配置logging:enabled:trueasync-enabled:truevirtual-thread-enabled:truereactive-enabled:truedefault-level:INFOslow-threshold:1000log-params:truelog-result:truepush-to-center:truecenter-url:http://log-center:8080# 模块配置modules:user-service:enabled:truelevel:INFOasync:truevirtual-thread:trueslow-threshold:500order-service:enabled:truelevel:DEBUGasync:false# 虚拟线程配置threads:virtual:enabled:truename-prefix:app-virtual-# 响应式配置webflux:base-path:/api# 分布式追踪sleuth:enabled:truesampler:probability:1.0propagation:type:B3baggage:enabled:true# Micrometermicrometer:tracing:enabled:truemetrics:export:prometheus:enabled:true# 日志级别配置logging:level:com.example:INFOcom.example.logging:DEBUGorg.springframework.web:INFOreactor.netty:INFOpattern:console:%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%nfile:%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n# Logback配置logback:rollingpolicy:max-file-size:10MBmax-history:30total-size-cap:1GB# Logstashlogstash:enabled:truedestination:logstash:5044# 管理端点management:endpoints:web:exposure:include:health,info,metrics,prometheus,loggersendpoint:health:show-details:alwaysloggers:enabled:truemetrics:tags:application:${spring.application.name}tracing:sampling:probability:0.1十、网关集成十一、Spring Cloud Gateway 集成11.1 网关全局过滤器packagecom.example.gateway.filter;importcom.example.logging.annotation.Loggable;importcom.example.logging.context.LogContext;importio.micrometer.tracing.Span;importio.micrometer.tracing.Tracer;importlombok.RequiredArgsConstructor;importlombok.extern.slf4j.Slf4j;importorg.springframework.cloud.gateway.filter.GatewayFilterChain;importorg.springframework.cloud.gateway.filter.GlobalFilter;importorg.springframework.cloud.gateway.route.Route;importorg.springframework.cloud.gateway.support.ServerWebExchangeUtils;importorg.springframework.core.Ordered;importorg.springframework.core.io.buffer.DataBuffer;importorg.springframework.core.io.buffer.DataBufferFactory;importorg.springframework.core.io.buffer.DataBufferUtils;importorg.springframework.http.HttpHeaders;importorg.springframework.http.MediaType;importorg.springframework.http.server.reactive.ServerHttpRequest;importorg.springframework.http.server.reactive.ServerHttpRequestDecorator;importorg.springframework.http.server.reactive.ServerHttpResponse;importorg.springframework.http.server.reactive.ServerHttpResponseDecorator;importorg.springframework.stereotype.Component;importorg.springframework.web.server.ServerWebExchange;importreactor.core.publisher.Flux;importreactor.core.publisher.Mono;importjava.net.InetSocketAddress;importjava.net.URI;importjava.nio.charset.StandardCharsets;importjava.time.Duration;importjava.time.Instant;importjava.util.List;importjava.util.Map;importjava.util.concurrent.atomic.AtomicLong;importjava.util.concurrent.atomic.AtomicReference;importstaticorg.springframework.cloud.gateway.support.ServerWebExchangeUtils.*;/** * Spring Cloud Gateway 全局日志过滤器 * 支持响应式日志记录和虚拟线程 */Slf4jComponentRequiredArgsConstructorpublicclassGatewayGlobalLogFilterimplementsGlobalFilter,Ordered{privatefinalTracertracer;// 请求计数器privatefinalAtomicLongrequestCounternewAtomicLong(0);OverridepublicintgetOrder(){returnOrdered.HIGHEST_PRECEDENCE1;}Loggable(module网关,value网关请求处理,asynctrue,virtualThreadtrue,levelLoggable.LogLevel.INFO,pushToCentertrue)OverridepublicMonoVoidfilter(ServerWebExchangeexchange,GatewayFilterChainchain){longrequestIdrequestCounter.incrementAndGet();InstantstartTimeInstant.now();ServerHttpRequestrequestexchange.getRequest();// 创建日志上下文LogContextlogContextcreateLogContext(exchange,requestId);// 获取路由信息Routerouteexchange.getAttribute(GATEWAY_ROUTE_ATTR);if(route!null){logContext.addAttribute(route.id,route.getId());logContext.addAttribute(route.uri,route.getUri().toString());}// 创建SpanSpangatewaySpancreateGatewaySpan(request,logContext);// 包装请求和响应ServerHttpRequestdecoratedRequestdecorateRequest(request,logContext);ServerHttpResponsedecoratedResponsedecorateResponse(exchange.getResponse(),logContext);ServerWebExchangedecoratedExchangeexchange.mutate().request(decoratedRequest).response(decoratedResponse).build();// 记录请求开始logRequestStart(logContext,request);returnchain.filter(decoratedExchange).contextWrite(ctx-{// 在上下文中存储日志信息returnctx.put(gateway.logContext,logContext).put(gateway.startTime,startTime).put(gateway.requestId,requestId).put(gateway.span,gatewaySpan);}).doOnSuccess(v-{// 记录请求成功longdurationDuration.between(startTime,Instant.now()).toMillis();logRequestSuccess(logContext,duration,gatewaySpan);}).doOnError(throwable-{// 记录请求失败longdurationDuration.between(startTime,Instant.now()).toMillis();logRequestError(logContext,throwable,duration,gatewaySpan);}).doFinally(signalType-{// 结束Spanif(gatewaySpan!null){gatewaySpan.tag(signal.type,signalType.name());gatewaySpan.end();}// 清理资源DataBufferUtils.release(logContext.getAttributes().remove(request.body));DataBufferUtils.release(logContext.getAttributes().remove(response.body));log.debug(【网关】请求处理完成: {}信号: {},requestId,signalType);});}/** * 创建日志上下文 */privateLogContextcreateLogContext(ServerWebExchangeexchange,longrequestId){ServerHttpRequestrequestexchange.getRequest();LogContextcontextLogContext.create();// 请求信息LogContext.RequestInforequestInfonewLogContext.RequestInfo();requestInfo.setRequestId(String.valueOf(requestId));requestInfo.setMethod(request.getMethod().name());requestInfo.setUri(request.getURI().toString());// 请求头MapString,Stringheadersrequest.getHeaders().toSingleValueMap();requestInfo.setHeaders(headers);// 查询参数MapString,StringqueryParamsrequest.getQueryParams().toSingleValueMap();requestInfo.setQueryParams(queryParams);// 远程地址InetSocketAddressremoteAddressrequest.getRemoteAddress();if(remoteAddress!null){requestInfo.setRemoteAddress(remoteAddress.getAddress().getHostAddress());}// User AgentrequestInfo.setUserAgent(request.getHeaders().getFirst(User-Agent));context.setRequestInfo(requestInfo);// 追踪信息StringtraceIdrequest.getHeaders().getFirst(X-B3-TraceId);StringspanIdrequest.getHeaders().getFirst(X-B3-SpanId);if(traceId!null){context.setTraceId(traceId);}if(spanId!null){context.setSpanId(spanId);}returncontext;}/** * 创建网关Span */privateSpancreateGatewaySpan(ServerHttpRequestrequest,LogContextlogContext){if(tracernull){returnnull;}StringspanNamegateway:request.getMethod().name():request.getURI().getPath();Spanspantracer.nextSpan().name(spanName).kind(Span.Kind.SERVER).tag(http.method,request.getMethod().name()).tag(http.path,request.getURI().getPath()).tag(gateway.request.id,String.valueOf(logContext.getRequestInfo().getRequestId())).tag(thread.virtual,String.valueOf(Thread.currentThread().isVirtual())).start();// 设置追踪ID到上下文logContext.setTraceId(span.context().traceId());logContext.setSpanId(span.context().spanId());returnspan;}/** * 包装请求记录请求体 */privateServerHttpRequestdecorateRequest(ServerHttpRequestrequest,LogContextlogContext){// 如果不是JSON请求直接返回原请求MediaTypecontentTyperequest.getHeaders().getContentType();if(contentTypenull||!contentType.includes(MediaType.APPLICATION_JSON)){returnrequest;}returnnewServerHttpRequestDecorator(request){privatefinalAtomicReferencebyte[]cachedBodynewAtomicReference();OverridepublicFluxDataBuffergetBody(){returnsuper.getBody().doOnNext(dataBuffer-{// 缓存请求体用于日志记录byte[]bytesnewbyte[dataBuffer.readableByteCount()];dataBuffer.read(bytes);DataBufferUtils.release(dataBuffer);// 限制大小避免大请求体导致内存问题if(bytes.length1024*10){// 10KB以内cachedBody.set(bytes);logContext.addAttribute(request.body,newString(bytes,StandardCharsets.UTF_8));}// 重新创建DataBufferDataBufferFactoryfactoryrequest.bufferFactory();DataBuffernewBufferfactory.wrap(bytes);cachedBody.set(bytes);}).thenMany(Flux.defer(()-{byte[]bodycachedBody.get();if(body!null){returnFlux.just(request.bufferFactory().wrap(body));}returnFlux.empty();}));}};}/** * 包装响应记录响应体 */privateServerHttpResponsedecorateResponse(ServerHttpResponseresponse,LogContextlogContext){returnnewServerHttpResponseDecorator(response){privatefinalAtomicReferencebyte[]cachedBodynewAtomicReference();OverridepublicMonoVoidwriteWith(Publisher?extendsDataBufferbody){returnsuper.writeWith(Flux.from(body).doOnNext(dataBuffer-{// 缓存响应体用于日志记录byte[]bytesnewbyte[dataBuffer.readableByteCount()];dataBuffer.read(bytes);DataBufferUtils.release(dataBuffer);// 限制大小避免大响应体导致内存问题if(bytes.length1024*10){// 10KB以内cachedBody.set(bytes);logContext.addAttribute(response.body,newString(bytes,StandardCharsets.UTF_8));logContext.addAttribute(response.status,String.valueOf(getStatusCode().value()));}// 重新创建DataBufferDataBufferFactoryfactoryresponse.bufferFactory();DataBuffernewBufferfactory.wrap(bytes);cachedBody.set(bytes);}).thenMany(Flux.defer(()-{byte[]bodyBytescachedBody.get();if(bodyBytes!null){returnFlux.just(response.bufferFactory().wrap(bodyBytes));}returnFlux.empty();})));}OverridepublicMonoVoidwriteAndFlushWith(Publisher?extendsPublisher?extendsDataBufferbody){returnwriteWith(Flux.from(body).flatMapSequential(p-p));}};}/** * 记录请求开始 */privatevoidlogRequestStart(LogContextcontext,ServerHttpRequestrequest){log.info(【网关请求开始】ID: {}, 方法: {}, 路径: {}, 来源IP: {}, 虚拟线程: {},context.getRequestInfo().getRequestId(),request.getMethod().name(),request.getURI().getPath(),context.getRequestInfo().getRemoteAddress(),Thread.currentThread().isVirtual());}/** * 记录请求成功 */privatevoidlogRequestSuccess(LogContextcontext,longduration,Spanspan){StringtraceIdspan!null?span.context().traceId():N/A;log.info(【网关请求成功】ID: {}, 耗时: {}ms, 追踪ID: {}, 线程: {},context.getRequestInfo().getRequestId(),duration,traceId,Thread.currentThread().getName());// 记录到指标io.micrometer.core.instrument.Metrics.counter(gateway.requests.success,method,context.getRequestInfo().getMethod(),path,context.getRequestInfo().getUri()).increment();io.micrometer.core.instrument.Timer.builder(gateway.request.duration).tag(status,success).register(io.micrometer.core.instrument.Metrics.globalRegistry).record(Duration.ofMillis(duration));}/** * 记录请求失败 */privatevoidlogRequestError(LogContextcontext,Throwablethrowable,longduration,Spanspan){StringtraceIdspan!null?span.context().traceId():N/A;log.error(【网关请求失败】ID: {}, 耗时: {}ms, 追踪ID: {}, 错误: {},context.getRequestInfo().getRequestId(),duration,traceId,throwable.getMessage(),throwable);// 记录到指标io.micrometer.core.instrument.Metrics.counter(gateway.requests.error,method,context.getRequestInfo().getMethod(),path,context.getRequestInfo().getUri(),exception,throwable.getClass().getSimpleName()).increment();}}11.2 网关虚拟线程配置packagecom.example.gateway.config;importorg.springframework.boot.autoconfigure.web.ServerProperties;importorg.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory;importorg.springframework.boot.web.reactive.server.ReactiveWebServerFactory;importorg.springframework.cloud.gateway.config.HttpClientCustomizer;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.http.client.reactive.ReactorClientHttpConnector;importorg.springframework.http.client.reactive.ReactorResourceFactory;importreactor.netty.http.client.HttpClient;importreactor.netty.resources.ConnectionProvider;importreactor.netty.resources.LoopResources;importjava.time.Duration;importjava.util.concurrent.Executors;/** * 网关虚拟线程配置 */ConfigurationpublicclassGatewayVirtualThreadConfig{/** * 配置Netty使用虚拟线程 */BeanpublicReactiveWebServerFactoryreactiveWebServerFactory(ServerPropertiesserverProperties){NettyReactiveWebServerFactoryfactorynewNettyReactiveWebServerFactory();factory.addServerCustomizers(httpServer-{// 使用虚拟线程的事件循环组httpServer.runOn(LoopResources.create(gateway-virtual,1,// 线程数true,// 守护线程true// 选择最佳事件循环));returnhttpServer;});returnfactory;}/** * 配置HTTP客户端使用虚拟线程 */BeanpublicHttpClientCustomizerhttpClientVirtualThreadCustomizer(){returnfactory-{ConnectionProviderproviderConnectionProvider.builder(gateway-virtual-connection).maxConnections(500).pendingAcquireTimeout(Duration.ofSeconds(60)).evictInBackground(Duration.ofSeconds(120)).build();HttpClienthttpClientHttpClient.create(provider).runOn(LoopResources.create(client-virtual,2,true,true)).responseTimeout(Duration.ofSeconds(30)).compress(true);returnhttpClient;};}/** * Reactor资源工厂 */BeanpublicReactorResourceFactoryreactorResourceFactory(){ReactorResourceFactoryfactorynewReactorResourceFactory();factory.setUseGlobalResources(false);factory.setLoopResourcesSupplier(()-LoopResources.create(gateway-global-virtual,Runtime.getRuntime().availableProcessors()*2,true,true));returnfactory;}/** * 虚拟线程执行器 */Beanpublicjava.util.concurrent.ExecutorServicegatewayVirtualExecutor(){returnExecutors.newThreadPerTaskExecutor(Thread.ofVirtual().name(gateway-vt-,0).factory());}}十二、服务间调用日志12.1 OpenFeign 日志拦截器packagecom.example.feign.interceptor;importcom.example.logging.annotation.Loggable;importcom.example.logging.context.LogContext;importfeign.RequestInterceptor;importfeign.RequestTemplate;importio.micrometer.tracing.Span;importio.micrometer.tracing.Tracer;importlombok.RequiredArgsConstructor;importlombok.extern.slf4j.Slf4j;importorg.springframework.cloud.openfeign.FeignClient;importorg.springframework.stereotype.Component;importjava.time.Instant;importjava.util.concurrent.Executors;importjava.util.concurrent.atomic.AtomicLong;/** * OpenFeign 日志拦截器 * 自动传播追踪信息和记录调用日志 */Slf4jComponentRequiredArgsConstructorpublicclassFeignLoggingInterceptorimplementsRequestInterceptor{privatefinalTracertracer;// Feign调用计数器privatefinalAtomicLongfeignCallCounternewAtomicLong(0);// 虚拟线程执行器privatefinaljava.util.concurrent.ExecutorServicevirtualExecutorExecutors.newThreadPerTaskExecutor(Thread.ofVirtual().name(feign-log-,0).factory());Loggable(module服务调用,valueFeign远程调用,asynctrue,virtualThreadtrue,levelLoggable.LogLevel.INFO)Overridepublicvoidapply(RequestTemplatetemplate){longcallIdfeignCallCounter.incrementAndGet();InstantstartTimeInstant.now();// 创建日志上下文LogContextlogContextLogContext.create();logContext.setOperation(Feign远程调用);logContext.setClassName(template.feignTarget().type().getName());logContext.setMethodName(template.methodMetadata().configKey());logContext.addAttribute(feign.call.id,String.valueOf(callId));logContext.addAttribute(service.url,template.feignTarget().url());logContext.addAttribute(request.url,template.url());logContext.addAttribute(request.headers,template.headers());// 记录开始日志logFeignCallStart(logContext,template);// 注入追踪头injectTraceHeaders(template);// 注入自定义头template.header(X-Feign-Call-Id,String.valueOf(callId));template.header(X-Feign-Start-Time,String.valueOf(startTime.toEpochMilli()));template.header(X-Is-Virtual-Thread,String.valueOf(Thread.currentThread().isVirtual()));// 记录请求体如果有if(template.body()!null){StringbodynewString(template.body());if(body.length()1024){// 只记录1KB以内的请求体logContext.addAttribute(request.body,body);}}// 异步记录调用信息virtualExecutor.submit(()-{try{// 记录到指标io.micrometer.core.instrument.Metrics.counter(feign.calls.initiated,service,extractServiceName(template),method,template.method()).increment();// 创建Feign调用的SpancreateFeignSpan(template,logContext);}catch(Exceptione){log.error(Feign日志记录失败,e);}});// 存储日志上下文供响应拦截器使用template.header(X-Log-Context,serializeLogContext(logContext));}/** * 注入追踪头 */privatevoidinjectTraceHeaders(RequestTemplatetemplate){if(tracernull){return;}SpancurrentSpantracer.currentSpan();if(currentSpan!null){// 传播追踪上下文tracer.inject(currentSpan.context(),template,(carrier,key,value)-{if(carrierinstanceofRequestTemplate){((RequestTemplate)carrier).header(key,value);}});// 记录追踪信息到日志上下文template.header(X-Parent-Trace-Id,currentSpan.context().traceId());template.header(X-Parent-Span-Id,currentSpan.context().spanId());}}/** * 创建Feign调用Span */privatevoidcreateFeignSpan(RequestTemplatetemplate,LogContextlogContext){if(tracernull){return;}StringspanNamefeign:extractServiceName(template):template.methodMetadata().method().getName();Spanspantracer.nextSpan().name(spanName).kind(Span.Kind.CLIENT).tag(rpc.system,feign).tag(rpc.service,extractServiceName(template)).tag(rpc.method,template.methodMetadata().method().getName()).tag(http.method,template.method()).tag(http.url,template.url()).tag(feign.call.id,String.valueOf(logContext.getAttributes().get(feign.call.id))).start();// 设置追踪ID到日志上下文logContext.setTraceId(span.context().traceId());logContext.setSpanId(span.context().spanId());// 在Span上下文中执行try(Tracer.SpanInScopescopetracer.withSpan(span)){log.debug(【Feign调用Span创建】名称: {}, 追踪ID: {},spanName,span.context().traceId());}}/** * 提取服务名称 */privateStringextractServiceName(RequestTemplatetemplate){Class?targetTypetemplate.feignTarget().type();FeignClientfeignClienttargetType.getAnnotation(FeignClient.class);if(feignClient!null){returnfeignClient.name();}returntargetType.getSimpleName();}/** * 记录Feign调用开始 */privatevoidlogFeignCallStart(LogContextcontext,RequestTemplatetemplate){log.info(【Feign调用开始】服务: {}, 方法: {}, URL: {}, 虚拟线程: {},extractServiceName(template),template.methodMetadata().method().getName(),template.url(),Thread.currentThread().isVirtual());}/** * 序列化日志上下文 */privateStringserializeLogContext(LogContextcontext){try{// 简单序列化实际可以使用JSONreturnString.format(%s|%s|%s,context.getLogId(),context.getTraceId(),context.getSpanId());}catch(Exceptione){return;}}}12.2 Feign 响应拦截器packagecom.example.feign.interceptor;importcom.example.logging.context.LogContext;importfeign.Response;importfeign.codec.ErrorDecoder;importlombok.RequiredArgsConstructor;importlombok.extern.slf4j.Slf4j;importorg.springframework.stereotype.Component;importjava.time.Duration;importjava.time.Instant;importjava.util.concurrent.Executors;/** * Feign 响应拦截器 * 记录响应日志和处理错误 */Slf4jComponentRequiredArgsConstructorpublicclassFeignResponseInterceptorimplementsErrorDecoder{// 虚拟线程执行器privatefinaljava.util.concurrent.ExecutorServicevirtualExecutorExecutors.newThreadPerTaskExecutor(Thread.ofVirtual().name(feign-resp-,0).factory());OverridepublicExceptiondecode(StringmethodKey,Responseresponse){// 解析日志上下文StringlogContextHeaderresponse.request().headers().get(X-Log-Context);if(logContextHeader!null!logContextHeader.isEmpty()){LogContextlogContextdeserializeLogContext(logContextHeader);StringstartTimeHeaderresponse.request().headers().get(X-Feign-Start-Time);if(startTimeHeader!null){try{longstartTimeLong.parseLong(startTimeHeader);longdurationSystem.currentTimeMillis()-startTime;// 异步记录错误响应virtualExecutor.submit(()-{logFeignError(logContext,methodKey,response,duration);});}catch(NumberFormatExceptione){log.warn(解析Feign开始时间失败,e);}}}// 使用默认错误解码器returnnewErrorDecoder.Default().decode(methodKey,response);}/** * 记录Feign调用成功 */publicvoidlogFeignSuccess(Responseresponse,Durationduration){virtualExecutor.submit(()-{try{StringlogContextHeaderresponse.request().headers().get(X-Log-Context);if(logContextHeader!null!logContextHeader.isEmpty()){LogContextlogContextdeserializeLogContext(logContextHeader);log.info(【Feign调用成功】服务: {}, 方法: {}, 耗时: {}ms, 状态码: {},extractServiceNameFromRequest(response.request()),extractMethodNameFromRequest(response.request()),duration.toMillis(),response.status());// 记录到指标io.micrometer.core.instrument.Metrics.counter(feign.calls.success,service,extractServiceNameFromRequest(response.request()),status,String.valueOf(response.status())).increment();io.micrometer.core.instrument.Timer.builder(feign.call.duration).tag(status,success).register(io.micrometer.core.instrument.Metrics.globalRegistry).record(duration);}}catch(Exceptione){log.error(Feign成功日志记录失败,e);}});}/** * 记录Feign调用错误 */privatevoidlogFeignError(LogContextcontext,StringmethodKey,Responseresponse,longduration){log.error(【Feign调用失败】服务: {}, 方法: {}, 耗时: {}ms, 状态码: {}, 错误: {},extractServiceName(context),methodKey,duration,response.status(),response.reason());// 记录到指标io.micrometer.core.instrument.Metrics.counter(feign.calls.error,service,extractServiceName(context),status,String.valueOf(response.status())).increment();io.micrometer.core.instrument.Timer.builder(feign.call.duration).tag(status,error).register(io.micrometer.core.instrument.Metrics.globalRegistry).record(Duration.ofMillis(duration));}/** * 反序列化日志上下文 */privateLogContextdeserializeLogContext(Stringheader){try{String[]partsheader.split(\\|);if(parts.length3){LogContextcontextnewLogContext();context.setLogId(parts[0]);context.setTraceId(parts[1]);context.setSpanId(parts[2]);returncontext;}}catch(Exceptione){log.warn(反序列化日志上下文失败,e);}returnLogContext.create();}/** * 从请求中提取服务名称 */privateStringextractServiceNameFromRequest(feign.Requestrequest){// 从URL或header中提取服务名称Stringurlrequest.url();// 简化的提取逻辑if(url.contains(/api/)){String[]partsurl.split(/);for(inti0;iparts.length;i){if(api.equals(parts[i])i1parts.length){returnparts[i1];}}}returnunknown;}/** * 从请求中提取方法名称 */privateStringextractMethodNameFromRequest(feign.Requestrequest){Stringurlrequest.url();String[]partsurl.split(/);returnparts.length0?parts[parts.length-1]:unknown;}/** * 从上下文中提取服务名称 */privateStringextractServiceName(LogContextcontext){ObjectserviceNamecontext.getAttributes().get(service.url);returnserviceName!null?serviceName.toString():unknown;}}十三、服务网格集成13.1 Istio 边车日志集成packagecom.example.mesh.integration;importcom.example.logging.annotation.Loggable;importcom.example.logging.context.LogContext;importlombok.RequiredArgsConstructor;importlombok.extern.slf4j.Slf4j;importorg.springframework.cloud.client.loadbalancer.LoadBalanced;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.http.HttpHeaders;importorg.springframework.http.HttpRequest;importorg.springframework.http.client.ClientHttpRequestExecution;importorg.springframework.http.client.ClientHttpRequestInterceptor;importorg.springframework.http.client.ClientHttpResponse;importorg.springframework.web.client.RestTemplate;importorg.springframework.web.reactive.function.client.ClientRequest;importorg.springframework.web.reactive.function.client.ClientResponse;importorg.springframework.web.reactive.function.client.ExchangeFilterFunction;importorg.springframework.web.reactive.function.client.WebClient;importreactor.core.publisher.Mono;importjava.io.IOException;importjava.time.Duration;importjava.time.Instant;importjava.util.Collections;importjava.util.List;importjava.util.concurrent.Executors;/** * 服务网格集成配置 * 支持Istio边车日志和追踪 */Slf4jConfigurationRequiredArgsConstructorpublicclassServiceMeshIntegrationConfig{/** * RestTemplate 拦截器支持Istio */BeanLoadBalancedpublicRestTemplatemeshAwareRestTemplate(){RestTemplaterestTemplatenewRestTemplate();restTemplate.setInterceptors(Collections.singletonList(newMeshRestTemplateInterceptor()));returnrestTemplate;}/** * WebClient 过滤器支持Istio */BeanLoadBalancedpublicWebClientmeshAwareWebClient(){returnWebClient.builder().filter(meshExchangeFilterFunction()).build();}/** * Mesh感知的ExchangeFilterFunction */BeanpublicExchangeFilterFunctionmeshExchangeFilterFunction(){returnExchangeFilterFunction.ofRequestProcessor(clientRequest-{// 在请求前添加Mesh相关headerClientRequestnewRequestClientRequest.from(clientRequest).header(X-Request-Id,generateRequestId()).header(X-Mesh-Service,getCurrentServiceName()).header(X-Envoy-Timeout,30s).build();returnMono.just(newRequest);});}/** * RestTemplate拦截器实现 */Loggable(module服务网格,valueMesh服务调用,asynctrue,virtualThreadtrue)privatestaticclassMeshRestTemplateInterceptorimplementsClientHttpRequestInterceptor{privatefinaljava.util.concurrent.ExecutorServicevirtualExecutorExecutors.newThreadPerTaskExecutor(Thread.ofVirtual().name(mesh-rest-,0).factory());OverridepublicClientHttpResponseintercept(HttpRequestrequest,byte[]body,ClientHttpRequestExecutionexecution)throwsIOException{longstartTimeSystem.currentTimeMillis();StringrequestIdgenerateRequestId();// 添加Mesh headerrequest.getHeaders().add(X-Request-Id,requestId);request.getHeaders().add(X-Mesh-Service,getCurrentServiceName());request.getHeaders().add(X-Caller-Service,System.getProperty(spring.application.name,unknown));// 记录调用开始logMeshCallStart(request,requestId);try{ClientHttpResponseresponseexecution.execute(request,body);longdurationSystem.currentTimeMillis()-startTime;// 异步记录调用成功virtualExecutor.submit(()-{logMeshCallSuccess(request,response,requestId,duration);});returnresponse;}catch(IOExceptione){longdurationSystem.currentTimeMillis()-startTime;// 异步记录调用失败virtualExecutor.submit(()-{logMeshCallError(request,e,requestId,duration);});throwe;}}privatevoidlogMeshCallStart(HttpRequestrequest,StringrequestId){log.info(【Mesh调用开始】ID: {}, 服务: {}, 路径: {}, 虚拟线程: {},requestId,extractServiceName(request.getURI().toString()),request.getURI().getPath(),Thread.currentThread().isVirtual());}privatevoidlogMeshCallSuccess(HttpRequestrequest,ClientHttpResponseresponse,StringrequestId,longduration){try{log.info(【Mesh调用成功】ID: {}, 服务: {}, 耗时: {}ms, 状态码: {},requestId,extractServiceName(request.getURI().toString()),duration,response.getStatusCode().value());// 记录到指标io.micrometer.core.instrument.Metrics.counter(mesh.calls.success,service,extractServiceName(request.getURI().toString()),status,String.valueOf(response.getStatusCode().value())).increment();}catch(IOExceptione){log.error(记录Mesh调用成功日志失败,e);}}privatevoidlogMeshCallError(HttpRequestrequest,IOExceptionexception,StringrequestId,longduration){log.error(【Mesh调用失败】ID: {}, 服务: {}, 耗时: {}ms, 错误: {},requestId,extractServiceName(request.getURI().toString()),duration,exception.getMessage(),exception);// 记录到指标io.micrometer.core.instrument.Metrics.counter(mesh.calls.error,service,extractServiceName(request.getURI().toString()),exception,exception.getClass().getSimpleName()).increment();}}/** * 生成请求ID */privatestaticStringgenerateRequestId(){returnjava.util.UUID.randomUUID().toString().replace(-,).substring(0,16);}/** * 获取当前服务名称 */privatestaticStringgetCurrentServiceName(){returnSystem.getProperty(spring.application.name,unknown-service);}/** * 从URL中提取服务名称 */privatestaticStringextractServiceName(Stringurl){// 简化的服务名称提取逻辑// 实际中可能根据服务发现机制来提取if(url.contains(://)){urlurl.substring(url.indexOf(://)3);}if(url.contains(/)){urlurl.substring(0,url.indexOf(/));}if(url.contains(:)){urlurl.substring(0,url.indexOf(:));}returnurl;}}十四、监控与告警14.1 Actuator 端点扩展packagecom.example.logging.actuator;importcom.example.logging.context.LogContext;importcom.example.logging.service.LogService;importio.micrometer.core.instrument.MeterRegistry;importlombok.RequiredArgsConstructor;importlombok.extern.slf4j.Slf4j;importorg.springframework.boot.actuate.endpoint.annotation.Endpoint;importorg.springframework.boot.actuate.endpoint.annotation.ReadOperation;importorg.springframework.boot.actuate.endpoint.annotation.WriteOperation;importorg.springframework.boot.actuate.endpoint.web.annotation.WebEndpoint;importorg.springframework.stereotype.Component;importjava.time.LocalDateTime;importjava.time.format.DateTimeFormatter;importjava.util.*;importjava.util.concurrent.ConcurrentHashMap;importjava.util.concurrent.atomic.AtomicLong;/** * 自定义Actuator端点 * 提供日志相关的监控和管理功能 */Slf4jComponentWebEndpoint(idlogging)RequiredArgsConstructorpublicclassLoggingActuatorEndpoint{privatefinalMeterRegistrymeterRegistry;privatefinalLogServicelogService;// 日志统计缓存privatefinalMapString,LogStatisticsstatisticsCachenewConcurrentHashMap();privatefinalAtomicLonglastResetTimenewAtomicLong(System.currentTimeMillis());privatestaticfinalDateTimeFormatterTIME_FORMATTERDateTimeFormatter.ofPattern(yyyy-MM-dd HH:mm:ss);/** * 获取日志统计信息 */ReadOperationpublicMapString,ObjectgetLoggingStats(){MapString,ObjectstatsnewLinkedHashMap();// 基本统计stats.put(timestamp,LocalDateTime.now().format(TIME_FORMATTER));stats.put(lastReset,formatTime(lastResetTime.get()));// 线程统计stats.put(threads,getThreadStats());// 日志量统计stats.put(volume,getLogVolumeStats());// 性能统计stats.put(performance,getPerformanceStats());// 虚拟线程统计stats.put(virtualThreads,getVirtualThreadStats());// 错误统计stats.put(errors,getErrorStats());returnstats;}/** * 重置统计信息 */WriteOperationpublicMapString,ObjectresetStats(){statisticsCache.clear();lastResetTime.set(System.currentTimeMillis());MapString,ObjectresultnewHashMap();result.put(message,统计信息已重置);result.put(resetTime,formatTime(lastResetTime.get()));log.info(日志统计信息已重置);returnresult;}/** * 获取线程统计 */privateMapString,ObjectgetThreadStats(){MapString,ObjectthreadStatsnewHashMap();ThreadGrouprootGroupThread.currentThread().getThreadGroup();while(rootGroup.getParent()!null){rootGrouprootGroup.getParent();}Thread[]threadsnewThread[rootGroup.activeCount()];rootGroup.enumerate(threads,true);longvirtualThreadCountArrays.stream(threads).filter(Thread::isVirtual).count();longplatformThreadCountArrays.stream(threads).filter(t-!t.isVirtual()).count();threadStats.put(total,threads.length);threadStats.put(virtual,virtualThreadCount);threadStats.put(platform,platformThreadCount);threadStats.put(daemon,Arrays.stream(threads).filter(Thread::isDaemon).count());returnthreadStats;}/** * 获取日志量统计 */privateMapString,ObjectgetLogVolumeStats(){MapString,ObjectvolumeStatsnewHashMap();// 从MeterRegistry获取指标Collectionio.micrometer.core.instrument.CountercountersmeterRegistry.find(log.).counters();MapString,DoublecounterValuesnewHashMap();counters.forEach(counter-{Stringnamecounter.getId().getName();doublevaluecounter.count();counterValues.put(name,value);});volumeStats.put(counters,counterValues);volumeStats.put(totalLogs,counterValues.values().stream().mapToDouble(Double::doubleValue).sum());returnvolumeStats;}/** * 获取性能统计 */privateMapString,ObjectgetPerformanceStats(){MapString,ObjectperfStatsnewHashMap();// 收集计时器信息Collectionio.micrometer.core.instrument.TimertimersmeterRegistry.find(log.execution.time).timers();ListMapString,ObjecttimerInfosnewArrayList();timers.forEach(timer-{MapString,ObjecttimerInfonewHashMap();timerInfo.put(name,timer.getId().getName());timerInfo.put(count,timer.count());timerInfo.put(mean,timer.mean(io.micrometer.core.instrument.TimeUnit.MILLISECONDS));timerInfo.put(max,timer.max(io.micrometer.core.instrument.TimeUnit.MILLISECONDS));timerInfo.put(p95,timer.percentile(0.95,io.micrometer.core.instrument.TimeUnit.MILLISECONDS));timerInfos.add(timerInfo);});perfStats.put(timers,timerInfos);returnperfStats;}/** * 获取虚拟线程统计 */privateMapString,ObjectgetVirtualThreadStats(){MapString,ObjectvtStatsnewHashMap();// 虚拟线程创建率io.micrometer.core.instrument.CountervtCountermeterRegistry.find(log.virtual.thread.count).counter();if(vtCounter!null){vtStats.put(created,vtCounter.count());}// 活跃虚拟线程数longactiveVirtualThreadsThread.getAllStackTraces().keySet().stream().filter(Thread::isVirtual).count();vtStats.put(active,activeVirtualThreads);vtStats.put(carrierThreads,getCarrierThreadCount());returnvtStats;}/** * 获取载体线程数 */privateintgetCarrierThreadCount(){// 估算载体线程数returnRuntime.getRuntime().availableProcessors()*2;}/** * 获取错误统计 */privateMapString,ObjectgetErrorStats(){MapString,ObjecterrorStatsnewHashMap();// 错误计数器Collectionio.micrometer.core.instrument.CountererrorCountersmeterRegistry.find(log.*.error).counters();MapString,DoubleerrorsnewHashMap();errorCounters.forEach(counter-{Stringnamecounter.getId().getName();doublevaluecounter.count();errors.put(name,value);});errorStats.put(counters,errors);errorStats.put(totalErrors,errors.values().stream().mapToDouble(Double::doubleValue).sum());returnerrorStats;}/** * 格式化时间戳 */privateStringformatTime(longtimestamp){returnLocalDateTime.ofInstant(java.time.Instant.ofEpochMilli(timestamp),java.time.ZoneId.systemDefault()).format(TIME_FORMATTER);}/** * 日志统计数据结构 */DataprivatestaticclassLogStatistics{privateStringmodule;privatelongtotalRequests;privatelongsuccessfulRequests;privatelongfailedRequests;privatelongslowQueries;privatedoubleavgResponseTime;privatedoublep95ResponseTime;privatedoublep99ResponseTime;privateLocalDateTimelastUpdated;publicvoidincrementTotal(){totalRequests;lastUpdatedLocalDateTime.now();}publicvoidincrementSuccess(){successfulRequests;lastUpdatedLocalDateTime.now();}publicvoidincrementFailure(){failedRequests;lastUpdatedLocalDateTime.now();}publicvoidincrementSlowQuery(){slowQueries;lastUpdatedLocalDateTime.now();}}}十五、测试与验证15.1 集成测试配置packagecom.example.test;importcom.example.logging.annotation.Loggable;importorg.junit.jupiter.api.Test;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.test.context.SpringBootTest;importorg.springframework.boot.test.mock.mockito.MockBean;importorg.springframework.test.context.ActiveProfiles;importreactor.core.publisher.Mono;importreactor.test.StepVerifier;importjava.util.concurrent.CompletableFuture;importjava.util.concurrent.TimeUnit;importstaticorg.assertj.core.api.Assertions.assertThat;importstaticorg.mockito.ArgumentMatchers.any;importstaticorg.mockito.Mockito.*;/** * 日志注解集成测试 */SpringBootTest(webEnvironmentSpringBootTest.WebEnvironment.RANDOM_PORT)ActiveProfiles(test)classLoggingIntegrationTest{AutowiredprivateTestServicetestService;MockBeanprivateLoggingMetricsCollectormetricsCollector;TestvoidtestSyncMethodLogging(){// 执行测试方法StringresulttestService.syncMethod(test-input);// 验证结果assertThat(result).isEqualTo(SYNC-test-input);// 验证指标被记录verify(metricsCollector,times(1)).recordLogCount(eq(test-module),eq(INFO),eq(true));}TestvoidtestAsyncMethodLogging()throwsException{// 执行异步方法CompletableFutureStringfuturetestService.asyncMethod(async-input);Stringresultfuture.get(5,TimeUnit.SECONDS);// 验证结果assertThat(result).isEqualTo(ASYNC-async-input);// 验证虚拟线程指标verify(metricsCollector,atLeastOnce()).recordVirtualThreadMetrics();}TestvoidtestReactiveMethodLogging(){// 执行响应式方法MonoStringmonotestService.reactiveMethod(reactive-input);StepVerifier.create(mono).expectNext(REACTIVE-reactive-input).verifyComplete();// 验证响应式指标verify(metricsCollector,atLeastOnce()).recordReactiveMetrics(anyString(),anyInt(),any());}TestvoidtestErrorLogging(){// 验证异常日志try{testService.errorMethod();}catch(RuntimeExceptione){assertThat(e.getMessage()).isEqualTo(Test error);}// 验证错误指标verify(metricsCollector,times(1)).recordLogCount(eq(test-module),eq(ERROR),eq(false));}TestvoidtestVirtualThreadMethod()throwsException{// 执行虚拟线程方法CompletableFutureStringfuturetestService.virtualThreadMethod(virtual-input);Stringresultfuture.get(5,TimeUnit.SECONDS);assertThat(result).isEqualTo(VIRTUAL-virtual-input);// 验证虚拟线程使用情况verify(metricsCollector,atLeastOnce()).recordVirtualThreadMetrics();}/** * 测试服务 */ComponentstaticclassTestService{Loggable(moduletest-module,value同步方法测试,levelLoggable.LogLevel.INFO)publicStringsyncMethod(Stringinput){returnSYNC-input;}Loggable(moduletest-module,value异步方法测试,asynctrue,virtualThreadtrue)publicCompletableFutureStringasyncMethod(Stringinput){returnCompletableFuture.supplyAsync(()-{try{Thread.sleep(100);// 模拟耗时操作}catch(InterruptedExceptione){Thread.currentThread().interrupt();}returnASYNC-input;});}Loggable(moduletest-module,value响应式方法测试,asynctrue)publicMonoStringreactiveMethod(Stringinput){returnMono.fromCallable(()-REACTIVE-input).delayElement(java.time.Duration.ofMillis(100));}Loggable(moduletest-module,value错误方法测试,levelLoggable.LogLevel.ERROR)publicvoiderrorMethod(){thrownewRuntimeException(Test error);}Loggable(moduletest-module,value虚拟线程方法测试,asynctrue,virtualThreadtrue,asyncStrategyLoggable.AsyncStrategy.VIRTUAL_THREAD)publicCompletableFutureStringvirtualThreadMethod(Stringinput){returnCompletableFuture.supplyAsync(()-{// 在虚拟线程中执行try{Thread.sleep(50);}catch(InterruptedExceptione){Thread.currentThread().interrupt();}returnVIRTUAL-input;});}}}十六、部署配置16.1 Dockerfile (原生镜像)# 第一阶段构建原生镜像 FROM ghcr.io/graalvm/native-image:ol8-java21 AS builder # 安装必要的构建工具 RUN microdnf install -y gcc gcc-c zlib-devel # 设置工作目录 WORKDIR /app # 复制构建文件 COPY mvnw . COPY .mvn .mvn COPY pom.xml . COPY src src # 下载依赖 RUN ./mvnw dependency:go-offline -B # 构建原生镜像 RUN ./mvnw clean package -DskipTests -Pnative # 第二阶段运行镜像 FROM oraclelinux:9-slim # 安装必要的运行时库 RUN microdnf install -y \ ca-certificates \ tzdata \ glibc-langpack-en \ microdnf clean all # 设置时区 ENV TZAsia/Shanghai # 创建非root用户 RUN groupadd -r appuser useradd -r -g appuser appuser # 设置工作目录 WORKDIR /app # 复制原生可执行文件 COPY --frombuilder /app/target/*-runner /app/application COPY --frombuilder /app/src/main/resources /app/resources # 设置权限 RUN chown -R appuser:appuser /app USER appuser # 暴露端口 EXPOSE 8080 EXPOSE 8081 # 监控端口 # 设置健康检查 HEALTHCHECK --interval30s --timeout3s --start-period5s --retries3 \ CMD curl -f http://localhost:8080/actuator/health || exit 1 # 运行应用 ENTRYPOINT [/app/application] CMD []16.2 docker-compose.ymlversion:3.8services:# 日志中心服务log-center:build:context:.dockerfile:Dockerfileports:-8080:8080-8081:8081environment:-SPRING_PROFILES_ACTIVEproduction-JAVA_OPTS-XX:UseZGC-Xmx512m-Xms512m-LOGGING_CONFIG_ENABLEDtrue-LOGGING_VIRTUAL_THREAD_ENABLEDtrue-MANAGEMENT_ENDPOINTS_WEB_EXPOSURE_INCLUDEhealth,info,metrics,prometheus,loggingnetworks:-logging-networkdepends_on:-elasticsearch-redisdeploy:resources:limits:memory:768Mreservations:memory:512Mreplicas:3placement:constraints:-node.rolemanagerhealthcheck:test:[CMD,curl,-f,http://localhost:8080/actuator/health]interval:30stimeout:10sretries:3start_period:40s# Elasticsearchelasticsearch:image:elasticsearch:8.12.0environment:-discovery.typesingle-node-xpack.security.enabledfalse-ES_JAVA_OPTS-Xms512m-Xmx512mports:-9200:9200volumes:-esdata:/usr/share/elasticsearch/datanetworks:-logging-networkdeploy:resources:limits:memory:1G# Redis缓存redis:image:redis:7.2-alpineports:-6379:6379command:redis-server--appendonly yesvolumes:-redisdata:/datanetworks:-logging-network# Prometheus监控prometheus:image:prom/prometheus:latestports:-9090:9090volumes:-./prometheus.yml:/etc/prometheus/prometheus.yml-prometheus-data:/prometheusnetworks:-logging-networkcommand:---config.file/etc/prometheus/prometheus.yml---storage.tsdb.path/prometheus---web.console.libraries/etc/prometheus/console_libraries---web.console.templates/etc/prometheus/consoles---storage.tsdb.retention.time200h---web.enable-lifecycle# Grafana可视化grafana:image:grafana/grafana:latestports:-3000:3000environment:-GF_SECURITY_ADMIN_PASSWORDadminvolumes:-grafana-data:/var/lib/grafana-./grafana/provisioning:/etc/grafana/provisioningnetworks:-logging-networkdepends_on:-prometheusnetworks:logging-network:driver:bridgevolumes:esdata:driver:localredisdata:driver:localprometheus-data:driver:localgrafana-data:driver:local十七、最佳实践总结17.1 使用建议/** * 日志注解最佳实践示例 */Slf4jServicepublicclassLoggingBestPracticeService{// 1. 明确的模块划分Loggable(module用户管理,value创建用户账户,typeLoggable.LogType.INSERT,bizNo#userDto.username)publicUsercreateUser(UserDTOuserDto){// 业务逻辑}// 2. 敏感信息脱敏Loggable(module认证授权,value用户登录认证,logParamsfalse,// 不记录密码参数logResultfalse// 不记录令牌结果)publicAuthTokenlogin(Stringusername,Stringpassword){// 认证逻辑}// 3. 大文件/大结果集处理Loggable(module文件服务,value下载文件,logParamstrue,logResultfalse// 不记录文件内容)publicbyte[]downloadFile(StringfileId){// 文件下载逻辑}// 4. 性能敏感操作使用异步Loggable(module报表服务,value生成年度报表,asynctrue,virtualThreadtrue,slowThreshold30000// 30秒超时标记为慢查询)publicCompletableFutureReportgenerateAnnualReport(ReportRequestrequest){// 报表生成逻辑}// 5. 分布式追踪集成TraceLog(spanNamepayment.process,tags{orderId#orderId,amount#amount},remotetrue,remoteServicepayment-service)Loggable(module支付服务,value处理支付订单)publicPaymentResultprocessPayment(StringorderId,BigDecimalamount){// 支付处理逻辑}// 6. 响应式方法ReactiveLog(traceStreamtrue,maxTraceElements50,timeout15000)Loggable(module消息服务,value流式处理消息)publicFluxMessageprocessMessageStream(FluxMessagemessages){returnmessages.doOnNext(msg-log.debug(Processing message: {},msg.getId())).buffer(10).flatMap(this::processBatch);}// 7. 错误处理和降级Loggable(module外部服务,value调用第三方API,levelLoggable.LogLevel.WARN,stackTracetrue)publicExternalResponsecallExternalApi(ExternalRequestrequest){try{returnexternalClient.call(request);}catch(ExternalServiceExceptione){log.error(外部服务调用失败,e);returnfallbackResponse();}}// 8. 虚拟线程并发处理Loggable(module数据处理,value批量数据处理,asynctrue,virtualThreadtrue,asyncStrategyLoggable.AsyncStrategy.VIRTUAL_THREAD)publicvoidbatchProcess(ListDataItemitems){try(varscopenewStructuredTaskScope.ShutdownOnFailure()){ListFutureProcessResultfuturesitems.stream().map(item-scope.fork(()-processItem(item))).toList();scope.join();scope.throwIfFailed();futures.forEach(future-{try{ProcessResultresultfuture.resultNow();log.debug(Processed item: {},result.getItemId());}catch(Exceptione){log.warn(Item processing failed,e);}});}catch(InterruptedExceptione){Thread.currentThread().interrupt();thrownewRuntimeException(批量处理被中断,e);}}// 9. 审计日志Loggable(module审计日志,value重要业务操作,levelLoggable.LogLevel.WARN,pushToCentertrue,groupaudit)TransactionalpublicAuditRecordauditImportantOperation(AuditOperationoperation){// 审计记录逻辑}}17.2 性能优化配置# application-performance.ymlspring:logging:# 生产环境推荐配置enabled:trueasync-enabled:truevirtual-thread-enabled:truereactive-enabled:truedefault-level:INFOslow-threshold:1000log-params:truelog-result:truepush-to-center:true# 模块特定配置modules:gateway-service:enabled:truelevel:INFOasync:truevirtual-thread:trueslow-threshold:500user-service:enabled:truelevel:INFOasync:truevirtual-thread:trueslow-threshold:800order-service:enabled:truelevel:INFOasync:false# 订单服务追求强一致性使用同步日志log-params:false# 订单数据量大不记录参数# 虚拟线程配置threads:virtual:enabled:trueexecutor:core-pool-size:10max-pool-size:100queue-capacity:1000keep-alive-seconds:60thread-name-prefix:app-vt-# 响应式配置webflux:max-in-memory-size:256KB# 限制内存使用# 监控配置management:metrics:export:prometheus:step:1mdistribution:percentiles-histogram:http.server.requests:truesla:http.server.requests:10ms,50ms,100ms,500ms,1s,5s# Sleuth配置sleuth:enabled:truesampler:probability:0.1# 生产环境采样率propagation:type:B3,W3C# 日志级别控制logging:level:root:INFOcom.example:DEBUGcom.example.logging:INFOorg.springframework.web:WARNreactor.netty:WARNio.netty:WARN# 异步日志配置async:enabled:truequeue-size:10000discarding-threshold:0include-caller-data:falsenever-block:true十八、故障排查指南18.1 常见问题解决方案packagecom.example.logging.troubleshooting;importlombok.extern.slf4j.Slf4j;importorg.springframework.stereotype.Component;importjava.lang.management.ManagementFactory;importjava.lang.management.ThreadMXBean;importjava.util.Map;importjava.util.concurrent.ConcurrentHashMap;importjava.util.concurrent.TimeUnit;importjava.util.concurrent.atomic.AtomicInteger;/** * 日志系统故障排查工具 */Slf4jComponentpublicclassLoggingTroubleshooter{// 问题计数器privatefinalMapString,AtomicIntegerissueCountersnewConcurrentHashMap();// 最后检测时间privatevolatilelonglastCheckTimeSystem.currentTimeMillis();/** * 诊断日志系统健康状况 */publicHealthDiagnosisdiagnoseHealth(){HealthDiagnosisdiagnosisnewHealthDiagnosis();diagnosis.setTimestamp(System.currentTimeMillis());// 检查线程状态diagnoseThreadIssues(diagnosis);// 检查内存状态diagnoseMemoryIssues(diagnosis);// 检查死锁diagnoseDeadlocks(diagnosis);// 检查虚拟线程泄漏diagnoseVirtualThreadLeaks(diagnosis);// 检查日志积压diagnoseLogBacklog(diagnosis);// 生成诊断报告generateDiagnosticReport(diagnosis);returndiagnosis;}/** * 诊断线程问题 */privatevoiddiagnoseThreadIssues(HealthDiagnosisdiagnosis){ThreadMXBeanthreadMXBeanManagementFactory.getThreadMXBean();// 活跃线程数intactiveThreadCountThread.activeCount();diagnosis.setActiveThreads(activeThreadCount);// 虚拟线程比例longvirtualThreadCountgetAllThreads().stream().filter(Thread::isVirtual).count();diagnosis.setVirtualThreadRatio((double)virtualThreadCount/activeThreadCount);// 线程峰值diagnosis.setPeakThreadCount(threadMXBean.getPeakThreadCount());// 检查线程泄漏if(activeThreadCount1000){diagnosis.addIssue(THREAD_LEAK,活跃线程数过多: activeThreadCount);incrementIssueCounter(THREAD_LEAK);}}/** * 诊断内存问题 */privatevoiddiagnoseMemoryIssues(HealthDiagnosisdiagnosis){RuntimeruntimeRuntime.getRuntime();longtotalMemoryruntime.totalMemory();longfreeMemoryruntime.freeMemory();longusedMemorytotalMemory-freeMemory;longmaxMemoryruntime.maxMemory();diagnosis.setTotalMemory(totalMemory);diagnosis.setUsedMemory(usedMemory);diagnosis.setFreeMemory(freeMemory);diagnosis.setMaxMemory(maxMemory);diagnosis.setMemoryUsage((double)usedMemory/totalMemory);// 检查内存使用率if(diagnosis.getMemoryUsage()0.8){// 80%阈值diagnosis.addIssue(HIGH_MEMORY_USAGE,内存使用率过高: (diagnosis.getMemoryUsage()*100)%);incrementIssueCounter(HIGH_MEMORY_USAGE);}// 检查内存泄漏迹象if(usedMemorymaxMemory*0.9){// 90%阈值diagnosis.addIssue(MEMORY_LEAK_SUSPECTED,疑似内存泄漏使用内存接近最大值);incrementIssueCounter(MEMORY_LEAK_SUSPECTED);}}/** * 诊断死锁 */privatevoiddiagnoseDeadlocks(HealthDiagnosisdiagnosis){ThreadMXBeanthreadMXBeanManagementFactory.getThreadMXBean();long[]deadlockedThreadsthreadMXBean.findDeadlockedThreads();if(deadlockedThreads!nulldeadlockedThreads.length0){diagnosis.addCriticalIssue(DEADLOCK_DETECTED,检测到死锁涉及线程: deadlockedThreads.length);incrementIssueCounter(DEADLOCK_DETECTED);}}/** * 诊断虚拟线程泄漏 */privatevoiddiagnoseVirtualThreadLeaks(HealthDiagnosisdiagnosis){longvirtualThreadCountgetAllThreads().stream().filter(Thread::isVirtual).count();longplatformThreadCountgetAllThreads().stream().filter(t-!t.isVirtual()).count();// 虚拟线程与平台线程比例异常if(platformThreadCount0virtualThreadCount/platformThreadCount100){diagnosis.addIssue(VIRTUAL_THREAD_LEAK,虚拟线程与平台线程比例异常: virtualThreadCount/platformThreadCount);incrementIssueCounter(VIRTUAL_THREAD_LEAK);}