[DOC] improve godoc

This commit is contained in:
Martin Geno 2017-06-13 00:21:19 +02:00
parent b8ff3e5842
commit 0620dcaa88
No known key found for this signature in database
GPG Key ID: F0D39A37E925E941
12 changed files with 113 additions and 21 deletions

View File

@ -1 +1 @@
# logmania [![CircleCI](https://circleci.com/gh/genofire/logmania/tree/master.svg?style=shield)](https://circleci.com/gh/genofire/logmania/tree/master) # logmania [![CircleCI](https://circleci.com/gh/genofire/logmania/tree/master.svg?style=shield)](https://circleci.com/gh/genofire/logmania/tree/master) [![Coverage Status](https://coveralls.io/repos/github/genofire/logmania/badge.svg?branch=master)](https://coveralls.io/github/genofire/logmania?branch=master) [![Go Report Card](https://goreportcard.com/badge/github.com/genofire/logmania)](https://goreportcard.com/report/github.com/genofire/logmania) [![GoDoc](https://godoc.org/github.com/genofire/logmania?status.svg)](https://godoc.org/github.com/genofire/logmania)

View File

@ -1,3 +1,4 @@
// reciever of log entry over network (websocket)
package recieve package recieve
import ( import (
@ -9,16 +10,20 @@ import (
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
) )
// http.Handler for init network
type Handler struct { type Handler struct {
http.Handler
upgrader websocket.Upgrader upgrader websocket.Upgrader
} }
// init new Handler
func NewHandler() *Handler { func NewHandler() *Handler {
return &Handler{ return &Handler{
upgrader: websocket.Upgrader{}, upgrader: websocket.Upgrader{},
} }
} }
// server response of handler
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
logEntry := log.HTTP(r) logEntry := log.HTTP(r)
c, err := h.upgrader.Upgrade(w, r, nil) c, err := h.upgrader.Upgrade(w, r, nil)

View File

@ -1,3 +1,12 @@
// logmania Server
//
// reload config with SIGUSR1
//
// Usage of logmania:
// -config string
// config file (default "logmania.conf")
// -debug
// enable debuging
package main package main
import ( import (
@ -78,11 +87,7 @@ func reload() {
log.Errorf("reload: could not load '%s' for new configuration. Skip reload.", configPath) log.Errorf("reload: could not load '%s' for new configuration. Skip reload.", configPath)
return return
} }
if config.API.Bind != api.Addr { if api.Rebind(config.API.Bind) {
api.ErrorNoPanic = true
api.Close()
api.Addr = config.API.Bind
api.Start()
log.Info("reload: new api bind") log.Info("reload: new api bind")
} }
if database.ReplaceConnect(config.Database.Type, config.Database.Connect) { if database.ReplaceConnect(config.Database.Type, config.Database.Connect) {

View File

@ -7,6 +7,8 @@ import (
"github.com/genofire/logmania/log" "github.com/genofire/logmania/log"
) )
// Struct of the configuration
// e.g. under github.com/genofire/logmania/logmania_example.conf
type Config struct { type Config struct {
API struct { API struct {
Bind string `toml:"bind"` Bind string `toml:"bind"`
@ -35,6 +37,7 @@ type Config struct {
} `toml:"webserver"` } `toml:"webserver"`
} }
// read configuration from a file (use toml as file-format)
func ReadConfig(path string) (*Config, error) { func ReadConfig(path string) (*Config, error) {
log.Debugf("load of configfile: %s", path) log.Debugf("load of configfile: %s", path)
var config Config var config Config

2
lib/doc.go Normal file
View File

@ -0,0 +1,2 @@
// some little goodies for logmania
package lib

View File

@ -2,17 +2,21 @@ package lib
import ( import (
"net/http" "net/http"
"sync"
"github.com/genofire/logmania/log" "github.com/genofire/logmania/log"
) )
// little httpserver to handle reconnect and http.Handlers
type HTTPServer struct { type HTTPServer struct {
srv *http.Server srv *http.Server
ErrorNoPanic bool
Addr string Addr string
Handler http.Handler Handler http.Handler
errorNoPanic bool
errorNoPanicAsync sync.Mutex
} }
// start httpserver
func (hs *HTTPServer) Start() { func (hs *HTTPServer) Start() {
hs.srv = &http.Server{ hs.srv = &http.Server{
Addr: hs.Addr, Addr: hs.Addr,
@ -21,7 +25,7 @@ func (hs *HTTPServer) Start() {
go func() { go func() {
log.Debug("startup of http listener") log.Debug("startup of http listener")
if err := hs.srv.ListenAndServe(); err != nil { if err := hs.srv.ListenAndServe(); err != nil {
if hs.ErrorNoPanic { if hs.errorNoPanic {
log.Debug("httpserver shutdown without panic") log.Debug("httpserver shutdown without panic")
return return
} }
@ -29,6 +33,23 @@ func (hs *HTTPServer) Start() {
} }
}() }()
} }
// rebind httpserver to a new address (e.g. new configuration)
func (hs *HTTPServer) Rebind(addr string) bool {
if addr == hs.Addr {
return false
}
hs.errorNoPanicAsync.Lock()
hs.errorNoPanic = true
hs.Close()
hs.Addr = addr
hs.Start()
hs.errorNoPanic = false
hs.errorNoPanicAsync.Unlock()
return true
}
// close/stop current httpserver
func (hs *HTTPServer) Close() { func (hs *HTTPServer) Close() {
log.Debug("startup of http listener") log.Debug("startup of http listener")
hs.srv.Close() hs.srv.Close()

View File

@ -1,3 +1,4 @@
// logger to bind at github.com/genofire/logmania/log.AddLogger to send log entries to logmania server
package client package client
import ( import (
@ -8,6 +9,7 @@ import (
"github.com/genofire/logmania/log" "github.com/genofire/logmania/log"
) )
// client logger
type Logger struct { type Logger struct {
log.Logger log.Logger
AboveLevel log.LogLevel AboveLevel log.LogLevel
@ -15,8 +17,10 @@ type Logger struct {
closed bool closed bool
} }
// CurrentLogger (for override settings e.g. AboveLevel)
var CurrentLogger *Logger var CurrentLogger *Logger
// create a new logmania client logger
func NewLogger(url, token string, AboveLevel log.LogLevel) *Logger { func NewLogger(url, token string, AboveLevel log.LogLevel) *Logger {
c, _, err := websocket.DefaultDialer.Dial(fmt.Sprint(url, "/logger"), nil) c, _, err := websocket.DefaultDialer.Dial(fmt.Sprint(url, "/logger"), nil)
if err != nil { if err != nil {
@ -34,6 +38,7 @@ func NewLogger(url, token string, AboveLevel log.LogLevel) *Logger {
} }
} }
// handle a log entry (send to logmania server)
func (l *Logger) Hook(e *log.Entry) { func (l *Logger) Hook(e *log.Entry) {
if l.closed { if l.closed {
return return
@ -47,6 +52,8 @@ func (l *Logger) Hook(e *log.Entry) {
l.Close() l.Close()
} }
} }
// Listen if logmania server want to close the connection
func (l *Logger) Listen() { func (l *Logger) Listen() {
for { for {
msgType, _, err := l.conn.ReadMessage() msgType, _, err := l.conn.ReadMessage()
@ -60,11 +67,14 @@ func (l *Logger) Listen() {
} }
} }
} }
// close connection to logger
func (l *Logger) Close() { func (l *Logger) Close() {
l.conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, "")) l.conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
l.closed = true l.closed = true
} }
// init logmania's client logger and bind
func Init(url, token string, AboveLevel log.LogLevel) *Logger { func Init(url, token string, AboveLevel log.LogLevel) *Logger {
CurrentLogger = NewLogger(url, token, AboveLevel) CurrentLogger = NewLogger(url, token, AboveLevel)
go CurrentLogger.Listen() go CurrentLogger.Listen()

View File

@ -1,3 +1,5 @@
// logger to print log entry (with color)
// this logger would be bind by importing
package output package output
import ( import (
@ -16,6 +18,7 @@ var (
AboveLevel = log.InfoLevel AboveLevel = log.InfoLevel
) )
// logger for output
type Logger struct { type Logger struct {
log.Logger log.Logger
TimeFormat string TimeFormat string
@ -23,8 +26,10 @@ type Logger struct {
AboveLevel log.LogLevel AboveLevel log.LogLevel
} }
// CurrentLogger (for override settings e.g. AboveLevel,ShowTime or TimeFormat)
var CurrentLogger *Logger var CurrentLogger *Logger
// create a new output logger
func NewLogger() *Logger { func NewLogger() *Logger {
return &Logger{ return &Logger{
TimeFormat: "2006-01-02 15:04:05", TimeFormat: "2006-01-02 15:04:05",
@ -33,6 +38,7 @@ func NewLogger() *Logger {
} }
} }
// handle a log entry (print it on the terminal with color)
func (l *Logger) Hook(e *log.Entry) { func (l *Logger) Hook(e *log.Entry) {
if e.Level < AboveLevel { if e.Level < AboveLevel {
return return
@ -76,6 +82,7 @@ func (l *Logger) Hook(e *log.Entry) {
} }
} }
// do nothing - terminal did not need something to close
func (l *Logger) Close() { func (l *Logger) Close() {
} }

View File

@ -15,6 +15,7 @@ func getIP(r *http.Request) string {
return ip return ip
} }
// init log entry with extra fields of interesting http request context
func HTTP(r *http.Request) *Entry { func HTTP(r *http.Request) *Entry {
return New().AddFields(map[string]interface{}{ return New().AddFields(map[string]interface{}{
"remote": getIP(r), "remote": getIP(r),
@ -23,6 +24,7 @@ func HTTP(r *http.Request) *Entry {
}) })
} }
// init log entry with extra fields of interesting websocket request context
func WebsocketX(ws *websocket.Conn) *Entry { func WebsocketX(ws *websocket.Conn) *Entry {
r := ws.Request() r := ws.Request()
return New().AddFields(map[string]interface{}{ return New().AddFields(map[string]interface{}{
@ -31,6 +33,8 @@ func WebsocketX(ws *websocket.Conn) *Entry {
"url": r.URL.RequestURI(), "url": r.URL.RequestURI(),
}) })
} }
// init log entry with extra fields of interesting websocket request context
func WebsocketGozilla(ws *wsGozilla.Conn) *Entry { func WebsocketGozilla(ws *wsGozilla.Conn) *Entry {
return New().AddFields(map[string]interface{}{ return New().AddFields(map[string]interface{}{
"remote": ws.RemoteAddr().String(), "remote": ws.RemoteAddr().String(),

View File

@ -1,7 +1,9 @@
package log package log
// definition of loglevel
type LogLevel int32 type LogLevel int32
// accepted LogLevels and his internal int values
const ( const (
DebugLevel = LogLevel(-1) DebugLevel = LogLevel(-1)
InfoLevel = LogLevel(0) InfoLevel = LogLevel(0)
@ -10,6 +12,7 @@ const (
PanicLevel = LogLevel(3) PanicLevel = LogLevel(3)
) )
// string of loglevel
func (l LogLevel) String() string { func (l LogLevel) String() string {
switch l { switch l {
case DebugLevel: case DebugLevel:
@ -31,42 +34,52 @@ func (l LogLevel) String() string {
* log command * log command
*/ */
// debug // close logentry with debug
func (e *Entry) Debug(v ...interface{}) { func (e *Entry) Debug(v ...interface{}) {
e.Log(DebugLevel, v...) e.Log(DebugLevel, v...)
} }
// close logentry with formated debug
func (e *Entry) Debugf(format string, v ...interface{}) { func (e *Entry) Debugf(format string, v ...interface{}) {
e.Logf(DebugLevel, format, v...) e.Logf(DebugLevel, format, v...)
} }
// info // close logentry with info
func (e *Entry) Info(v ...interface{}) { func (e *Entry) Info(v ...interface{}) {
e.Log(InfoLevel, v...) e.Log(InfoLevel, v...)
} }
// close logentry with formated info
func (e *Entry) Infof(format string, v ...interface{}) { func (e *Entry) Infof(format string, v ...interface{}) {
e.Logf(InfoLevel, format, v...) e.Logf(InfoLevel, format, v...)
} }
// warn // close logentry with warning
func (e *Entry) Warn(v ...interface{}) { func (e *Entry) Warn(v ...interface{}) {
e.Log(WarnLevel, v...) e.Log(WarnLevel, v...)
} }
// close logentry with formated warning
func (e *Entry) Warnf(format string, v ...interface{}) { func (e *Entry) Warnf(format string, v ...interface{}) {
e.Logf(WarnLevel, format, v...) e.Logf(WarnLevel, format, v...)
} }
// error // close logentry with error
func (e *Entry) Error(v ...interface{}) { func (e *Entry) Error(v ...interface{}) {
e.Log(ErrorLevel, v...) e.Log(ErrorLevel, v...)
} }
// close logentry with formated error
func (e *Entry) Errorf(format string, v ...interface{}) { func (e *Entry) Errorf(format string, v ...interface{}) {
e.Logf(ErrorLevel, format, v...) e.Logf(ErrorLevel, format, v...)
} }
// panic // close logentry with panic
func (e *Entry) Panic(v ...interface{}) { func (e *Entry) Panic(v ...interface{}) {
e.Log(PanicLevel, v...) e.Log(PanicLevel, v...)
} }
// close logentry with formated panic
func (e *Entry) Panicf(format string, v ...interface{}) { func (e *Entry) Panicf(format string, v ...interface{}) {
e.Logf(PanicLevel, format, v...) e.Logf(PanicLevel, format, v...)
} }
@ -75,42 +88,52 @@ func (e *Entry) Panicf(format string, v ...interface{}) {
* Direct log command * Direct log command
*/ */
// debug // direct log with debug
func Debug(v ...interface{}) { func Debug(v ...interface{}) {
New().Log(DebugLevel, v...) New().Log(DebugLevel, v...)
} }
// direct log with formated debug
func Debugf(format string, v ...interface{}) { func Debugf(format string, v ...interface{}) {
New().Logf(DebugLevel, format, v...) New().Logf(DebugLevel, format, v...)
} }
// info // direct log with info
func Info(v ...interface{}) { func Info(v ...interface{}) {
New().Log(InfoLevel, v...) New().Log(InfoLevel, v...)
} }
// direct log with formated info
func Infof(format string, v ...interface{}) { func Infof(format string, v ...interface{}) {
New().Logf(InfoLevel, format, v...) New().Logf(InfoLevel, format, v...)
} }
// warn // direct log with warning
func Warn(v ...interface{}) { func Warn(v ...interface{}) {
New().Log(WarnLevel, v...) New().Log(WarnLevel, v...)
} }
// direct log with formated warning
func Warnf(format string, v ...interface{}) { func Warnf(format string, v ...interface{}) {
New().Logf(WarnLevel, format, v...) New().Logf(WarnLevel, format, v...)
} }
// error // direct log with error
func Error(v ...interface{}) { func Error(v ...interface{}) {
New().Log(ErrorLevel, v...) New().Log(ErrorLevel, v...)
} }
// direct log with formated error
func Errorf(format string, v ...interface{}) { func Errorf(format string, v ...interface{}) {
New().Logf(ErrorLevel, format, v...) New().Logf(ErrorLevel, format, v...)
} }
// panic // direct log with panic
func Panic(v ...interface{}) { func Panic(v ...interface{}) {
New().Log(PanicLevel, v...) New().Log(PanicLevel, v...)
} }
// direct log with formated panic
func Panicf(format string, v ...interface{}) { func Panicf(format string, v ...interface{}) {
New().Logf(PanicLevel, format, v...) New().Logf(PanicLevel, format, v...)
} }

View File

@ -1,5 +1,6 @@
package log package log
// interface of a logger
type Logger interface { type Logger interface {
Hook(*Entry) Hook(*Entry)
Close() Close()
@ -7,6 +8,7 @@ type Logger interface {
var loggers = make([]Logger, 0) var loggers = make([]Logger, 0)
// bind logger to handle saving/output of a Log entry
func AddLogger(logger Logger) { func AddLogger(logger Logger) {
loggers = append(loggers, logger) loggers = append(loggers, logger)
} }

View File

@ -1,32 +1,41 @@
// log package with entry as a lib in other go applications
package log package log
import "fmt" import "fmt"
// a struct with all information of a log entry
type Entry struct { type Entry struct {
Level LogLevel `json:"level"` Level LogLevel `json:"level"`
Fields map[string]interface{} `json:"fields"` Fields map[string]interface{} `json:"fields"`
Text string `json:"text"` Text string `json:"text"`
} }
// save/out current state of log entry
func (e *Entry) Log(level LogLevel, v ...interface{}) { func (e *Entry) Log(level LogLevel, v ...interface{}) {
e.Text = fmt.Sprint(v...) e.Text = fmt.Sprint(v...)
e.Level = level e.Level = level
save(e) save(e)
} }
// save/out current state of log entry with formation
func (e *Entry) Logf(level LogLevel, format string, v ...interface{}) { func (e *Entry) Logf(level LogLevel, format string, v ...interface{}) {
e.Text = fmt.Sprintf(format, v...) e.Text = fmt.Sprintf(format, v...)
e.Level = level e.Level = level
save(e) save(e)
} }
// init new log entry
func New() *Entry { func New() *Entry {
return &Entry{Fields: make(map[string]interface{})} return &Entry{Fields: make(map[string]interface{})}
} }
// add extra value to entry (log entry with context)
func (e *Entry) AddField(key string, value interface{}) *Entry { func (e *Entry) AddField(key string, value interface{}) *Entry {
e.Fields[key] = value e.Fields[key] = value
return e return e
} }
// add multi extra values to entry (log entry with context)
func (e *Entry) AddFields(fields map[string]interface{}) *Entry { func (e *Entry) AddFields(fields map[string]interface{}) *Entry {
for key, value := range fields { for key, value := range fields {
e.Fields[key] = value e.Fields[key] = value
@ -34,6 +43,7 @@ func (e *Entry) AddFields(fields map[string]interface{}) *Entry {
return e return e
} }
// create a readable string of extra values (log entry with context)
func (e *Entry) FieldString() string { func (e *Entry) FieldString() string {
text := "" text := ""
for key, value := range e.Fields { for key, value := range e.Fields {