handlersmisc.go - hugo - [fork] hugo port for 9front
(HTM) git clone https://git.drkhsh.at/hugo.git
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) Submodules
(DIR) README
(DIR) LICENSE
---
handlersmisc.go (3439B)
---
1 // Copyright 2024 The Hugo Authors. All rights reserved.
2 // Some functions in this file (see comments) is based on the Go source code,
3 // copyright The Go Authors and governed by a BSD-style license.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15
16 package loggers
17
18 import (
19 "fmt"
20 "strings"
21 "sync"
22
23 "github.com/bep/logg"
24 "github.com/gohugoio/hugo/common/hashing"
25 )
26
27 // PanicOnWarningHook panics on warnings.
28 var PanicOnWarningHook = func(e *logg.Entry) error {
29 if e.Level != logg.LevelWarn {
30 return nil
31 }
32 panic(e.Message)
33 }
34
35 func newLogLevelCounter() *logLevelCounter {
36 return &logLevelCounter{
37 counters: make(map[logg.Level]int),
38 }
39 }
40
41 func newLogOnceHandler(threshold logg.Level) *logOnceHandler {
42 return &logOnceHandler{
43 threshold: threshold,
44 seen: make(map[uint64]bool),
45 }
46 }
47
48 func newStopHandler(h ...logg.Handler) *stopHandler {
49 return &stopHandler{
50 handlers: h,
51 }
52 }
53
54 func newSuppressStatementsHandler(statements map[string]bool) *suppressStatementsHandler {
55 return &suppressStatementsHandler{
56 statements: statements,
57 }
58 }
59
60 type logLevelCounter struct {
61 mu sync.RWMutex
62 counters map[logg.Level]int
63 }
64
65 func (h *logLevelCounter) HandleLog(e *logg.Entry) error {
66 h.mu.Lock()
67 defer h.mu.Unlock()
68 h.counters[e.Level]++
69 return nil
70 }
71
72 var errStop = fmt.Errorf("stop")
73
74 type logOnceHandler struct {
75 threshold logg.Level
76 mu sync.Mutex
77 seen map[uint64]bool
78 }
79
80 func (h *logOnceHandler) HandleLog(e *logg.Entry) error {
81 if e.Level < h.threshold {
82 // We typically only want to enable this for warnings and above.
83 // The common use case is that many go routines may log the same error.
84 return nil
85 }
86 h.mu.Lock()
87 defer h.mu.Unlock()
88 hash := hashing.HashUint64(e.Level, e.Message, e.Fields)
89 if h.seen[hash] {
90 return errStop
91 }
92 h.seen[hash] = true
93 return nil
94 }
95
96 func (h *logOnceHandler) reset() {
97 h.mu.Lock()
98 defer h.mu.Unlock()
99 h.seen = make(map[uint64]bool)
100 }
101
102 type stopHandler struct {
103 handlers []logg.Handler
104 }
105
106 // HandleLog implements logg.Handler.
107 func (h *stopHandler) HandleLog(e *logg.Entry) error {
108 for _, handler := range h.handlers {
109 if err := handler.HandleLog(e); err != nil {
110 if err == errStop {
111 return nil
112 }
113 return err
114 }
115 }
116 return nil
117 }
118
119 type suppressStatementsHandler struct {
120 statements map[string]bool
121 }
122
123 func (h *suppressStatementsHandler) HandleLog(e *logg.Entry) error {
124 for _, field := range e.Fields {
125 if field.Name == FieldNameStatementID {
126 if h.statements[field.Value.(string)] {
127 return errStop
128 }
129 }
130 }
131 return nil
132 }
133
134 // whiteSpaceTrimmer creates a new log handler that trims whitespace from log messages and string fields.
135 func whiteSpaceTrimmer() logg.Handler {
136 return logg.HandlerFunc(func(e *logg.Entry) error {
137 e.Message = strings.TrimSpace(e.Message)
138 for i, field := range e.Fields {
139 if s, ok := field.Value.(string); ok {
140 e.Fields[i].Value = strings.TrimSpace(s)
141 }
142 }
143 return nil
144 })
145 }