summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorFabricio Voznika <fvoznika@google.com>2018-11-01 17:43:50 -0700
committerShentubot <shentubot@google.com>2018-11-01 17:44:58 -0700
commitb6b81fd04ba93db3268ff649c9d23a25c9b89db5 (patch)
tree730c112ed3d8aed5696466672f5c3a2eb16cb9a7
parent9d69d85bc13d4f0956a39951b5cd6777f938cffd (diff)
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
-rw-r--r--pkg/log/BUILD1
-rw-r--r--pkg/log/json_k8s.go47
-rw-r--r--runsc/boot/compat.go2
-rw-r--r--runsc/boot/config.go6
-rw-r--r--runsc/main.go39
5 files changed, 77 insertions, 18 deletions
diff --git a/pkg/log/BUILD b/pkg/log/BUILD
index bf85b4494..94ac66db3 100644
--- a/pkg/log/BUILD
+++ b/pkg/log/BUILD
@@ -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",
diff --git a/pkg/log/json_k8s.go b/pkg/log/json_k8s.go
new file mode 100644
index 000000000..9c2f8d2b7
--- /dev/null
+++ b/pkg/log/json_k8s.go
@@ -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)
+}
diff --git a/runsc/boot/compat.go b/runsc/boot/compat.go
index d18c2f802..4c49e90e3 100644
--- a/runsc/boot/compat.go
+++ b/runsc/boot/compat.go
@@ -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
diff --git a/runsc/boot/config.go b/runsc/boot/config.go
index 9ebbde424..2d89ad87e 100644
--- a/runsc/boot/config.go
+++ b/runsc/boot/config.go
@@ -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(),
diff --git a/runsc/main.go b/runsc/main.go
index 4a92db7c0..c0ee04216 100644
--- a/runsc/main.go
+++ b/runsc/main.go
@@ -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"