Add new log format that is compatible with Kubernetes

Fluentd configuration uses 'log' for the log message
while containerd uses 'msg'. Since we can't have a single
JSON format for both, add another log format and make
debug log configurable.

PiperOrigin-RevId: 219729658
Change-Id: I2a6afc4034d893ab90bafc63b394c4fb62b2a7a0
This commit is contained in:
Fabricio Voznika 2018-11-01 17:43:50 -07:00 committed by Shentubot
parent 9d69d85bc1
commit b6b81fd04b
5 changed files with 77 additions and 18 deletions

View File

@ -8,6 +8,7 @@ go_library(
"glog.go",
"glog_unsafe.go",
"json.go",
"json_k8s.go",
"log.go",
],
importpath = "gvisor.googlesource.com/gvisor/pkg/log",

47
pkg/log/json_k8s.go Normal file
View File

@ -0,0 +1,47 @@
// Copyright 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package log
import (
"encoding/json"
"fmt"
"time"
)
type k8sJSONLog struct {
Log string `json:"log"`
Level Level `json:"level"`
Time time.Time `json:"time"`
}
// K8sJSONEmitter logs messages in json format that is compatible with
// Kubernetes fluent configuration.
type K8sJSONEmitter struct {
Writer
}
// Emit implements Emitter.Emit.
func (e K8sJSONEmitter) Emit(level Level, timestamp time.Time, format string, v ...interface{}) {
j := k8sJSONLog{
Log: fmt.Sprintf(format, v...),
Level: level,
Time: timestamp,
}
b, err := json.Marshal(j)
if err != nil {
panic(err)
}
e.Writer.Write(b)
}

View File

@ -66,7 +66,7 @@ func newCompatEmitter(logFD int) (*compatEmitter, error) {
if logFD > 0 {
f := os.NewFile(uintptr(logFD), "user log file")
target := log.MultiEmitter{c.sink, log.GoogleEmitter{&log.Writer{Next: f}}}
target := log.MultiEmitter{c.sink, log.K8sJSONEmitter{log.Writer{Next: f}}}
c.sink = &log.BasicLogger{Level: log.Info, Emitter: target}
}
return c, nil

View File

@ -157,12 +157,15 @@ type Config struct {
// LogFilename is the filename to log to, if not empty.
LogFilename string
// LogFormat is the log format, "text" or "json".
// LogFormat is the log format.
LogFormat string
// DebugLog is the path to log debug information to, if not empty.
DebugLog string
// DebugLogFormat is the log format for debug.
DebugLogFormat string
// FileAccess indicates how the filesystem is accessed.
FileAccess FileAccessType
@ -214,6 +217,7 @@ func (c *Config) ToFlags() []string {
"--log=" + c.LogFilename,
"--log-format=" + c.LogFormat,
"--debug-log=" + c.DebugLog,
"--debug-log-format=" + c.DebugLogFormat,
"--file-access=" + c.FileAccess.String(),
"--overlay=" + strconv.FormatBool(c.Overlay),
"--network=" + c.Network.String(),

View File

@ -38,17 +38,18 @@ var (
// Docker, and thus should not be changed.
rootDir = flag.String("root", "", "root directory for storage of container state")
logFilename = flag.String("log", "", "file path where internal debug information is written, default is stdout")
logFormat = flag.String("log-format", "text", "log format: text (default) or json")
logFormat = flag.String("log-format", "text", "log format: text (default), json, or json-k8s")
debug = flag.Bool("debug", false, "enable debug logging")
// These flags are unique to runsc, and are used to configure parts of the
// system that are not covered by the runtime spec.
// Debugging flags.
debugLog = flag.String("debug-log", "", "additional location for logs. If it ends with '/', log files are created inside the directory with default names. The following variables are available: %TIMESTAMP%, %COMMAND%.")
logPackets = flag.Bool("log-packets", false, "enable network packet logging")
logFD = flag.Int("log-fd", -1, "file descriptor to log to. If set, the 'log' flag is ignored.")
debugLogFD = flag.Int("debug-log-fd", -1, "file descriptor to write debug logs to. If set, the 'debug-log-dir' flag is ignored.")
debugLog = flag.String("debug-log", "", "additional location for logs. If it ends with '/', log files are created inside the directory with default names. The following variables are available: %TIMESTAMP%, %COMMAND%.")
logPackets = flag.Bool("log-packets", false, "enable network packet logging")
logFD = flag.Int("log-fd", -1, "file descriptor to log to. If set, the 'log' flag is ignored.")
debugLogFD = flag.Int("debug-log-fd", -1, "file descriptor to write debug logs to. If set, the 'debug-log-dir' flag is ignored.")
debugLogFormat = flag.String("debug-log-format", "text", "log format: text (default), json, or json-k8s")
// Debugging flags: strace related
strace = flag.Bool("strace", false, "enable strace")
@ -133,6 +134,7 @@ func main() {
LogFilename: *logFilename,
LogFormat: *logFormat,
DebugLog: *debugLog,
DebugLogFormat: *debugLogFormat,
FileAccess: fsAccess,
Overlay: *overlay,
Network: netType,
@ -166,15 +168,7 @@ func main() {
logFile = f
}
var e log.Emitter
switch *logFormat {
case "text":
e = log.GoogleEmitter{&log.Writer{Next: logFile}}
case "json":
e = log.JSONEmitter{log.Writer{Next: logFile}}
default:
cmd.Fatalf("invalid log format %q, must be 'json' or 'text'", *logFormat)
}
e := newEmitter(*logFormat, logFile)
subcommand := flag.CommandLine.Arg(0)
if *debugLogFD > -1 {
@ -195,13 +189,13 @@ func main() {
cmd.Fatalf("error dup'ing fd %d to stderr: %v", f.Fd(), err)
}
e = log.MultiEmitter{e, log.GoogleEmitter{&log.Writer{Next: f}}}
e = log.MultiEmitter{e, newEmitter(*debugLogFormat, f)}
} else if *debugLog != "" {
f, err := specutils.DebugLogFile(*debugLog, subcommand)
if err != nil {
cmd.Fatalf("error opening debug log file in %q: %v", *debugLog, err)
}
e = log.MultiEmitter{e, log.GoogleEmitter{&log.Writer{Next: f}}}
e = log.MultiEmitter{e, newEmitter(*debugLogFormat, f)}
}
log.SetTarget(e)
@ -236,6 +230,19 @@ func main() {
os.Exit(128)
}
func newEmitter(format string, logFile io.Writer) log.Emitter {
switch format {
case "text":
return &log.GoogleEmitter{&log.Writer{Next: logFile}}
case "json":
return &log.JSONEmitter{log.Writer{Next: logFile}}
case "json-k8s":
return &log.K8sJSONEmitter{log.Writer{Next: logFile}}
}
cmd.Fatalf("invalid log format %q, must be 'text', 'json', or 'json-k8s'", format)
panic("unreachable")
}
func init() {
// Set default root dir to something (hopefully) user-writeable.
*rootDir = "/var/run/runsc"