一个有故事的可乐瓶

评论8

  • 谢谢你给我的改变,谢谢你给我的经验。
    加油
    坚持
    2020-07-13 22:54:21 回复
  • 2020-07-16 18:15:49 回复
  • 2020-07-16 18:16:02 回复
  • 2020-07-20 11:05:57 回复
  • 喜欢一个不喜欢你的人,真的太累了
    2020-08-03 10:01:10 回复
  • package middlewares
    import (
    "fmt"
    "net/http"
    "regexp"
    "sync"
    "time"
    _ "git.icarephone.com/icf/com.git/logger"
    "github.com/prometheus/client_golang/prometheus"
    "github.com/prometheus/client_golang/prometheus/promhttp"
    "github.com/valyala/fasthttp"
    "github.com/valyala/fasthttp/fasthttpadaptor"
    )
    /*
    * 指标监控处理中间件
    ————————————————————————
    */
    const namespace = "service"
    var (
    labels = []string{"status", "endpoint", "method"}
    requestHandlerPool sync.Pool
    uptime = prometheus.NewCounterVec(
    prometheus.CounterOpts{
    Namespace: namespace,
    Name: "uptime",
    Help: "HTTP service uptime.",
    }, nil,
    )
    reqCount = prometheus.NewCounterVec(
    prometheus.CounterOpts{
    Namespace: namespace,
    Name: "http_request_count_total",
    Help: "Total number of HTTP requests made.",
    }, labels,
    )
    reqDuration = prometheus.NewHistogramVec(
    prometheus.HistogramOpts{
    Namespace: namespace,
    Name: "http_request_duration_seconds",
    Help: "HTTP request latencies in seconds.",
    }, labels,
    )
    reqSizeBytes = prometheus.NewSummaryVec(
    prometheus.SummaryOpts{
    Namespace: namespace,
    Name: "http_request_size_bytes",
    Help: "HTTP request sizes in bytes.",
    }, labels,
    )
    respSizeBytes = prometheus.NewSummaryVec(
    prometheus.SummaryOpts{
    Namespace: namespace,
    Name: "http_response_size_bytes",
    Help: "HTTP request sizes in bytes.",
    }, labels,
    )
    )
    // init registers the prometheus metrics
    func init() {
    prometheus.MustRegister(uptime, reqCount, reqDuration, reqSizeBytes, respSizeBytes)
    go recordUptime()
    }
    // recordUptime increases service uptime per second.
    func recordUptime() {
    for range time.Tick(time.Second) {
    uptime.WithLabelValues().Inc()
    }
    }
    // calcRequestSize returns the size of request object.
    func calcRequestSize(r *http.Request) float64 {
    size := 0
    if r.URL != nil {
    size = len(r.URL.String())
    }
    size += len(r.Method)
    size += len(r.Proto)
    for name, values := range r.Header {
    size += len(name)
    for _, value := range values {
    size += len(value)
    }
    }
    size += len(r.Host)
    // r.Form and r.MultipartForm are assumed to be included in r.URL.
    if r.ContentLength != -1 {
    size += int(r.ContentLength)
    }
    return float64(size)
    }
    // PromOpts represents the Prometheus middleware Options.
    // It is used for filtering labels by regex.
    type PromOpts struct {
    ExcludeRegexStatus string
    ExcludeRegexEndpoint string
    ExcludeRegexMethod string
    }
    var defaultPromOpts = &PromOpts{}
    func acquireRequestFromPool() *fasthttp.Request {
    rp := requestHandlerPool.Get()
    if rp == nil {
    return new(fasthttp.Request)
    }
    frc := rp.(*fasthttp.Request)
    return frc
    }
    // Idea is from https://github.com/DanielHeckrath/gin-prometheus/blob/master/gin_prometheus.go and https://github.com/zsais/go-gin-prometheus/blob/master/middleware.go
    func computeApproximateRequestSize(ctx *fasthttp.Request, out chan int) {
    s := 0
    if ctx.URI() != nil {
    s += len(ctx.URI().Path())
    s += len(ctx.URI().Host())
    }
    s += len(ctx.Header.Method())
    s += len("HTTP/1.1")
    ctx.Header.VisitAll(func(key, value []byte) {
    if string(key) != "Host" {
    s += len(key) + len(value)
    }
    })
    if ctx.Header.ContentLength() != -1 {
    s += ctx.Header.ContentLength()
    }
    out <- s
    }
    // checkLabel returns the match result of labels.
    // Return true if regex-pattern compiles failed.
    func (po *PromOpts) checkLabel(label, pattern string) bool {
    if pattern == "" {
    return true
    }
    matched, err := regexp.MatchString(pattern, label)
    if err != nil {
    return true
    }
    return !matched
    }
    func PROM(next fasthttp.RequestHandler) fasthttp.RequestHandler {
    promOpts := defaultPromOpts
    return fasthttp.RequestHandler(func(ctx *fasthttp.RequestCtx) {
    reqSize := make(chan int)
    frc := acquireRequestFromPool()
    ctx.Request.CopyTo(frc)
    go computeApproximateRequestSize(frc, reqSize)
    start := time.Now()
    next(ctx)
    status := fmt.Sprintf("%d", ctx.Response.StatusCode())
    endpoint := string(ctx.Request.URI().Path())
    method := string(ctx.Method())
    lvs := []string{status, endpoint, method}
    isOk := promOpts.checkLabel(status, promOpts.ExcludeRegexStatus) &&
    promOpts.checkLabel(endpoint, promOpts.ExcludeRegexEndpoint) &&
    promOpts.checkLabel(method, promOpts.ExcludeRegexMethod)
    if !isOk {
    return
    }
    reqCount.WithLabelValues(lvs...).Inc()
    reqDuration.WithLabelValues(lvs...).Observe(time.Since(start).Seconds())
    reqSizeBytes.WithLabelValues(lvs...).Observe(float64(<-reqSize))
    respSizeBytes.WithLabelValues(lvs...).Observe(float64(len(ctx.Response.Body())))
    })
    }
    // PromHandler wrappers the standard http.Handler to gin.HandlerFunc
    func PromHandler() fasthttp.RequestHandler {
    return fasthttpadaptor.NewFastHTTPHandler(promhttp.Handler())
    }

    2020-08-12 17:41:11 回复
  • 2020-09-11 14:03:42 回复
  • 突然觉得活着是一件辛苦的事
    2020-09-23 17:51:51 回复
评论请先登录

最近热帖

  1. 基于 Harbor 搭建 Docker 私有镜像仓库 710708
  2. PPS代理节点池 272254
  3. PPS代理节点池② 181585
  4. PPS代理节点池③ 149607
  5. 订阅池记录 128343
  6. V2ray免费账号 12127
  7. WEB代理地址 3525
  8. 全栈开发笔记 3098
  9. GITHUB项目 2344
  10. 百度的无刷新搜索之PJAX 2285

近期热议

  1. GITHUB项目 55
  2. PPS代理节点池 50
  3. WEB代理地址 43
  4. 全栈开发笔记 42
  5. ROBOT机器人之路 31
  6. PPS代理节点池③ 26
  7. PPS代理节点池② 20
  8. C++回归之路 19
  9. OCR识别探索 16
  10. 错误笔记本 14