//StringService的结构体定义、以及输入输出参数结构定义和stringsvc1中是一样的
日志
//loggingMiddleware 这个方法的缺点在于无论是uppercase还是count参数都是uppercase,通用的就没有办法针对每个功能进行定制日志。
//由于StringService是一个接口,所以我们只需要定义一个新的类型包装之前的StringService,实现StringService的接口,在实现过程中加入log。
type logMiddleware struct {
logger log.Logger
next StringService
}
func (mw logMiddleware) Uppercase(ctx context.Context, s string) (output string, err error) {
defer func(begin time.Time) {
mw.logger.Log(
"logmethod", "uppercase",
"input", s,
"output", output,
"err", err,
"took", time.Since(begin),
)
}(time.Now())
output, err = mw.next.Uppercase(ctx, s)
return
}
func (mw logMiddleware) Count(ctx context.Context, s string) (n int) {
defer func(begin time.Time) {
mw.logger.Log(
"logmethod", "uppercase",
"input", s,
"output", n,
// "err", err,
"took", time.Since(begin),
)
}(time.Now())
n = mw.next.Count(ctx, s)
return
}
添加instrument
instrumentation means using package metrics to record statistics about your service’s runtime behavior. Counting the number of jobs processed, recording the duration of requests after they’ve finished, and tracking the number of in-flight operations would all be considered instrumentation.
说白了就是对服务运行情况的统计
type instrumentingMiddleware struct {
requestCount metrics.Counter
requestLatency metrics.Histogram //官网文档这里似乎错了
countResult metrics.Histogram
next StringService
}
func (mw instrumentingMiddleware) Uppercase(ctx context.Context, s string) (output string, err error) {
defer func(begin time.Time) {
//官网文档是 metrics.Field 似乎是错的
//methodFiled 要和 main中的fieldKeys保持一致
methodField := []string{
"method", "uppercase", "error", fmt.Sprintf("%T", err != nil)}
mw.requestCount.With(methodField...).Add(1)
mw.requestLatency.With(methodField...).Observe(time.Since(begin).Seconds())
}(time.Now())
output, err = mw.next.Uppercase(ctx, s)
return
}
func (mw instrumentingMiddleware) Count(ctx context.Context, s string) (n int) {
defer func(begin time.Time) {
//官网文档里面是 metrics.Field 似乎是错的
methodField := []string{
"method", "count", "error", "false"}
mw.requestCount.With(methodField...).Add(1)
mw.requestLatency.With(methodField...).Observe(time.Since(begin).Seconds())
//文档里面是int64是错的,
mw.countResult.Observe(float64(n))
}(time.Now())
n = mw.next.Count(ctx, s)
return
}
对于Histograms和Summary的区别
// Note that Histograms, in contrast to Summaries, can be aggregated with the
// Prometheus query language (see the documentation for detailed
// procedures). However, Histograms require the user to pre-define suitable
// buckets, and they are in general less accurate. The Observe method of a
// Histogram has a very low performance overhead in comparison with the Observe
// method of a Summary.
// A Summary captures individual observations from an event or sample stream and
// summarizes them in a manner similar to traditional summary statistics: 1. sum
// of observations, 2. observation count, 3. rank estimations.
//
// A typical use-case is the observation of request latencies. By default, a
// Summary provides the median, the 90th and the 99th percentile of the latency
// as rank estimations. However, the default behavior will change in the
// upcoming v0.10 of the library. There will be no rank estiamtions at all by
// default. For a sane transition, it is recommended to set the desired rank
// estimations explicitly.
//
// Note