Blame view

go/src/themaru/vendor/github.com/gin-gonic/gin/logger.go 6.94 KB
476d2547e   김태훈   태마루 시스템 설정 / 업데이트...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
  // Copyright 2014 Manu Martinez-Almeida.  All rights reserved.
  // Use of this source code is governed by a MIT style
  // license that can be found in the LICENSE file.
  
  package gin
  
  import (
  	"fmt"
  	"io"
  	"net/http"
  	"os"
  	"time"
  
  	"github.com/mattn/go-isatty"
  )
  
  type consoleColorModeValue int
  
  const (
  	autoColor consoleColorModeValue = iota
  	disableColor
  	forceColor
  )
  
  var (
  	green            = string([]byte{27, 91, 57, 55, 59, 52, 50, 109})
  	white            = string([]byte{27, 91, 57, 48, 59, 52, 55, 109})
  	yellow           = string([]byte{27, 91, 57, 48, 59, 52, 51, 109})
  	red              = string([]byte{27, 91, 57, 55, 59, 52, 49, 109})
  	blue             = string([]byte{27, 91, 57, 55, 59, 52, 52, 109})
  	magenta          = string([]byte{27, 91, 57, 55, 59, 52, 53, 109})
  	cyan             = string([]byte{27, 91, 57, 55, 59, 52, 54, 109})
  	reset            = string([]byte{27, 91, 48, 109})
  	consoleColorMode = autoColor
  )
  
  // LoggerConfig defines the config for Logger middleware.
  type LoggerConfig struct {
  	// Optional. Default value is gin.defaultLogFormatter
  	Formatter LogFormatter
  
  	// Output is a writer where logs are written.
  	// Optional. Default value is gin.DefaultWriter.
  	Output io.Writer
  
  	// SkipPaths is a url path array which logs are not written.
  	// Optional.
  	SkipPaths []string
  }
  
  // LogFormatter gives the signature of the formatter function passed to LoggerWithFormatter
  type LogFormatter func(params LogFormatterParams) string
  
  // LogFormatterParams is the structure any formatter will be handed when time to log comes
  type LogFormatterParams struct {
  	Request *http.Request
  
  	// TimeStamp shows the time after the server returns a response.
  	TimeStamp time.Time
  	// StatusCode is HTTP response code.
  	StatusCode int
  	// Latency is how much time the server cost to process a certain request.
  	Latency time.Duration
  	// ClientIP equals Context's ClientIP method.
  	ClientIP string
  	// Method is the HTTP method given to the request.
  	Method string
  	// Path is a path the client requests.
  	Path string
  	// ErrorMessage is set if error has occurred in processing the request.
  	ErrorMessage string
  	// isTerm shows whether does gin's output descriptor refers to a terminal.
  	isTerm bool
  	// BodySize is the size of the Response Body
  	BodySize int
  	// Keys are the keys set on the request's context.
  	Keys map[string]interface{}
  }
  
  // StatusCodeColor is the ANSI color for appropriately logging http status code to a terminal.
  func (p *LogFormatterParams) StatusCodeColor() string {
  	code := p.StatusCode
  
  	switch {
  	case code >= http.StatusOK && code < http.StatusMultipleChoices:
  		return green
  	case code >= http.StatusMultipleChoices && code < http.StatusBadRequest:
  		return white
  	case code >= http.StatusBadRequest && code < http.StatusInternalServerError:
  		return yellow
  	default:
  		return red
  	}
  }
  
  // MethodColor is the ANSI color for appropriately logging http method to a terminal.
  func (p *LogFormatterParams) MethodColor() string {
  	method := p.Method
  
  	switch method {
  	case "GET":
  		return blue
  	case "POST":
  		return cyan
  	case "PUT":
  		return yellow
  	case "DELETE":
  		return red
  	case "PATCH":
  		return green
  	case "HEAD":
  		return magenta
  	case "OPTIONS":
  		return white
  	default:
  		return reset
  	}
  }
  
  // ResetColor resets all escape attributes.
  func (p *LogFormatterParams) ResetColor() string {
  	return reset
  }
  
  // IsOutputColor indicates whether can colors be outputted to the log.
  func (p *LogFormatterParams) IsOutputColor() bool {
  	return consoleColorMode == forceColor || (consoleColorMode == autoColor && p.isTerm)
  }
  
  // defaultLogFormatter is the default log format function Logger middleware uses.
  var defaultLogFormatter = func(param LogFormatterParams) string {
  	var statusColor, methodColor, resetColor string
  	if param.IsOutputColor() {
  		statusColor = param.StatusCodeColor()
  		methodColor = param.MethodColor()
  		resetColor = param.ResetColor()
  	}
  
  	if param.Latency > time.Minute {
  		// Truncate in a golang < 1.8 safe way
  		param.Latency = param.Latency - param.Latency%time.Second
  	}
  	return fmt.Sprintf("[GIN] %v |%s %3d %s| %13v | %15s |%s %-7s %s %s
  %s",
  		param.TimeStamp.Format("2006/01/02 - 15:04:05"),
  		statusColor, param.StatusCode, resetColor,
  		param.Latency,
  		param.ClientIP,
  		methodColor, param.Method, resetColor,
  		param.Path,
  		param.ErrorMessage,
  	)
  }
  
  // DisableConsoleColor disables color output in the console.
  func DisableConsoleColor() {
  	consoleColorMode = disableColor
  }
  
  // ForceConsoleColor force color output in the console.
  func ForceConsoleColor() {
  	consoleColorMode = forceColor
  }
  
  // ErrorLogger returns a handlerfunc for any error type.
  func ErrorLogger() HandlerFunc {
  	return ErrorLoggerT(ErrorTypeAny)
  }
  
  // ErrorLoggerT returns a handlerfunc for a given error type.
  func ErrorLoggerT(typ ErrorType) HandlerFunc {
  	return func(c *Context) {
  		c.Next()
  		errors := c.Errors.ByType(typ)
  		if len(errors) > 0 {
  			c.JSON(-1, errors)
  		}
  	}
  }
  
  // Logger instances a Logger middleware that will write the logs to gin.DefaultWriter.
  // By default gin.DefaultWriter = os.Stdout.
  func Logger() HandlerFunc {
  	return LoggerWithConfig(LoggerConfig{})
  }
  
  // LoggerWithFormatter instance a Logger middleware with the specified log format function.
  func LoggerWithFormatter(f LogFormatter) HandlerFunc {
  	return LoggerWithConfig(LoggerConfig{
  		Formatter: f,
  	})
  }
  
  // LoggerWithWriter instance a Logger middleware with the specified writer buffer.
  // Example: os.Stdout, a file opened in write mode, a socket...
  func LoggerWithWriter(out io.Writer, notlogged ...string) HandlerFunc {
  	return LoggerWithConfig(LoggerConfig{
  		Output:    out,
  		SkipPaths: notlogged,
  	})
  }
  
  // LoggerWithConfig instance a Logger middleware with config.
  func LoggerWithConfig(conf LoggerConfig) HandlerFunc {
  	formatter := conf.Formatter
  	if formatter == nil {
  		formatter = defaultLogFormatter
  	}
  
  	out := conf.Output
  	if out == nil {
  		out = DefaultWriter
  	}
  
  	notlogged := conf.SkipPaths
  
  	isTerm := true
  
  	if w, ok := out.(*os.File); !ok || os.Getenv("TERM") == "dumb" ||
  		(!isatty.IsTerminal(w.Fd()) && !isatty.IsCygwinTerminal(w.Fd())) {
  		isTerm = false
  	}
  
  	var skip map[string]struct{}
  
  	if length := len(notlogged); length > 0 {
  		skip = make(map[string]struct{}, length)
  
  		for _, path := range notlogged {
  			skip[path] = struct{}{}
  		}
  	}
  
  	return func(c *Context) {
  		// Start timer
  		start := time.Now()
  		path := c.Request.URL.Path
  		raw := c.Request.URL.RawQuery
  
  		// Process request
  		c.Next()
  
  		// Log only when path is not being skipped
  		if _, ok := skip[path]; !ok {
  			param := LogFormatterParams{
  				Request: c.Request,
  				isTerm:  isTerm,
  				Keys:    c.Keys,
  			}
  
  			// Stop timer
  			param.TimeStamp = time.Now()
  			param.Latency = param.TimeStamp.Sub(start)
  
  			param.ClientIP = c.ClientIP()
  			param.Method = c.Request.Method
  			param.StatusCode = c.Writer.Status()
  			param.ErrorMessage = c.Errors.ByType(ErrorTypePrivate).String()
  
  			param.BodySize = c.Writer.Size()
  
  			if raw != "" {
  				path = path + "?" + raw
  			}
  
  			param.Path = path
  
  			fmt.Fprint(out, formatter(param))
  		}
  	}
  }