mirror of
https://github.com/wahyd4/loginsrv.git
synced 2026-08-09 21:06:44 +10:00
268 lines
6.1 KiB
Go
268 lines
6.1 KiB
Go
package logging
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"github.com/tarent/logrus"
|
|
"net/http"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
var Logger *logrus.Logger
|
|
|
|
// The of cookies which should not be logged
|
|
var AccessLogCookiesBlacklist = []string{}
|
|
|
|
var LifecycleEnvVars = []string{"BUILD_NUMBER", "BUILD_HASH", "BUILD_DATE"}
|
|
|
|
func init() {
|
|
Set("info", false)
|
|
}
|
|
|
|
// Set creates a new Logger with the matching specification
|
|
func Set(level string, textLogging bool) error {
|
|
l, err := logrus.ParseLevel(level)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
logger := logrus.New()
|
|
if textLogging {
|
|
logger.Formatter = &logrus.TextFormatter{}
|
|
} else {
|
|
logger.Formatter = &LogstashFormatter{TimestampFormat: time.RFC3339Nano}
|
|
}
|
|
logger.Level = l
|
|
Logger = logger
|
|
return nil
|
|
}
|
|
|
|
// Access logs an access entry with call duration and status code
|
|
func Access(r *http.Request, start time.Time, statusCode int) {
|
|
e := access(r, start, statusCode, nil)
|
|
|
|
var msg string
|
|
if len(r.URL.RawQuery) == 0 {
|
|
msg = fmt.Sprintf("%v ->%v %v", statusCode, r.Method, r.URL.Path)
|
|
} else {
|
|
msg = fmt.Sprintf("%v ->%v %v?...", statusCode, r.Method, r.URL.Path)
|
|
}
|
|
|
|
if statusCode >= 200 && statusCode <= 399 {
|
|
e.Info(msg)
|
|
} else if statusCode >= 400 && statusCode <= 499 {
|
|
e.Warn(msg)
|
|
} else {
|
|
e.Error(msg)
|
|
}
|
|
}
|
|
|
|
// AccessError logs an error while accessing
|
|
func AccessError(r *http.Request, start time.Time, err error) {
|
|
e := access(r, start, 0, err)
|
|
e.Errorf("ERROR ->%v %v", r.Method, r.URL.Path)
|
|
}
|
|
|
|
func access(r *http.Request, start time.Time, statusCode int, err error) *logrus.Entry {
|
|
url := r.URL.Path
|
|
if r.URL.RawQuery != "" {
|
|
url += "?" + r.URL.RawQuery
|
|
}
|
|
fields := logrus.Fields{
|
|
"type": "access",
|
|
"@timestamp": start,
|
|
"remote_ip": getRemoteIp(r),
|
|
"host": r.Host,
|
|
"url": url,
|
|
"method": r.Method,
|
|
"proto": r.Proto,
|
|
"duration": time.Since(start).Nanoseconds() / 1000000,
|
|
"User_Agent": r.Header.Get("User-Agent"),
|
|
}
|
|
|
|
if statusCode != 0 {
|
|
fields["response_status"] = statusCode
|
|
}
|
|
|
|
if err != nil {
|
|
fields[logrus.ErrorKey] = err.Error()
|
|
}
|
|
|
|
setCorrelationIds(fields, r.Header)
|
|
|
|
cookies := map[string]string{}
|
|
for _, c := range r.Cookies() {
|
|
if !contains(AccessLogCookiesBlacklist, c.Name) {
|
|
cookies[c.Name] = c.Value
|
|
}
|
|
}
|
|
if len(cookies) > 0 {
|
|
fields["cookies"] = cookies
|
|
}
|
|
|
|
return Logger.WithFields(fields)
|
|
}
|
|
|
|
// Call logs the result of an outgoing call
|
|
func Call(r *http.Request, resp *http.Response, start time.Time, err error) {
|
|
url := r.URL.Path
|
|
if r.URL.RawQuery != "" {
|
|
url += "?" + r.URL.RawQuery
|
|
}
|
|
fields := logrus.Fields{
|
|
"type": "call",
|
|
"@timestamp": start,
|
|
"host": r.Host,
|
|
"url": url,
|
|
"full_url": r.URL.String(),
|
|
"method": r.Method,
|
|
"duration": time.Since(start).Nanoseconds() / 1000000,
|
|
}
|
|
|
|
setCorrelationIds(fields, r.Header)
|
|
|
|
if err != nil {
|
|
fields[logrus.ErrorKey] = err.Error()
|
|
Logger.WithFields(fields).Error(err)
|
|
return
|
|
}
|
|
|
|
if resp != nil {
|
|
fields["response_status"] = resp.StatusCode
|
|
fields["content_type"] = resp.Header.Get("Content-Type")
|
|
e := Logger.WithFields(fields)
|
|
msg := fmt.Sprintf("%v %v-> %v", resp.StatusCode, r.Method, r.URL.String())
|
|
|
|
if resp.StatusCode >= 200 && resp.StatusCode <= 399 {
|
|
e.Info(msg)
|
|
} else if resp.StatusCode >= 400 && resp.StatusCode <= 499 {
|
|
e.Warn(msg)
|
|
} else {
|
|
e.Error(msg)
|
|
}
|
|
return
|
|
}
|
|
|
|
Logger.WithFields(fields).Warn("call, but no response given")
|
|
}
|
|
|
|
// Cacheinfo logs the hit information a accessing a ressource
|
|
func Cacheinfo(url string, hit bool) {
|
|
var msg string
|
|
if hit {
|
|
msg = fmt.Sprintf("cache hit: %v", url)
|
|
} else {
|
|
msg = fmt.Sprintf("cache miss: %v", url)
|
|
}
|
|
Logger.WithFields(
|
|
logrus.Fields{
|
|
"type": "cacheinfo",
|
|
"url": url,
|
|
"hit": hit,
|
|
}).
|
|
Debug(msg)
|
|
}
|
|
|
|
// Return a log entry for application logs,
|
|
// prefilled with the correlation ids out of the supplied request.
|
|
func Application(h http.Header) *logrus.Entry {
|
|
fields := logrus.Fields{
|
|
"type": "application",
|
|
}
|
|
setCorrelationIds(fields, h)
|
|
return Logger.WithFields(fields)
|
|
}
|
|
|
|
// LifecycleStart logs the start of an application
|
|
// with the configuration struct or map as paramter.
|
|
func LifecycleStart(appName string, args interface{}) {
|
|
fields := logrus.Fields{}
|
|
|
|
jsonString, err := json.Marshal(args)
|
|
if err == nil {
|
|
err := json.Unmarshal(jsonString, &fields)
|
|
if err != nil {
|
|
fields["parse_error"] = err.Error()
|
|
}
|
|
}
|
|
fields["type"] = "lifecycle"
|
|
fields["event"] = "start"
|
|
for _, env := range LifecycleEnvVars {
|
|
if os.Getenv(env) != "" {
|
|
fields[strings.ToLower(env)] = os.Getenv(env)
|
|
}
|
|
}
|
|
|
|
Logger.WithFields(fields).Infof("starting application: %v", appName)
|
|
}
|
|
|
|
// LifecycleStop logs the stop of an application
|
|
func LifecycleStop(appName string, signal os.Signal, err error) {
|
|
fields := logrus.Fields{
|
|
"type": "lifecycle",
|
|
"event": "stop",
|
|
}
|
|
if signal != nil {
|
|
fields["signal"] = signal.String()
|
|
}
|
|
|
|
if os.Getenv("BUILD_NUMBER") != "" {
|
|
fields["build_number"] = os.Getenv("BUILD_NUMBER")
|
|
}
|
|
|
|
if err != nil {
|
|
Logger.WithFields(fields).
|
|
WithError(err).
|
|
Errorf("stopping application: %v (%v)", appName, err)
|
|
} else {
|
|
Logger.WithFields(fields).Infof("stopping application: %v (%v)", appName, signal)
|
|
}
|
|
}
|
|
|
|
// LifecycleStop logs the stop of an application
|
|
func ServerClosed(appName string) {
|
|
fields := logrus.Fields{
|
|
"type": "application",
|
|
"event": "stop",
|
|
}
|
|
|
|
if os.Getenv("BUILD_NUMBER") != "" {
|
|
fields["build_number"] = os.Getenv("BUILD_NUMBER")
|
|
}
|
|
|
|
Logger.WithFields(fields).Infof("http server was closed: %v", appName)
|
|
}
|
|
|
|
func getRemoteIp(r *http.Request) string {
|
|
if r.Header.Get("X-Cluster-Client-Ip") != "" {
|
|
return r.Header.Get("X-Cluster-Client-Ip")
|
|
}
|
|
if r.Header.Get("X-Real-Ip") != "" {
|
|
return r.Header.Get("X-Real-Ip")
|
|
}
|
|
return strings.Split(r.RemoteAddr, ":")[0]
|
|
}
|
|
|
|
func setCorrelationIds(fields logrus.Fields, h http.Header) {
|
|
correlationId := GetCorrelationId(h)
|
|
if correlationId != "" {
|
|
fields["correlation_id"] = correlationId
|
|
}
|
|
|
|
userCorrelationId := GetUserCorrelationId(h)
|
|
if userCorrelationId != "" {
|
|
fields["user_correlation_id"] = userCorrelationId
|
|
}
|
|
}
|
|
|
|
func contains(s []string, e string) bool {
|
|
for _, a := range s {
|
|
if a == e {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|