169 lines
3.8 KiB
Go
169 lines
3.8 KiB
Go
// Copyright 2019 The Gitea Authors. All rights reserved.
|
|
// Use of this source code is governed by a MIT-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package log
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"net/url"
|
|
"strings"
|
|
)
|
|
|
|
// HTTPLogger implements LoggerProvider
|
|
// it writes messages across HTTP as GETs or POSTs with JSON
|
|
type HTTPLogger struct {
|
|
WriterLogger
|
|
URL string `json:"url"`
|
|
Method string `json:"method"`
|
|
Header map[string][]string `json:"header"`
|
|
}
|
|
|
|
// NewHTTP creates a new HTTPLogger returning as a LoggerProvider
|
|
func NewHTTP() LoggerProvider {
|
|
logger := new(HTTPLogger)
|
|
logger.Level = TRACE
|
|
return logger
|
|
}
|
|
|
|
// Init inits http writer with json config.
|
|
func (log *HTTPLogger) Init(jsonconfig string) error {
|
|
err := json.Unmarshal([]byte(jsonconfig), log)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if _, err := url.Parse(log.URL); err != nil {
|
|
return err
|
|
}
|
|
if log.Method == "POST" {
|
|
log.Header["Content-Type"] = []string{"application/json"}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// LogEvent logs the event to HTTP
|
|
func (log *HTTPLogger) LogEvent(event *Event) error {
|
|
if log.Level > event.level {
|
|
return nil
|
|
}
|
|
if !log.Match(event) {
|
|
return nil
|
|
}
|
|
valueMap := map[string]string{}
|
|
|
|
t := event.time
|
|
if log.Prefix != "" {
|
|
valueMap["prefix"] = log.Prefix
|
|
}
|
|
if log.Flags&LUTC != 0 {
|
|
t = t.UTC()
|
|
}
|
|
if log.Flags&Ldate != 0 {
|
|
year, month, day := t.Date()
|
|
valueMap["date"] = fmt.Sprintf("%4d/%2d/%2d", year, month, day)
|
|
}
|
|
if log.Flags&(Ltime|Lmicroseconds) != 0 {
|
|
hour, min, sec := t.Clock()
|
|
if log.Flags&Lmicroseconds != 0 {
|
|
valueMap["time"] = fmt.Sprintf("%2d:%2d:%2d.%6d", hour, min, sec, t.Nanosecond()/1e3)
|
|
} else {
|
|
valueMap["time"] = fmt.Sprintf("%2d:%2d:%2d", hour, min, sec)
|
|
}
|
|
}
|
|
if log.Flags&(Lshortfile|Llongfile) != 0 {
|
|
file := event.filename
|
|
if log.Flags&Lmedfile == Lmedfile {
|
|
startIndex := len(file) - 20
|
|
if startIndex > 0 {
|
|
file = "..." + file[startIndex:]
|
|
}
|
|
} else if log.Flags&Lshortfile != 0 {
|
|
startIndex := strings.LastIndexByte(file, '/')
|
|
if startIndex > 0 && startIndex < len(file) {
|
|
file = file[startIndex+1:]
|
|
}
|
|
}
|
|
valueMap["file"] = file
|
|
}
|
|
if log.Flags&(Lfuncname|Lshortfuncname) != 0 {
|
|
funcname := event.caller
|
|
if log.Flags&Lshortfuncname != 0 {
|
|
lastIndex := strings.LastIndexByte(funcname, '.')
|
|
if lastIndex > 0 && len(funcname) > lastIndex+1 {
|
|
funcname = funcname[lastIndex+1:]
|
|
}
|
|
}
|
|
valueMap["funcname"] = funcname
|
|
}
|
|
if log.Flags&(Llevel|Llevelinitial) != 0 {
|
|
level := strings.ToUpper(event.level.String())
|
|
if log.Flags&Llevelinitial != 0 {
|
|
valueMap["level"] = level[0:1]
|
|
} else {
|
|
valueMap["level"] = level
|
|
}
|
|
}
|
|
|
|
pawMode := allowColor
|
|
if !log.Colorize {
|
|
pawMode = removeColor
|
|
}
|
|
|
|
buf := make([]byte, 0, len(event.msg))
|
|
baw := byteArrayWriter(buf)
|
|
(&protectedANSIWriter{
|
|
w: &baw,
|
|
mode: pawMode,
|
|
}).Write([]byte(event.msg))
|
|
buf = baw
|
|
valueMap["msg"] = string(buf)
|
|
|
|
if event.stacktrace != "" && log.StacktraceLevel <= event.level {
|
|
valueMap["stack"] = event.stacktrace
|
|
}
|
|
|
|
var req *http.Request
|
|
if log.Method == "POST" {
|
|
jsonBytes, err := json.Marshal(valueMap)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
req, err = http.NewRequest(log.Method, log.URL, bytes.NewBuffer(jsonBytes))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
} else {
|
|
reqURL, _ := url.Parse(log.URL)
|
|
query := reqURL.Query()
|
|
for key, value := range valueMap {
|
|
query.Add(key, value)
|
|
}
|
|
reqURL.RawQuery = query.Encode()
|
|
|
|
var err error
|
|
req, err = http.NewRequest(log.Method, reqURL.String(), nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
req.Header = log.Header
|
|
_, err := http.DefaultClient.Do(req)
|
|
return err
|
|
}
|
|
|
|
// Flush does nothing for this implementation
|
|
func (log *HTTPLogger) Flush() {
|
|
}
|
|
|
|
// GetName returns the default name for this implementation
|
|
func (log *HTTPLogger) GetName() string {
|
|
return "http"
|
|
}
|
|
|
|
func init() {
|
|
Register("http", NewHTTP)
|
|
}
|