Skip to content

Commit

Permalink
Logs refactoring after #780
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexxIT committed Dec 11, 2023
1 parent 1f3a320 commit d3bc18c
Show file tree
Hide file tree
Showing 4 changed files with 195 additions and 159 deletions.
28 changes: 4 additions & 24 deletions internal/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -254,35 +254,15 @@ func restartHandler(w http.ResponseWriter, r *http.Request) {
go shell.Restart()
}

// logHandler handles HTTP requests for log buffer operations.
// It supports two HTTP methods:
// - GET: Retrieves the content of in-memory log and sends it back to the client as plain text.
// - DELETE: Clear the in-memory log buffer.
//
// The function expects a valid http.ResponseWriter and an http.Request as parameters.
// For a GET request, it reads the log from in-memory buffer and writes
// the content to the response writer with a "text/plain" content type.
//
// For a DELETE request, it clears the in-memory buffer.
//
// For any other HTTP method, it responds with an HTTP 400 (Bad Request) status.
//
// Parameters:
// - w http.ResponseWriter: The response writer to write the HTTP response to.
// - r *http.Request: The HTTP request object containing the request details.
//
// No return values are provided since the function writes directly to the response writer.
func logHandler(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case "GET":

// Send current state of the log file immediately
data := app.LogCollector.Bytes()
Response(w, data, "text/plain")
w.Header().Set("Content-Type", "application/jsonlines")
_, _ = app.MemoryLog.WriteTo(w)
case "DELETE":
app.LogCollector.Reset()

Response(w, "Log truncated", "text/plain")
app.MemoryLog.Reset()
Response(w, "OK", "text/plain")
default:
http.Error(w, "Method not allowed", http.StatusBadRequest)
}
Expand Down
48 changes: 0 additions & 48 deletions internal/app/app.go
Original file line number Diff line number Diff line change
@@ -1,21 +1,16 @@
package app

import (
"bytes"
"errors"
"flag"
"fmt"
"io"

"os"
"path/filepath"
"runtime"
"strings"
"time"

"github.com/AlexxIT/go2rtc/pkg/shell"
"github.com/AlexxIT/go2rtc/pkg/yaml"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
)

Expand All @@ -27,8 +22,6 @@ var Info = map[string]any{
"version": Version,
}

var LogCollector bytes.Buffer

func Init() {
var confs Config
var version bool
Expand Down Expand Up @@ -90,32 +83,6 @@ func Init() {
migrateStore()
}

func NewLogger(format string, level string) zerolog.Logger {
var writer io.Writer = os.Stdout

if format != "json" {
writer = zerolog.ConsoleWriter{
Out: writer, TimeFormat: "15:04:05.000",
NoColor: writer != os.Stdout || format == "text",
}
}
memoryLogger := zerolog.ConsoleWriter{
Out: &LogCollector, TimeFormat: "15:04:05.000",
NoColor: true,
}

writer = zerolog.MultiLevelWriter(writer, memoryLogger)

zerolog.TimeFieldFormat = time.RFC3339Nano

lvl, err := zerolog.ParseLevel(level)
if err != nil || lvl == zerolog.NoLevel {
lvl = zerolog.InfoLevel
}

return zerolog.New(writer).With().Timestamp().Logger().Level(lvl)
}

func LoadConfig(v any) {
for _, data := range configs {
if err := yaml.Unmarshal(data, v); err != nil {
Expand All @@ -124,18 +91,6 @@ func LoadConfig(v any) {
}
}

func GetLogger(module string) zerolog.Logger {
if s, ok := modules[module]; ok {
lvl, err := zerolog.ParseLevel(s)
if err == nil {
return log.Level(lvl)
}
log.Warn().Err(err).Caller().Send()
}

return log.Logger
}

func PatchConfig(key string, value any, path ...string) error {
if ConfigPath == "" {
return errors.New("config file disabled")
Expand Down Expand Up @@ -166,6 +121,3 @@ func (c *Config) Set(value string) error {
}

var configs [][]byte

// modules log levels
var modules map[string]string
117 changes: 117 additions & 0 deletions internal/app/log.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package app

import (
"io"
"os"

"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
)

var MemoryLog *circularBuffer

func NewLogger(format string, level string) zerolog.Logger {
var writer io.Writer = os.Stdout

if format != "json" {
writer = zerolog.ConsoleWriter{
Out: writer, TimeFormat: "15:04:05.000", NoColor: format == "text",
}
}

MemoryLog = newBuffer(16)

writer = zerolog.MultiLevelWriter(writer, MemoryLog)

zerolog.TimeFieldFormat = zerolog.TimeFormatUnixMs

lvl, err := zerolog.ParseLevel(level)
if err != nil || lvl == zerolog.NoLevel {
lvl = zerolog.InfoLevel
}

return zerolog.New(writer).With().Timestamp().Logger().Level(lvl)
}

func GetLogger(module string) zerolog.Logger {
if s, ok := modules[module]; ok {
lvl, err := zerolog.ParseLevel(s)
if err == nil {
return log.Level(lvl)
}
log.Warn().Err(err).Caller().Send()
}

return log.Logger
}

// modules log levels
var modules map[string]string

const chunkSize = 1 << 16

type circularBuffer struct {
chunks [][]byte
r, w int
}

func newBuffer(chunks int) *circularBuffer {
b := &circularBuffer{chunks: make([][]byte, 0, chunks)}
// create first chunk
b.chunks = append(b.chunks, make([]byte, 0, chunkSize))
return b
}

func (b *circularBuffer) Write(p []byte) (n int, err error) {
n = len(p)

// check if chunk has size
if len(b.chunks[b.w])+n > chunkSize {
// increase write chunk index
if b.w++; b.w == cap(b.chunks) {
b.w = 0
}
// check overflow
if b.r == b.w {
// increase read chunk index
if b.r++; b.r == cap(b.chunks) {
b.r = 0
}
}
// check if current chunk exists
if b.w == len(b.chunks) {
// allocate new chunk
b.chunks = append(b.chunks, make([]byte, 0, chunkSize))
} else {
// reset len of current chunk
b.chunks[b.w] = b.chunks[b.w][:0]
}
}

b.chunks[b.w] = append(b.chunks[b.w], p...)
return
}

func (b *circularBuffer) WriteTo(w io.Writer) (n int64, err error) {
for i := b.r; ; {
var nn int
if nn, err = w.Write(b.chunks[i]); err != nil {
return
}
n += int64(nn)

if i == b.w {
break
}
if i++; i == cap(b.chunks) {
i = 0
}
}
return
}

func (b *circularBuffer) Reset() {
b.chunks[0] = b.chunks[0][:0]
b.r = 0
b.w = 0
}
Loading

0 comments on commit d3bc18c

Please sign in to comment.