当前位置: 首页 > wzjs >正文

seopc流量排名网站百度ai人工智能平台

seopc流量排名网站,百度ai人工智能平台,企业网站开发中文摘要,做视频的软件模板下载网站1. 日志通用理论 1.1 引入日志的原因 在项目开发过程中,日志的重要性不言而喻,如果没有日志的存在,就会出现以下问题: 无法确认当前系统的状态,出了问题也不知道出现了问题以后没有办法及时定位排查难以对日志进行归…

1. 日志通用理论

1.1 引入日志的原因

在项目开发过程中,日志的重要性不言而喻,如果没有日志的存在,就会出现以下问题:

  • 无法确认当前系统的状态,出了问题也不知道
  • 出现了问题以后没有办法及时定位排查
  • 难以对日志进行归纳、整理、总结等操作

1.2 日志级别

在大多数的公司规范当中,日志是有不同级别的,常见级别如下:

  • DEBUG 级别:记录一些辅助排查问题的信息,一般在线上不会打印
  • INFO 级别:中性的描述了发生了什么事情。线上一般从这个级别开始打印
  • WARN 级别:系统当中发生了一些不好的事情(偶尔触发可以接收,频繁触发需要关注)
  • ERROR 级别:系统当中出现了一些不应该出现的错误,需要及时处理

除此以外还有一些额外的日志级别:

  • DATA:有些公司用这个级别来处理接收请求与响应的日志
  • FATAL:一般用来表示及其严重的错误,需要立刻手工介入

1.3 日志参考规范

什么时候该打日志?需要打什么级别的日志?这些都没有统一的规范,这时可以参考一个宁滥勿缺原则:如果纠结是否需要打日志,那就打上;如果纠结是否要打更高级别的日志,那就打上更高级别

有些大佬的做法:

  • 统一利用 AOP 机制,记录任何跟第三方交互的请求与响应,包括数据库、缓存、RPC调用,使用 DEBUG 级别
  • 统一利用 AOP 机制,当系统接收请求以及返回响应,使用 INFO 级别日志
  • 怀疑系统出现了某些问题,偶尔触发没有问题但是频繁触发需要关注,使用 WARN 级别日志
  • 当某些条件不应该触发却触发了或者有人攻击系统的时候,需要记录 ERROR 日志

2. zap 快速入门

2.1 Go 接入日志模块

在 Go 项目当中,可以使用 zap 作为日志框架

⭐ zap 项目地址:https://github.com/uber-go/zap

Go 接入 zap 非常简单,只需要按照以下代码替换全局 Logger 对象即可:

import "go.uber.org/zap"func InitLogger() {logger, err := zap.NewDevelopment()if err != nil {panic(err)}// 替换全局Logger对象zap.ReplaceGlobals(logger)
}

2.2 webook 日志使用案例

在我们当前这个 webook 项目中,还没有接入日志模块,现在我们演示在该系统当中如何打印 DEBUG、INFO、WARN、ERROR 各种级别的日志

2.2.1 ERROR 级别演示

上图所示代码便是 ERROR 级别日志的案例,因为正常情况下调用验证码服务验证短信是不会出现错误的,因此这里可以需要使用 ERROR 级别,并且我们在这里也可以看出两个细节:

  1. 后端系统是不会也不应该把 err 等错误信息返回给前端的
  2. 对于手机号这类敏感字段,哪怕是在日志中也不应该打印出来
2.2.2 WARN 级别演示

上图所示代码便是 WARN 级别日志的案例,因为正常情况是不可能会触发一分钟内连续发送多个验证码请求的(意味着有人可能会攻击你的系统),因此偶尔出现不需要关注,频繁出现则需要关注

💡 温馨提示:同样这里不应该打印手机号等敏感字段

2.2.3 INFO 级别演示

上图所示代码便是 INFO 级别日志的案例,这次中性的记录了用户首次进行微信扫码登录,开始用户注册的流程

2.2.4 DEBUG 级别演示

上图所示代码便是 DEBUG 级别日志的案例,记录了和第三方短信服务平台交互的日志

2.3 zap 优雅实践

在上述使用案例中,我们都是通过直接使用 zap 内部全局 Logger 对象完成的操作,但是包变量无法实现不同模块日志的相互隔离,因此我们还是希望保持依赖注入的写法:

3. zap 实战

3.1 封装统一日志接口

现在的情况是业务代码与 zap 日志紧密耦合在一起,如果后续需要更换其他的日志框架,就需要同步修改业务代码,因此我们可以抽象出自己的一套统一日志接口

step1:定义统一日志接口 LoggerX

package logxtype LoggerX interface {Debug(msg string, args ...Field)Info(msg string, args ...Field)Warn(msg string, args ...Field)Error(msg string, args ...Field)
}type Field struct {Key   stringValue any
}

这里我们模拟 zap 的日志定义,参数使用 Field 结构体封装,我们还可以借鉴 zap 提供如 zap.Error、zap.String类似快速创建 Field 的方法

step2:定义 ZapLogger 的结构体实现

