json.go raw
1 // Copyright 2018 The gVisor Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 package log
16
17 import (
18 "encoding/json"
19 "fmt"
20 "runtime"
21 "strings"
22 "time"
23 )
24
25 type jsonLog struct {
26 Msg string `json:"msg"`
27 Level Level `json:"level"`
28 Time time.Time `json:"time"`
29 }
30
31 // MarshalJSON implements json.Marshaler.MarashalJSON.
32 func (l Level) MarshalJSON() ([]byte, error) {
33 switch l {
34 case Warning:
35 return []byte(`"warning"`), nil
36 case Info:
37 return []byte(`"info"`), nil
38 case Debug:
39 return []byte(`"debug"`), nil
40 default:
41 return nil, fmt.Errorf("unknown level %v", l)
42 }
43 }
44
45 // UnmarshalJSON implements json.Unmarshaler.UnmarshalJSON. It can unmarshal
46 // from both string names and integers.
47 func (l *Level) UnmarshalJSON(b []byte) error {
48 switch s := string(b); s {
49 case "0", `"warning"`:
50 *l = Warning
51 case "1", `"info"`:
52 *l = Info
53 case "2", `"debug"`:
54 *l = Debug
55 default:
56 return fmt.Errorf("unknown level %q", s)
57 }
58 return nil
59 }
60
61 // JSONEmitter logs messages in json format.
62 type JSONEmitter struct {
63 *Writer
64 }
65
66 // Emit implements Emitter.Emit.
67 func (e JSONEmitter) Emit(depth int, level Level, timestamp time.Time, format string, v ...any) {
68 logLine := fmt.Sprintf(format, v...)
69 if _, file, line, ok := runtime.Caller(depth + 1); ok {
70 if slash := strings.LastIndexByte(file, byte('/')); slash >= 0 {
71 file = file[slash+1:] // Trim any directory path from the file.
72 }
73 logLine = fmt.Sprintf("%s:%d] %s", file, line, logLine)
74 }
75 j := jsonLog{
76 Msg: logLine,
77 Level: level,
78 Time: timestamp,
79 }
80 b, err := json.Marshal(j)
81 if err != nil {
82 panic(err)
83 }
84 e.Writer.Write(b)
85 }
86