Skip to content

Commit 16f4c9d

Browse files
committed
Add structured logging
1 parent 14ab95f commit 16f4c9d

File tree

6 files changed

+49
-4
lines changed

6 files changed

+49
-4
lines changed

api/openapi.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ components:
6363
type: array
6464
items:
6565
type: string
66+
structuredLog:
67+
type: boolean
6668
logFile:
6769
type: string
6870
sysLogPrefix:

internal/conf/conf.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ type Conf struct {
152152
// General
153153
LogLevel LogLevel `json:"logLevel"`
154154
LogDestinations LogDestinations `json:"logDestinations"`
155+
StructuredLog bool `json:"structuredLog"`
155156
LogFile string `json:"logFile"`
156157
SysLogPrefix string `json:"sysLogPrefix"`
157158
ReadTimeout Duration `json:"readTimeout"`
@@ -312,6 +313,7 @@ func (conf *Conf) setDefaults() {
312313
// General
313314
conf.LogLevel = LogLevel(logger.Info)
314315
conf.LogDestinations = LogDestinations{logger.DestinationStdout}
316+
conf.StructuredLog = false
315317
conf.LogFile = "mediamtx.log"
316318
conf.SysLogPrefix = "mediamtx"
317319
conf.ReadTimeout = 10 * Duration(time.Second)

internal/core/core.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ func New(args []string) (*Core, bool) {
156156
done: make(chan struct{}),
157157
}
158158

159-
tempLogger, _ := logger.New(logger.Warn, []logger.Destination{logger.DestinationStdout}, "", "")
159+
tempLogger, _ := logger.New(logger.Warn, []logger.Destination{logger.DestinationStdout}, "", "", false)
160160

161161
confPaths := append([]string(nil), defaultConfPaths...)
162162
if runtime.GOOS != "windows" {
@@ -267,6 +267,7 @@ func (p *Core) createResources(initial bool) error {
267267
p.conf.LogDestinations,
268268
p.conf.LogFile,
269269
p.conf.SysLogPrefix,
270+
p.conf.StructuredLog,
270271
)
271272
if err != nil {
272273
return err
@@ -690,7 +691,8 @@ func (p *Core) closeResources(newConf *conf.Conf, calledByAPI bool) {
690691
newConf.LogLevel != p.conf.LogLevel ||
691692
!reflect.DeepEqual(newConf.LogDestinations, p.conf.LogDestinations) ||
692693
newConf.LogFile != p.conf.LogFile ||
693-
newConf.SysLogPrefix != p.conf.SysLogPrefix
694+
newConf.SysLogPrefix != p.conf.SysLogPrefix ||
695+
newConf.StructuredLog != p.conf.StructuredLog
694696

695697
closeAuthManager := newConf == nil ||
696698
newConf.AuthMethod != p.conf.AuthMethod ||
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package logger
2+
3+
import (
4+
"bytes"
5+
"fmt"
6+
"os"
7+
"strconv"
8+
"time"
9+
)
10+
11+
type destinationStdoutStructured struct {
12+
buf bytes.Buffer
13+
}
14+
15+
func newDestionationStdoutStructured() destination {
16+
return &destinationStdoutStructured{}
17+
}
18+
19+
func (d *destinationStdoutStructured) log(t time.Time, level Level, format string, args ...any) {
20+
d.buf.Reset()
21+
d.buf.WriteString(`{"ts":"`)
22+
writeTime(&d.buf, t, false)
23+
d.buf.WriteString(`","level":"`)
24+
writeLevel(&d.buf, level, false)
25+
d.buf.WriteString(`","msg":"`)
26+
d.buf.WriteString(strconv.Quote(fmt.Sprintf(format, args...)))
27+
d.buf.WriteString(`"}`)
28+
d.buf.WriteByte('\n')
29+
os.Stdout.Write(d.buf.Bytes()) //nolint:errcheck
30+
}
31+
32+
func (d *destinationStdoutStructured) close() {
33+
}

internal/logger/logger.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,19 @@ type Logger struct {
1919
}
2020

2121
// New allocates a log handler.
22-
func New(level Level, destinations []Destination, filePath string, sysLogPrefix string) (*Logger, error) {
22+
func New(level Level, destinations []Destination, filePath string, sysLogPrefix string, structuredLog bool) (*Logger, error) {
2323
lh := &Logger{
2424
level: level,
2525
}
2626

2727
for _, destType := range destinations {
2828
switch destType {
2929
case DestinationStdout:
30-
lh.destinations = append(lh.destinations, newDestionationStdout())
30+
if structuredLog {
31+
lh.destinations = append(lh.destinations, newDestionationStdoutStructured())
32+
} else {
33+
lh.destinations = append(lh.destinations, newDestionationStdout())
34+
}
3135

3236
case DestinationFile:
3337
dest, err := newDestinationFile(filePath)

mediamtx.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
logLevel: info
1111
# Destinations of log messages; available values are "stdout", "file" and "syslog".
1212
logDestinations: [stdout]
13+
# If "stdout" in logDestination, use json for logs.
14+
structuredLog: no
1315
# If "file" is in logDestinations, this is the file which will receive the logs.
1416
logFile: mediamtx.log
1517
# If "syslog" is in logDestinations, use prefix for logs.

0 commit comments

Comments
 (0)