package logximport "go.uber.org/zap"type ZapLogger struct {logger *zap.Logger
}func NewZapLogger(logger *zap.Logger) *ZapLogger {return &ZapLogger{logger: logger,}
}func (z *ZapLogger) toArgs(args []Field) []zap.Field {var result = make([]zap.Field, len(args))for i, arg := range args {result[i] = zap.Any(arg.Key, arg.Value)}return result
}func (z *ZapLogger) Debug(msg string, args ...Field) {z.logger.Debug(msg, z.toArgs(args)...)
}func (z *ZapLogger) Info(msg string, args ...Field) {z.logger.Info(msg, z.toArgs(args)...)
}func (z *ZapLogger) Warn(msg string, args ...Field) {z.logger.Warn(msg, z.toArgs(args)...)
}func (z *ZapLogger) Error(msg string, args ...Field) {z.logger.Error(msg, z.toArgs(args)...)
}

step3:业务代码改造成使用自定义接口

type UserHandler struct {EmailCompile    *regexp.RegexpPasswordCompile *regexp.RegexpNicknameCompile *regexp.RegexpBirthdayCompile *regexp.RegexpAboutMeCompile  *regexp.Regexpsvc             service.IUserServicecodeSvc         service.CodeServicejwtHdl          IJwtHandlerlogger          logx.LoggerX
}

3.2 封装请求响应日志中间件

目前我们有一个通用功能需要解决:那就是使用 AOP 机制在系统的入口接收请求以及出口返回响应的地方记录日志,当然 Gin 框架提供的 middleware 机制本质上就是 AOP 的实现方式,即我们可以借助 Gin 的 middleware 实现这个通用日志处理功能:

package middlewareimport ("bytes""context""github.com/gin-gonic/gin""io""time"
)type LogMiddlewareBuilder struct {allowReqBody  bool                                        // 是否打印请求体allowRespBody bool                                        // 是否打印响应体logFunc       func(context context.Context, al AccessLog) // 打印逻辑
}func NewLogMiddlewareBuilder(logFunc func(context context.Context, al AccessLog)) *LogMiddlewareBuilder {return &LogMiddlewareBuilder{logFunc: logFunc,}
}func (l *LogMiddlewareBuilder) AllowReqBody() *LogMiddlewareBuilder {l.allowReqBody = truereturn l
}func (l *LogMiddlewareBuilder) AllowRespBody() *LogMiddlewareBuilder {l.allowRespBody = truereturn l
}func (l *LogMiddlewareBuilder) Build() gin.HandlerFunc {return func(ctx *gin.Context) {// 1. 打印请求var accessLog AccessLogaccessLog.url = ctx.Request.URL.String()accessLog.method = ctx.Request.Method// 究竟要不要打印请求体(可能很大)// 究竟是用info呢还是debug呢?if l.allowReqBody && ctx.Request.Body != nil {data, _ := ctx.GetRawData()// 需要将数据放回去ctx.Request.Body = io.NopCloser(bytes.NewBuffer(data))accessLog.reqBody = string(data[:1024])}// 2. 打印响应if l.allowRespBody {// 替换ctx中的responseWritectx.Writer = &responseWriter{ResponseWriter: ctx.Writer,al:             &accessLog,}}start := time.Now()defer func() {accessLog.duration = time.Since(start)l.logFunc(ctx, accessLog)}()// 放行ctx.Next()}
}// AccessLog 允许打印的日志对象
type AccessLog struct {statusCode inturl        stringmethod     stringreqBody    stringrespBody   stringduration   time.Duration
}type responseWriter struct {gin.ResponseWriteral *AccessLog
}func (w *responseWriter) Write(data []byte) (n int, err error) {w.al.respBody = string(data)return w.ResponseWriter.Write(data)
}func (w *responseWriter) WriteHeader(code int) {w.al.statusCode = codew.ResponseWriter.WriteHeader(code)
}
http://www.dtcms.com/wzjs/204386.html

相关文章:

  • 找源码的网站宁波seo推广推荐公司
  • 做食品检测的网站专业做seo推广
  • 千图网免费素材图库设计seo怎么刷排名
  • 沈阳网站网页百度搜索关键词技巧
  • 苏州做公司网站成人短期技能培训
  • 适合个人做的网站有哪些东西吗广州疫情最新动态
  • 巩义网络推广公司seo搜索引擎优化价格
  • 上海做网站汉狮网络郑州竞价托管
  • 请别人做网站有风险吗百度搜索入口
  • 怎样优化网站关键词排名靠前朝阳seo推广
  • 中国建筑土木建设有限公司网站哈尔滨网络推广
  • 营销型网站免费模板新冠咳嗽一般要咳多少天
  • 网站开发多少钱seo引擎优化服务
  • php网站中水印怎么做军事新闻
  • 深圳响应式网站找哪里站长推荐
  • 大庆建设大厦网站小网站怎么搜关键词
  • wordpress网站阿里云备案竞价恶意点击器
  • 网店美工需要掌握哪些软件搜狗整站优化
  • 怎么在招聘网站做评估碉堡了seo博客
  • 公司网站建设上海网上店铺的推广方法有哪些
  • 网站的费用多少广告联盟大全
  • 大同推广型网站建设查询关键词排名工具
  • 广东中山市做网站html网页制作代码
  • 网站优化方案书网址收录查询
  • 江阴那家网站做的好深圳搜索引擎
  • 自己做网站怎么弄品牌推广和营销推广
  • skycc营销软件soe搜索优化
  • 舟山做网站百度快速收录网站
  • 企业网站搭建的优点全网线报 实时更新
  • 莱芜都市人才网seo如何优化关键词上首页