github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/log/handler_glog.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 12:09:41</date>
    10  //</624342646499840000>
    11  
    12  
    13  package log
    14  
    15  import (
    16  	"errors"
    17  	"fmt"
    18  	"regexp"
    19  	"runtime"
    20  	"strconv"
    21  	"strings"
    22  	"sync"
    23  	"sync/atomic"
    24  )
    25  
    26  //当用户vmodule模式无效时返回errvmodulesyntax。
    27  var errVmoduleSyntax = errors.New("expect comma-separated list of filename=N")
    28  
    29  //当用户回溯模式无效时,返回errTraceSyntax。
    30  var errTraceSyntax = errors.New("expect file.go:234")
    31  
    32  //Gloghandler是一个日志处理程序,模拟谷歌的过滤功能。
    33  //glog logger:设置全局日志级别;用callsite模式覆盖
    34  //匹配;并在特定位置请求回溯。
    35  type GlogHandler struct {
    36  origin Handler //此包装的原始处理程序
    37  
    38  level     uint32 //当前日志级别,可原子访问
    39  override  uint32 //标记是否使用原子可访问的重写
    40  backtrace uint32 //标记是否设置回溯位置
    41  
    42  patterns  []pattern       //要重写的模式的当前列表
    43  siteCache map[uintptr]Lvl //调用站点模式计算的缓存
    44  location  string          //文件:进行堆栈转储的行位置
    45  lock      sync.RWMutex    //锁定保护覆盖模式列表
    46  }
    47  
    48  //newgloghandler创建了一个新的日志处理程序,其过滤功能与
    49  //谷歌的Glog日志。返回的处理程序实现处理程序。
    50  func NewGlogHandler(h Handler) *GlogHandler {
    51  	return &GlogHandler{
    52  		origin: h,
    53  	}
    54  }
    55  
    56  //sethandler更新处理程序以将记录写入指定的子处理程序。
    57  func (h *GlogHandler) SetHandler(nh Handler) {
    58  	h.origin = nh
    59  }
    60  
    61  //模式包含vmodule选项的筛选器,保持详细级别
    62  //和要匹配的文件模式。
    63  type pattern struct {
    64  	pattern *regexp.Regexp
    65  	level   Lvl
    66  }
    67  
    68  //冗长设置了发光的冗长天花板。单个包装的冗长程度
    69  //源文件可以使用vmodule来提升。
    70  func (h *GlogHandler) Verbosity(level Lvl) {
    71  	atomic.StoreUint32(&h.level, uint32(level))
    72  }
    73  
    74  //vmodule设置glog冗长模式。
    75  //
    76  //参数的语法是以逗号分隔的pattern=n列表,其中
    77  //模式是文本文件名或“glob”模式匹配,n是v级别。
    78  //
    79  //例如:
    80  //
    81  //pattern=“gopher.go=3”
    82  //在所有名为“gopher.go”的go文件中将v级别设置为3
    83  //
    84  //模式=“FoO=3”
    85  //将导入路径以“foo”结尾的任何包的所有文件中的v设置为3
    86  //
    87  /*pattern=“foo/*=3”
    88  //在导入路径包含“foo”的任何包的所有文件中,将v设置为3
    89  func(h*gloghandler)vmodule(ruleset string)错误
    90   var过滤器[]模式
    91   对于u,规则:=range strings.split(ruleset,“,”)
    92    //可以忽略尾随逗号等空字符串
    93    如果len(rule)==0
    94     持续
    95    }
    96    //确保我们有模式=级别筛选规则
    97    部分:=strings.split(rule,“=”)
    98    如果莱恩(零件)!= 2 {
    99     返回errvmodulesyntax
   100    }
   101    零件[0]=字符串.trimspace(零件[0])
   102    部件[1]=字符串。Trimspace(部件[1])
   103    如果len(零件[0])=0 len(零件[1])=0
   104     返回errvmodulesyntax
   105    }
   106    //分析级别,如果正确,则组装筛选规则
   107    级别,错误:=strconv.atoi(部件[1])
   108    如果犯错!= nIL{
   109     返回errvmodulesyntax
   110    }
   111    如果水平<=0
   112     继续//忽略。这是无害的,但没有必要支付管理费用。
   113    }
   114    //将规则模式编译为正则表达式
   115    匹配器=:“*”
   116    对于u,comp:=range strings.split(parts[0],“/”)
   117     如果comp=“*”
   118      匹配器+=“(/.*)?”
   119     其他,如果有!=“{”
   120      matcher+=“/”+regexp.quoteteta(comp)
   121     }
   122    }
   123    如果!字符串.hassuffix(部件[0],“.go”);
   124     Matcher+=“/[^/]+\\.go”
   125    }
   126    matcher=matcher+“$”
   127  
   128    re,:=regexp.compile(matcher)
   129    filter=append(filter,pattern re,lvl(level))
   130   }
   131   //换掉新过滤系统的vmodule模式
   132   H.Lo.C.()
   133   延迟h.lock.unlock()
   134  
   135   h.patterns=过滤器
   136   h.sitecache=make(映射[uintptr]lvl)
   137   atomic.storeuint32(&h.override,uint32(len(filter)))
   138  
   139   返回零
   140  }
   141  
   142  //backtraceat设置glog backtrace位置。当设置为文件和行时
   143  //保存日志语句的数字,堆栈跟踪将写入信息
   144  //每当执行命中该语句时记录。
   145  / /
   146  //与vmodule不同,“.go”必须存在。
   147  func(h*gloghandler)backtraceat(location string)错误
   148   //确保回溯位置包含两个非空元素
   149   部件:=strings.split(位置,“:”)
   150   如果莱恩(零件)!= 2 {
   151    返回errtraceSyntax
   152   }
   153   零件[0]=字符串.trimspace(零件[0])
   154   部件[1]=字符串。Trimspace(部件[1])
   155   如果len(零件[0])=0 len(零件[1])=0
   156    返回errtraceSyntax
   157   }
   158   //确保.go前缀存在且该行有效
   159   如果!字符串.hassuffix(部件[0],“.go”);
   160    返回errtraceSyntax
   161   }
   162   如果uuErr:=strconv.atoi(第[1]部分);Err!= nIL{
   163    返回errtraceSyntax
   164   }
   165   //一切似乎都有效
   166   H.Lo.C.()
   167   延迟h.lock.unlock()
   168  
   169   H.位置=位置
   170   atomic.storeuint32(&h.backtrace,uint32(len(location)))
   171  
   172   返回零
   173  }
   174  
   175  //日志实现handler.log,通过全局、本地筛选日志记录
   176  //和回溯过滤器,如果允许它通过,最后发出它。
   177  func(h*gloghandler)日志(r*record)错误
   178   //如果请求回溯,请检查这是否是调用站点
   179   如果atomic.loaduint32(&h.backtrace)>0
   180    //这里的一切都很慢。尽管我们可以缓存呼叫站点
   181    //和vmodule一样,回溯非常罕见,不值得额外增加
   182    / /复杂性。
   183    H.锁定()
   184    匹配:=h.location==r.call.string()
   185    h.lock.runlock()。
   186  
   187    如果匹配{
   188     //调用站点匹配,将日志级别提升为INFO并收集堆栈
   189     吕林佛
   190  
   191     buf:=make([]字节,1024*1024)
   192     buf=buf[:runtime.stack(buf,true)]
   193     r.msg+=“\n\n”+字符串(buf)
   194    }
   195   }
   196   //如果全局日志级别允许,则快速跟踪日志记录
   197   如果atomic.loadunt32(&h.level)>=uint32(r.lvl)
   198    返回h.origin.log(r)
   199   }
   200   //如果不存在本地重写,则快速跟踪跳过
   201   如果atomic.loaduint32(&h.override)==0
   202    返回零
   203   }
   204   //检查调用站点缓存中以前计算的日志级别
   205   H.锁定()
   206   lvl,确定:=h.sitecache[r.call.pc()]
   207   h.lock.runlock()。
   208  
   209   //如果我们还没有缓存调用站点,请计算它
   210   如果!好吧{
   211    H.Lo.C.()
   212    对于u,规则:=范围h.模式
   213     if rule.pattern.matchString(fmt.sprintf(“%+s”,r.call))
   214      h.sitecache[r.call.pc()],lvl,ok=rule.level,rule.level,真
   215      打破
   216     }
   217    }
   218    //如果没有匹配的规则,记得下次删除日志
   219    如果!好吧{
   220     h.sitecache[r.call.pc()]=0
   221    }
   222    锁定()
   223   }
   224   如果lvl>=r.lvl
   225    返回h.origin.log(r)
   226   }
   227   返回零
   228  }
   229