174 lines
4.0 KiB
Go
174 lines
4.0 KiB
Go
package logutil
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"io"
|
|
"mime/multipart"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"go.uber.org/zap"
|
|
"go.uber.org/zap/zapcore"
|
|
"gopkg.in/natefinch/lumberjack.v2"
|
|
)
|
|
|
|
type Logger struct {
|
|
*zap.SugaredLogger
|
|
logPath string
|
|
}
|
|
|
|
func NewLogger(logPath string) *Logger {
|
|
envLogLevel := os.Getenv("LOG_LEVEL")
|
|
var zapLevel zapcore.Level
|
|
|
|
switch envLogLevel {
|
|
case "DEBUG":
|
|
zapLevel = zapcore.DebugLevel
|
|
case "INFO":
|
|
zapLevel = zapcore.InfoLevel
|
|
case "WARN":
|
|
zapLevel = zapcore.WarnLevel
|
|
case "ERROR":
|
|
zapLevel = zapcore.ErrorLevel
|
|
case "FATAL":
|
|
zapLevel = zapcore.FatalLevel
|
|
default:
|
|
zapLevel = zapcore.DebugLevel
|
|
}
|
|
|
|
consoleCfg := zapcore.EncoderConfig{
|
|
TimeKey: "time",
|
|
LevelKey: "level",
|
|
NameKey: "logger",
|
|
MessageKey: "msg",
|
|
CallerKey: "",
|
|
StacktraceKey: "",
|
|
LineEnding: zapcore.DefaultLineEnding,
|
|
EncodeLevel: zapcore.CapitalColorLevelEncoder,
|
|
EncodeTime: zapcore.ISO8601TimeEncoder,
|
|
EncodeDuration: zapcore.StringDurationEncoder,
|
|
}
|
|
consoleEncoder := zapcore.NewConsoleEncoder(consoleCfg)
|
|
consoleEncoderCore := zapcore.NewCore(consoleEncoder, zapcore.AddSync(os.Stdout), zapLevel)
|
|
|
|
// Set up file logging with overwrite mode
|
|
lj := lumberjack.Logger{
|
|
Filename: logPath,
|
|
MaxSize: 10, // megabytes
|
|
MaxBackups: 20,
|
|
}
|
|
lj.Rotate()
|
|
logFile := zapcore.AddSync(&lj)
|
|
fmt.Println("Logging to", logPath)
|
|
|
|
fileCfg := zapcore.EncoderConfig{
|
|
TimeKey: "time",
|
|
LevelKey: "level",
|
|
NameKey: "logger",
|
|
MessageKey: "msg",
|
|
CallerKey: "",
|
|
StacktraceKey: "",
|
|
LineEnding: zapcore.DefaultLineEnding,
|
|
EncodeLevel: zapcore.CapitalLevelEncoder,
|
|
EncodeTime: zapcore.ISO8601TimeEncoder,
|
|
EncodeDuration: zapcore.StringDurationEncoder,
|
|
}
|
|
fileEncoder := zapcore.NewConsoleEncoder(fileCfg)
|
|
fileEncoderCore := zapcore.NewCore(fileEncoder, zapcore.AddSync(logFile), zapLevel)
|
|
|
|
cores := zapcore.NewTee(consoleEncoderCore, fileEncoderCore)
|
|
logger := zap.New(cores, zap.AddCaller(), zap.Development())
|
|
defer logger.Sync() // flushes buffer, if any
|
|
sugar := logger.Sugar()
|
|
|
|
zLogger := &Logger{
|
|
SugaredLogger: sugar,
|
|
logPath: logPath,
|
|
}
|
|
|
|
return zLogger
|
|
}
|
|
|
|
func (l *Logger) Printf(format string, v ...interface{}) {
|
|
l.SugaredLogger.Infof(format, v...)
|
|
}
|
|
|
|
func (l *Logger) Named(name string) *Logger {
|
|
return &Logger{
|
|
SugaredLogger: l.SugaredLogger.Named(name),
|
|
logPath: l.logPath,
|
|
}
|
|
}
|
|
|
|
// GetLogsFromFile opens the file at l.logPath, reads its contents, and returns them as a string.
|
|
func (l *Logger) GetLogsFromFile() (string, error) {
|
|
file, err := os.Open(l.logPath)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer file.Close()
|
|
|
|
data, err := io.ReadAll(file)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return string(data), nil
|
|
}
|
|
|
|
// UploadLogFile opens the file at l.logPath, uploads it to 0x0.st, and returns the URL of the uploaded file.
|
|
func (l *Logger) UploadLogFile() (string, error) {
|
|
file, err := os.Open(l.logPath)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer file.Close()
|
|
|
|
// Prepare a form that you will submit to that URL.
|
|
var b bytes.Buffer
|
|
w := multipart.NewWriter(&b)
|
|
fw, err := w.CreateFormFile("file", filepath.Base(l.logPath))
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
// Copy the file into the form file
|
|
if _, err = io.Copy(fw, file); err != nil {
|
|
return "", err
|
|
}
|
|
|
|
// Close the multipart writer to set the terminating boundary
|
|
if err = w.Close(); err != nil {
|
|
return "", err
|
|
}
|
|
|
|
// Create a request and add the proper headers.
|
|
req, err := http.NewRequest(http.MethodPost, "https://0x0.st/", &b)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
req.Header.Set("Content-Type", w.FormDataContentType())
|
|
|
|
// Send the request
|
|
client := &http.Client{}
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
return "", fmt.Errorf("failed to upload log file, server responded with status code: %d", resp.StatusCode)
|
|
}
|
|
|
|
// Read the response body
|
|
responseBody, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return string(responseBody), nil
|
|
}
|