| 496 | } |
| 497 | |
| 498 | func (h logHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { |
| 499 | // If there's already a logHandler up the chain, skip this one. |
| 500 | ctx := r.Context() |
| 501 | if errCallback.Has(ctx) { |
| 502 | h.h.ServeHTTP(w, r) |
| 503 | return |
| 504 | } |
| 505 | |
| 506 | msg := AccessLogRecord{ |
| 507 | Time: h.opts.Now(), |
| 508 | RemoteAddr: r.RemoteAddr, |
| 509 | Proto: r.Proto, |
| 510 | TLS: r.TLS != nil, |
| 511 | Host: r.Host, |
| 512 | Method: r.Method, |
| 513 | RequestURI: r.URL.RequestURI(), |
| 514 | UserAgent: r.UserAgent(), |
| 515 | Referer: r.Referer(), |
| 516 | RequestID: RequestIDFromContext(r.Context()), |
| 517 | } |
| 518 | |
| 519 | if bs := h.opts.BucketedStats; bs != nil && bs.Started != nil && bs.Finished != nil { |
| 520 | bucket := bs.bucketForRequest(r) |
| 521 | var startRecorded bool |
| 522 | switch v := bs.Started.Map.Get(bucket).(type) { |
| 523 | case *expvar.Int: |
| 524 | // If we've already seen this bucket for, count it immediately. |
| 525 | // Otherwise, for newly seen paths, only count retroactively |
| 526 | // (so started-finished doesn't go negative) so we don't fill |
| 527 | // this LabelMap up with internet scanning spam. |
| 528 | v.Add(1) |
| 529 | startRecorded = true |
| 530 | } |
| 531 | defer func() { |
| 532 | // Only increment metrics for buckets that result in good HTTP statuses |
| 533 | // or when we know the start was already counted. |
| 534 | // Otherwise they get full of internet scanning noise. Only filtering 404 |
| 535 | // gets most of the way there but there are also plenty of URLs that are |
| 536 | // almost right but result in 400s too. Seem easier to just only ignore |
| 537 | // all 4xx and 5xx. |
| 538 | if startRecorded { |
| 539 | bs.Finished.Add(bucket, 1) |
| 540 | } else if msg.Code < 400 { |
| 541 | // This is the first non-error request for this bucket, |
| 542 | // so count it now retroactively. |
| 543 | bs.Started.Add(bucket, 1) |
| 544 | bs.Finished.Add(bucket, 1) |
| 545 | } |
| 546 | }() |
| 547 | } |
| 548 | |
| 549 | if fn := h.opts.OnStart; fn != nil { |
| 550 | fn(r, msg) |
| 551 | } |
| 552 | |
| 553 | // Let errorHandler tell us what error it wrote to the client. |
| 554 | r = r.WithContext(errCallback.WithValue(ctx, func(e HTTPError) { |
| 555 | // Keep the deepest error. |