Repository: scionproto/scion
Pull request #3828 (2020-07-13 06:32:26)

log: remove file logging
File logging support is removed without replacement. It is
recommended to use stdout logging at the appropriate level and collect the
logs manually via another mechanism (docker, journald, etc.)

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/scionproto/scion/3828)
<!-- Reviewable:end -->



Patch:
diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml
index 268a99abb..0cc2336e0 100644
--- a/.buildkite/pipeline.yml
+++ b/.buildkite/pipeline.yml
@@ -53,17 +53,6 @@ steps:
       automatic:
         - exit_status: -1  # Agent was lost
         - exit_status: 255 # Forced agent shutdown
-  - label: "IT: :bazel: "
-    if: build.message !~ /\[doc\]/
-    command:
-    - bazel test //integration/...
-    key: integration_tests
-    artifact_paths:
-      - "artifacts.out/**/*"
-    retry:
-      automatic:
-        - exit_status: -1  # Agent was lost
-        - exit_status: 255 # Forced agent shutdown
   - label: "IT: (svisor) Revocation tests"
     if: build.message !~ /\[doc\]/
     command:
diff --git a/acceptance/brutil/common.sh b/acceptance/brutil/common.sh
index 26b304a4b..be59517e1 100644
--- a/acceptance/brutil/common.sh
+++ b/acceptance/brutil/common.sh
@@ -58,7 +58,6 @@ test_config() {
 
     # Replace BR ID
     sed -i "s/id = .*$/id = \"${BRID}\"/g" "$BR_TOML"
-    sed -i "s/path = .*$/path = \"\/share\/logs\/${BRID}.log\"/g" "$BR_TOML"
 }
 
 test_run() {
diff --git a/acceptance/brutil/conf/br.toml b/acceptance/brutil/conf/br.toml
index 25208f567..5025bef92 100644
--- a/acceptance/brutil/conf/br.toml
+++ b/acceptance/brutil/conf/br.toml
@@ -2,6 +2,8 @@
 config_dir = "/share/conf"
 id = <AUTOFILLED>
 
-[log.file]
+[log.console]
 level = "debug"
-path = <AUTOFILLED>
+
+[features]
+allow_run_as_root = true
diff --git a/acceptance/brutil/conf/disp.toml b/acceptance/brutil/conf/disp.toml
index 66b7de370..60d7a431c 100644
--- a/acceptance/brutil/conf/disp.toml
+++ b/acceptance/brutil/conf/disp.toml
@@ -1,6 +1,8 @@
 [dispatcher]
 id = "dispatcher"
 
-[log.file]
+[log.console]
 level = "debug"
-path = "/share/logs/dispatcher.log"
+
+[features]
+allow_run_as_root = true
diff --git a/acceptance/brutil/docker-compose.yml b/acceptance/brutil/docker-compose.yml
index 0794532e1..dfce51b2f 100644
--- a/acceptance/brutil/docker-compose.yml
+++ b/acceptance/brutil/docker-compose.yml
@@ -8,7 +8,6 @@ x-br: &br
     - "/etc/passwd:/etc/passwd:ro"
     - "/etc/group:/etc/group:ro"
     - "/run/shm/dispatcher:/run/shm/dispatcher"
-    - "../../logs:/share/logs"
     - "${TEST_ARTIFACTS_DIR}/conf:/share/conf"
 services:
   dispatcher:
@@ -20,7 +19,6 @@ services:
       - "/etc/passwd:/etc/passwd:ro"
       - "/etc/group:/etc/group:ro"
       - "/run/shm/dispatcher:/run/shm/dispatcher"
-      - "../../logs:/share/logs"
       - "${TEST_ARTIFACTS_DIR}/conf:/share/conf"
   core-brA:
     <<: *br
diff --git a/acceptance/common/scion.py b/acceptance/common/scion.py
index 6ea1ab432..4aeb110a1 100644
--- a/acceptance/common/scion.py
+++ b/acceptance/common/scion.py
@@ -99,10 +99,10 @@ class SCION(ABC):
         """
         Overwrite or set the values in the toml files with the specified
         changes. The key in the change dictionary is a dot separated path
-        to the toml value. E.g. {'log.file.level': 'debug'} result in the
+        to the toml value. E.g. {'log.console.level': 'debug'} result in the
         toml file with the following set:
 
-        [log.file]
+        [log.console]
           level = "debug"
         """
         for f in files:
diff --git a/acceptance/sig_failover/docker-compose.yml b/acceptance/sig_failover/docker-compose.yml
index c36b36bfc..c069eb0f8 100644
--- a/acceptance/sig_failover/docker-compose.yml
+++ b/acceptance/sig_failover/docker-compose.yml
@@ -49,7 +49,6 @@ services:
       bridge1:
         ipv4_address: 242.254.100.2
     volumes:
-    - vol_logs:/share/logs:rw
     - vol_scion_disp_sig1-ff00_0_110:/run/shm/dispatcher:rw
   dispatcher2:
     container_name: dispatcher2
@@ -58,7 +57,6 @@ services:
       bridge2:
         ipv4_address: 242.254.200.2
     volumes:
-    - vol_logs:/share/logs:rw
     - vol_scion_disp_sig1-ff00_0_111:/run/shm/dispatcher:rw
   sig1:
     cap_add:
@@ -72,7 +70,6 @@ services:
     volumes:
     - vol_scion_disp_sig1-ff00_0_110:/run/shm/dispatcher:rw
     - /dev/net/tun:/dev/net/tun
-    - vol_logs:/share/logs:rw
   sig2:
     cap_add:
     - NET_ADMIN
@@ -85,7 +82,6 @@ services:
     volumes:
     - vol_scion_disp_sig1-ff00_0_111:/run/shm/dispatcher:rw
     - /dev/net/tun:/dev/net/tun
-    - vol_logs:/share/logs:rw
   tester1:
     container_name: tester1
     image: alpine
@@ -96,13 +92,7 @@ services:
     image: alpine
     network_mode: service:dispatcher2
     privileged: true
-  log_exporter:
-    container_name: log_exporter
-    image: alpine
-    volumes:
-    - vol_logs:/share/logs:ro
 version: '2.4'
 volumes:
-  vol_logs: null
   vol_scion_disp_sig1-ff00_0_110: null
   vol_scion_disp_sig1-ff00_0_111: null
diff --git a/acceptance/sig_short_exp_time/docker-compose.yml b/acceptance/sig_short_exp_time/docker-compose.yml
index c7b1854ed..65fc288fd 100644
--- a/acceptance/sig_short_exp_time/docker-compose.yml
+++ b/acceptance/sig_short_exp_time/docker-compose.yml
@@ -49,7 +49,6 @@ services:
       bridge1:
         ipv4_address: 242.254.100.2
     volumes:
-    - vol_logs:/share/logs:rw
     - vol_scion_disp_sig1-ff00_0_110:/run/shm/dispatcher:rw
   dispatcher2:
     container_name: dispatcher2
@@ -58,7 +57,6 @@ services:
       bridge2:
         ipv4_address: 242.254.200.2
     volumes:
-    - vol_logs:/share/logs:rw
     - vol_scion_disp_sig1-ff00_0_111:/run/shm/dispatcher:rw
   sig1:
     cap_add:
@@ -72,7 +70,6 @@ services:
     volumes:
     - vol_scion_disp_sig1-ff00_0_110:/run/shm/dispatcher:rw
     - /dev/net/tun:/dev/net/tun
-    - vol_logs:/share/logs:rw
   sig2:
     cap_add:
     - NET_ADMIN
@@ -85,7 +82,6 @@ services:
     volumes:
     - vol_scion_disp_sig1-ff00_0_111:/run/shm/dispatcher:rw
     - /dev/net/tun:/dev/net/tun
-    - vol_logs:/share/logs:rw
   tester1:
     container_name: tester1
     image: alpine
@@ -96,11 +92,6 @@ services:
     image: alpine
     network_mode: service:dispatcher2
     privileged: true
-  log_exporter:
-    container_name: log_exporter
-    image: alpine
-    volumes:
-    - vol_logs:/share/logs:ro
 version: '2.4'
 volumes:
   vol_logs: null
diff --git a/acceptance/sigutil/common.sh b/acceptance/sigutil/common.sh
index 9ea7f1150..b51ef0bf8 100755
--- a/acceptance/sigutil/common.sh
+++ b/acceptance/sigutil/common.sh
@@ -9,9 +9,6 @@ DST_IA=${DST_IA:-1-ff00:0:112}
 test_setup() {
     set -e
     ./scion.sh topology -c $TEST_TOPOLOGY -d --sig -n 242.254.0.0/16
-    for sig in gen/ISD1/*/sig*/sig.toml; do
-        sed -i '/\[log\.file\]/a flush_interval = 1' "$sig"
-    done
     ./scion.sh run nobuild
     ./tools/dc start 'tester*'
     sleep 7
@@ -56,7 +53,7 @@ reload_sig() {
     # Wait till the new config takes effect.
     sleep 3
     # Make sure that the reload actually happened.
-    COUNT=$(grep --text ".*Config reloaded.*" "logs/sig$1.log" | wc -l)
+    COUNT=$(./tools/dc scion logs scion_sig_$1 | grep --text ".*Config reloaded.*" | wc -l)
     if [ "$COUNT" != "$2" ]; then
             echo "Expected $2 config reloads, found $COUNT."
         exit 1
diff --git a/acceptance/topo_br_reload_util/util.sh b/acceptance/topo_br_reload_util/util.sh
index e12fa9e63..c36957a5e 100644
--- a/acceptance/topo_br_reload_util/util.sh
+++ b/acceptance/topo_br_reload_util/util.sh
@@ -13,7 +13,7 @@ DST_TOPO="gen/ISD1/AS$DST_AS_FILE/br$DST_IA_FILE-1/topology.json"
 . acceptance/common.sh
 
 check_logs() {
-    fgrep -q "$1" "logs/br$2-1.log" || fail "Not found: $1"
+    docker-compose -f gen/scion-dc.yml -p scion logs "scion_br$2-1" | fgrep -q "$1" || fail "Not found: $1"
 }
 
 check_connectivity() {
@@ -32,7 +32,6 @@ base_setup() {
 
 base_gen_topo() {
     ./scion.sh topology -c $TEST_TOPOLOGY -d
-    sed -i '/\[log\.file\]/a flush_interval = 1' gen/ISD1/*/br*/br.toml
 }
 
 base_run_topo() {
diff --git a/go.mod b/go.mod
index 812cd4ffc..ba485e57d 100644
--- a/go.mod
+++ b/go.mod
@@ -38,7 +38,6 @@ require (
 	golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5
 	golang.org/x/net v0.0.0-20191105084925-a882066a44e0
 	golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c
-	gopkg.in/natefinch/lumberjack.v2 v2.0.0-20170531160350-a96e63847dc3
 	gopkg.in/restruct.v1 v1.0.0-20151213023948-80ede2e57cc2
 	gopkg.in/yaml.v2 v2.3.0
 	zombiezen.com/go/capnproto2 v0.0.0-20190813022230-ddfb9bb855fa
diff --git a/go.sum b/go.sum
index 9a2930f92..b65a2e111 100644
--- a/go.sum
+++ b/go.sum
@@ -411,8 +411,6 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8
 gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
 gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
 gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
-gopkg.in/natefinch/lumberjack.v2 v2.0.0-20170531160350-a96e63847dc3 h1:AFxeG48hTWHhDTQDk/m2gorfVHUEa9vo3tp3D7TzwjI=
-gopkg.in/natefinch/lumberjack.v2 v2.0.0-20170531160350-a96e63847dc3/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
 gopkg.in/restruct.v1 v1.0.0-20151213023948-80ede2e57cc2 h1:pqzOumCQ6icMR4sIIYRe2w7xCERvcPOFx22W9jSRsWg=
 gopkg.in/restruct.v1 v1.0.0-20151213023948-80ede2e57cc2/go.mod h1:WJaLhyHHEQFOgwIxu/SJxvUHJA18glYsMETBTMIySTY=
 gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
diff --git a/go/lib/log/BUILD.bazel b/go/lib/log/BUILD.bazel
index e8694306b..3f3b8cca7 100644
--- a/go/lib/log/BUILD.bazel
+++ b/go/lib/log/BUILD.bazel
@@ -23,7 +23,6 @@ go_library(
         "@com_github_kormat_fmt15//:go_default_library",
         "@com_github_mattn_go_isatty//:go_default_library",
         "@com_github_opentracing_opentracing_go//:go_default_library",
-        "@in_gopkg_natefinch_lumberjack_v2//:go_default_library",
     ],
 )
 
@@ -39,7 +38,6 @@ go_test(
     deps = [
         "//go/lib/config:go_default_library",
         "//go/lib/log/logtest:go_default_library",
-        "//go/lib/xtest:go_default_library",
         "@com_github_pelletier_go_toml//:go_default_library",
         "@com_github_stretchr_testify//assert:go_default_library",
     ],
diff --git a/go/lib/log/config.go b/go/lib/log/config.go
index 313107495..ce2a1e4a4 100644
--- a/go/lib/log/config.go
+++ b/go/lib/log/config.go
@@ -15,7 +15,6 @@
 package log
 
 import (
-	"fmt"
 	"io"
 	"strings"
 
@@ -24,24 +23,12 @@ import (
 
 const (
 	// DefaultConsoleLevel is the default log level for the console.
-	DefaultConsoleLevel = "crit"
-	// DefaultFileLevel is the defaul log level for files.
-	DefaultFileLevel = "debug"
-	// DefaultFileSizeMiB is the default rotation size in MiB.
-	DefaultFileSizeMiB = 50
-	// DefaultFileMaxAgeDays is the default rollover age in days.
-	DefaultFileMaxAgeDays = 7
-	// DefaultFileMaxBackups is the default maximum amount of file backups.
-	DefaultFileMaxBackups = 10
-	// DefaultFileFlushSeconds is the default amount of time between flushes.
-	DefaultFileFlushSeconds uint = 5
+	DefaultConsoleLevel = "info"
 )
 
 // Config is the configuration for the logger.
 type Config struct {
 	config.NoValidator
-	// File is the configuration for file logging.
-	File FileConfig `toml:"file,omitempty"`
 	// Console is the configuration for the console logging.
 	Console ConsoleConfig `toml:"console,omitempty"`
 }
@@ -49,17 +36,12 @@ type Config struct {
 // InitDefaults populates unset fields in cfg to their default values (if they
 // have one).
 func (c *Config) InitDefaults() {
-	c.File.InitDefaults()
 	c.Console.InitDefaults()
 }
 
 // Sample writes the sample configuration to the dst writer.
 func (c *Config) Sample(dst io.Writer, path config.Path, ctx config.CtxMap) {
 	config.WriteSample(dst, path, nil,
-		config.StringSampler{
-			Text: fmt.Sprintf(loggingFileSample, ctx[config.ID]),
-			Name: "file",
-		},
 		config.StringSampler{
 			Text: loggingConsoleSample,
 			Name: "console",
@@ -73,54 +55,6 @@ func (c *Config) ConfigName() string {
 	return "log"
 }
 
-// FileConfig is the configuration for the file logger.
-type FileConfig struct {
-	// Path is the location of the logging file. If unset, no file logging is
-	// performed.
-	Path string `toml:"path,omitempty"`
-	// Level of file logging (defaults to DefaultFileLevel).
-	Level string `toml:"level,omitempty"`
-	// Size is the max size of log file in MiB (defaults to DefaultFileSizeMiB).
-	Size uint `toml:"size,omitempty"`
-	// MaxAge is the max age of log file in days (defaults to
-	// DefaultFileMaxAgeDays).
-	MaxAge uint `toml:"max_age,omitempty"`
-	// MaxBackups is the max number of log files to retain (defaults to
-	// DefaultFileMaxBackups).
-	MaxBackups uint `toml:"max_backups,omitempty"`
-	// FlushInterval specifies how frequently to flush to the log file, in
-	// seconds (defaults to DefaultFileFlushSeconds).
-	FlushInterval *uint `toml:"flush_interval,omitempty"`
-	// Compress can be set to enable rotated file compression.
-	Compress bool `toml:"compress,omitempty"`
-	// Format of the file logging. (human|json)
-	Format string `toml:"format,omitempty"`
-}
-
-// InitDefaults populates unset fields in cfg to their default values (if they
-// have one).
-func (c *FileConfig) InitDefaults() {
-	if c.Level == "" {
-		c.Level = DefaultFileLevel
-	}
-	if c.Size == 0 {
-		c.Size = DefaultFileSizeMiB
-	}
-	if c.MaxAge == 0 {
-		c.MaxAge = DefaultFileMaxAgeDays
-	}
-	if c.MaxBackups == 0 {
-		c.MaxBackups = DefaultFileMaxBackups
-	}
-	if c.FlushInterval == nil {
-		s := DefaultFileFlushSeconds
-		c.FlushInterval = &s
-	}
-	if !strings.EqualFold(c.Format, "json") {
-		c.Format = "human"
-	}
-}
-
 // ConsoleConfig is the config for the console logger.
 type ConsoleConfig struct {
 	// Level of console logging (defaults to DefaultConsoleLevel).
diff --git a/go/lib/log/log.go b/go/lib/log/log.go
index 02326e941..de07badd1 100644
--- a/go/lib/log/log.go
+++ b/go/lib/log/log.go
@@ -16,18 +16,14 @@
 package log
 
 import (
-	"io"
 	"os"
-	"path/filepath"
 	"runtime/debug"
 	"strings"
-	"time"
 
 	"github.com/inconshreveable/log15"
 	// Allows customization of timestamps and multi-line support
 	"github.com/kormat/fmt15"
 	"github.com/mattn/go-isatty"
-	"gopkg.in/natefinch/lumberjack.v2"
 
 	"github.com/scionproto/scion/go/lib/common"
 	"github.com/scionproto/scion/go/lib/serrors"
@@ -42,63 +38,15 @@ var logBuf *syncBuf
 // Setup configures the logging library with the given config.
 func Setup(cfg Config) error {
 	cfg.InitDefaults()
-	var file, console log15.Handler
+	var console log15.Handler
 	var err error
-	if file, err = setupFile(cfg.File); err != nil {
-		return err
-	}
 	if console, err = setupConsole(cfg.Console); err != nil {
 		return err
 	}
-	setHandlers(file, console)
+	setHandlers(console)
 	return nil
 }
 
-func setupFile(cfg FileConfig) (log15.Handler, error) {
-	if cfg.Path == "" {
-		return nil, nil
-	}
-
-	if err := os.MkdirAll(filepath.Dir(cfg.Path), os.ModePerm); err != nil {
-		return nil, serrors.WrapStr("unable create log directory", err,
-			"dir", filepath.Dir(cfg.Path))
-	}
-
-	logLvl, err := log15.LvlFromString(cfg.Level)
-	if err != nil {
-		return nil, serrors.WrapStr("unable to parse log.file.level", err, "level", cfg.Level)
-	}
-
-	var logger io.WriteCloser
-	logger = &lumberjack.Logger{
-		Filename:   cfg.Path,
-		MaxSize:    int(cfg.Size),   // MiB
-		MaxAge:     int(cfg.MaxAge), // days
-		MaxBackups: int(cfg.MaxBackups),
-		Compress:   cfg.Compress,
-	}
-
-	if cfg.FlushInterval != nil {
-		logBuf = newSyncBuf(logger)
-		logger = logBuf
-	}
-	format := fmt15.Fmt15Format(nil)
-	if strings.EqualFold(cfg.Format, "json") {
-		format = log15.JsonFormat()
-	}
-	handler := log15.LvlFilterHandler(logLvl, log15.StreamHandler(logger, format))
-
-	if cfg.FlushInterval != nil && *cfg.FlushInterval > 0 {
-		go func() {
-			defer HandlePanic()
-			for range time.Tick(time.Duration(*cfg.FlushInterval) * time.Second) {
-				Flush()
-			}
-		}()
-	}
-	return handler, nil
-}
-
 func setupConsole(cfg ConsoleConfig) (log15.Handler, error) {
 	lvl, err := log15.LvlFromString(cfg.Level)
 	if err != nil {
@@ -116,14 +64,10 @@ func setupConsole(cfg ConsoleConfig) (log15.Handler, error) {
 	return handler, nil
 }
 
-func setHandlers(logFileHandler, logConsHandler log15.Handler) {
+func setHandlers(logConsHandler log15.Handler) {
 	var handler log15.Handler
 	switch {
-	case logFileHandler != nil && logConsHandler != nil:
-		handler = log15.MultiHandler(logFileHandler, logConsHandler)
-	case logFileHandler != nil: // logConsHandler == nil
-		handler = logFileHandler
-	case logConsHandler != nil: // logFileHandler == nil
+	case logConsHandler != nil:
 		handler = logConsHandler
 	}
 	log15.Root().SetHandler(handler)
diff --git a/go/lib/log/sample.go b/go/lib/log/sample.go
index dc62d0753..a5f661e9b 100644
--- a/go/lib/log/sample.go
+++ b/go/lib/log/sample.go
@@ -14,34 +14,9 @@
 
 package log
 
-const loggingFileSample = `
-# Location of the logging file. If not specified, logging to file is disabled.
-path = "/var/log/scion/%s.log"
-
-# File logging level. (trace|debug|info|warn|error|crit) (default debug)
-level = "debug"
-
-# Max size of log file in MiB. (default 50)
-size = 50
-
-# Max age of log file in days. (default 7)
-max_age = 7
-
-# Maximum number of log files to retain. (default 10)
-max_backups = 10
-
-# How frequently to flush to the log file, in seconds. If 0, all messages
-# are immediately flushed. If negative, messages are never flushed
-# automatically. (default 5)
-flush_interval = 5
-
-# Logging fromat (human|json) (default human)
-format = "human"
-`
-
 const loggingConsoleSample = `
-# Console logging level (trace|debug|info|warn|error|crit) (default crit)
-level = "crit"
+# Console logging level (debug|info|error) (default info)
+level = "info"
 
 # Logging fromat (human|json) (default human)
 format = "human"
diff --git a/go_deps.bzl b/go_deps.bzl
index cec2c4507..c82de0d89 100644
--- a/go_deps.bzl
+++ b/go_deps.bzl
@@ -1083,12 +1083,6 @@ def go_deps():
         sum = "h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=",
         version = "v0.9.1",
     )
-    go_repository(
-        name = "in_gopkg_natefinch_lumberjack_v2",
-        importpath = "gopkg.in/natefinch/lumberjack.v2",
-        sum = "h1:AFxeG48hTWHhDTQDk/m2gorfVHUEa9vo3tp3D7TzwjI=",
-        version = "v2.0.0-20170531160350-a96e63847dc3",
-    )
     go_repository(
         name = "in_gopkg_restruct_v1",
         importpath = "gopkg.in/restruct.v1",
diff --git a/integration/service_filelog/BUILD.bazel b/integration/service_filelog/BUILD.bazel
deleted file mode 100644
index 22088d1b7..000000000
--- a/integration/service_filelog/BUILD.bazel
+++ /dev/null
@@ -1,24 +0,0 @@
-load("@io_bazel_rules_docker//container:container.bzl", "container_image")
-load("@rules_python//python:defs.bzl", "py_test")
-load("@pip3_deps//:requirements.bzl", "requirement")
-
-py_test(
-    name = "test",
-    srcs = ["test.py"],
-    data = [":cs.tar"],
-    deps = [
-        requirement("plumbum"),
-    ],
-)
-
-container_image(
-    name = "cs",
-    base = "//docker:cs_debug",
-    entrypoint = [
-        "/app/cs",
-        "--config",
-        "/cs.toml",
-    ],
-    files = ["testdata/cs.toml"],
-    stamp = False,
-)
diff --git a/licenses/data/in_gopkg_natefinch_lumberjack_v2/LICENSE b/licenses/data/in_gopkg_natefinch_lumberjack_v2/LICENSE
deleted file mode 100644
index c3d4cc307..000000000
--- a/licenses/data/in_gopkg_natefinch_lumberjack_v2/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2014 Nate Finch 
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
\ No newline at end of file
diff --git a/python/topology/docker.py b/python/topology/docker.py
index e93e5380f..00d4e4dcf 100644
--- a/python/topology/docker.py
+++ b/python/topology/docker.py
@@ -132,7 +132,6 @@ class DockerGenerator(object):
                 'volumes': [
                     *DOCKER_USR_VOL,
                     self._disp_vol(disp_id),
-                    self._logs_vol(),
                     '%s:/share/conf:ro' % os.path.join(base, k)
                 ],
                 'command': []
@@ -168,7 +167,6 @@ class DockerGenerator(object):
                 'volumes': [
                     *DOCKER_USR_VOL,
                     self._cache_vol(),
-                    self._logs_vol(),
                     self._certs_vol(),
                     '%s:/share/conf:ro' % os.path.join(base, k),
                     self._disp_vol(k),
@@ -187,7 +185,6 @@ class DockerGenerator(object):
             'networks': {},
             'volumes': [
                 *DOCKER_USR_VOL,
-                self._logs_vol()
             ]
         }
         keys = list(topo.get("border_routers", {})) + list(topo.get("control_service", {}))
@@ -231,7 +228,6 @@ class DockerGenerator(object):
                 *DOCKER_USR_VOL,
                 self._disp_vol(disp_id),
                 self._cache_vol(),
-                self._logs_vol(),
                 self._certs_vol(),
                 '%s:/share/conf:ro' % os.path.join(base, 'endhost'),
             ],
@@ -244,9 +240,6 @@ class DockerGenerator(object):
     def _disp_vol(self, disp_id):
         return 'vol_%sdisp_%s:/run/shm/dispatcher:rw' % (self.prefix, disp_id)
 
-    def _logs_vol(self):
-        return self.output_base + '/logs:/share/logs:rw'
-
     def _cache_vol(self):
         return self.output_base + '/gen-cache:/share/cache:rw'
 
diff --git a/python/topology/go.py b/python/topology/go.py
index ad1f29a75..177ba358e 100755
--- a/python/topology/go.py
+++ b/python/topology/go.py
@@ -307,15 +307,11 @@ class GoGenerator(object):
         return entry
 
     def _log_entry(self, name):
-        entry = {
-            'file': {
-                'path': os.path.join(self.log_dir, "%s.log" % name),
+        return {
+            'console': {
                 'level': self.log_level,
             },
         }
-        if self.args.docker:
-            entry['console'] = {'level': self.log_level}
-        return entry
 
     def _metrics_entry(self, infra_elem, base_port):
         a = prom_addr(infra_elem['addr'], base_port)
diff --git a/python/topology/sig.py b/python/topology/sig.py
index a1341dc0c..bbfce9e47 100644
--- a/python/topology/sig.py
+++ b/python/topology/sig.py
@@ -79,7 +79,6 @@ class SIGGenerator(object):
             'networks': {},
             'volumes': [
                 *DOCKER_USR_VOL,
-                self._logs_vol(),
                 self._disp_vol(topo_id),
                 '%s:/share/conf:rw' % os.path.join(base, 'disp_sig_%s' % topo_id.file_fmt()),
             ]
@@ -112,7 +111,6 @@ class SIGGenerator(object):
                 self._disp_vol(topo_id),
                 '/dev/net/tun:/dev/net/tun',
                 '%s/sig%s:/share/conf' % (base, topo_id.file_fmt()),
-                self._logs_vol()
             ],
             'network_mode': 'service:scion_disp_sig_%s' % topo_id.file_fmt(),
             'command': [remote_nets(self.args.networks, topo_id)]
@@ -157,12 +155,8 @@ class SIGGenerator(object):
                 'address': socket_address_str(sciond_ip, SD_API_PORT),
             },
             'log': {
-                'file': {
-                    'level': log_level,
-                    'path': '/share/logs/%s.log' % name
-                },
                 'console': {
-                    'level': 'error',
+                    'level': log_level,
                 }
             },
             'metrics': {
@@ -177,6 +171,3 @@ class SIGGenerator(object):
 
     def _disp_vol(self, topo_id):
         return 'vol_scion_%sdisp_sig_%s:/run/shm/dispatcher:rw' % (self.prefix, topo_id.file_fmt())
-
-    def _logs_vol(self):
-        return self.output_base + '/logs:/share/logs:rw'
diff --git a/python/topology/supervisor.py b/python/topology/supervisor.py
index 21977b823..8a1d1db7c 100755
--- a/python/topology/supervisor.py
+++ b/python/topology/supervisor.py
@@ -135,5 +135,5 @@ class SupervisorGenerator(object):
         return entry
 
     def _mk_cmd(self, name, cmd_args):
-        return "bash -c 'exec %s &>logs/%s.OUT'" % (
+        return "bash -c 'exec %s &>logs/%s.log'" % (
             " ".join(['"%s"' % arg for arg in cmd_args]), name)


Test patch:
diff --git a/acceptance/bs_add_link_acceptance/test b/acceptance/bs_add_link_acceptance/test
index 8f198fd08..ba34c850a 100755
--- a/acceptance/bs_add_link_acceptance/test
+++ b/acceptance/bs_add_link_acceptance/test
@@ -67,10 +67,6 @@ class TestSetup(CmdBase):
         self.cmd_setup()
         self.scion.topology('topology/tiny.topo')
         self.modify_topologies()
-        self.scion.set_configs({
-            'log.file.flush_interval': 1,
-            'log.file.level': 'debug',
-        }, local.path('gen/ISD1') // '*/cs*/cs.toml')
         self.scion.run()
         if not self.no_docker:
             self.tools_dc('start', 'tester*')
diff --git a/acceptance/sig_failover/test b/acceptance/sig_failover/test
index 457c50ee6..89326e78b 100755
--- a/acceptance/sig_failover/test
+++ b/acceptance/sig_failover/test
@@ -87,8 +87,8 @@ RC=$?
 OUTPUT_DIR=$TEST_UNDECLARED_OUTPUTS_DIR
 mkdir -p $OUTPUT_DIR/logs
 
-for FILE in sig1-ff00_0_110.log sig1-ff00_0_111.log disp_1-ff00_0_110.log disp_1-ff00_0_111.log; do
-    docker-compose -f acceptance/sig_failover/docker-compose.yml run log_exporter cat /share/logs/$FILE > $OUTPUT_DIR/logs/$FILE
+for CNTR in sig1 sig2 dispatcher1 dispatcher2; do
+    docker-compose -f acceptance/sig_failover/docker-compose.yml logs "$CNTR" > "$OUTPUT_DIR/logs/$CNTR.log"
 done
 
 docker-compose -f acceptance/sig_failover/docker-compose.yml down -v
diff --git a/acceptance/sig_failover/testdata/1-ff00_0_110/dispatcher/disp.toml b/acceptance/sig_failover/testdata/1-ff00_0_110/dispatcher/disp.toml
index a338e76e7..bdac3aa86 100644
--- a/acceptance/sig_failover/testdata/1-ff00_0_110/dispatcher/disp.toml
+++ b/acceptance/sig_failover/testdata/1-ff00_0_110/dispatcher/disp.toml
@@ -4,6 +4,5 @@ id = "disp_1-ff00_0_110"
 [features]
 allow_run_as_root = true
 
-[log.file]
+[log.console]
 level = "debug"
-path = "/share/logs/disp_1-ff00_0_110.log"
diff --git a/acceptance/sig_failover/testdata/1-ff00_0_110/sig/sig.toml b/acceptance/sig_failover/testdata/1-ff00_0_110/sig/sig.toml
index a515b8b0f..8ae421502 100644
--- a/acceptance/sig_failover/testdata/1-ff00_0_110/sig/sig.toml
+++ b/acceptance/sig_failover/testdata/1-ff00_0_110/sig/sig.toml
@@ -10,7 +10,5 @@ allow_run_as_root = true
 [sciond_connection]
 fake_data = "/fake_sciond.json"
 
-[log.file]
-flush_interval = 1
+[log.console]
 level = "debug"
-path = "/share/logs/sig1-ff00_0_110.log"
diff --git a/acceptance/sig_failover/testdata/1-ff00_0_111/dispatcher/disp.toml b/acceptance/sig_failover/testdata/1-ff00_0_111/dispatcher/disp.toml
index 14e542dfd..596ceb162 100644
--- a/acceptance/sig_failover/testdata/1-ff00_0_111/dispatcher/disp.toml
+++ b/acceptance/sig_failover/testdata/1-ff00_0_111/dispatcher/disp.toml
@@ -4,6 +4,5 @@ id = "disp_1-ff00_0_111"
 [features]
 allow_run_as_root = true
 
-[log.file]
+[log.console]
 level = "debug"
-path = "/share/logs/disp_1-ff00_0_111.log"
diff --git a/acceptance/sig_failover/testdata/1-ff00_0_111/sig/sig.toml b/acceptance/sig_failover/testdata/1-ff00_0_111/sig/sig.toml
index 0f3887251..5ab481ce6 100644
--- a/acceptance/sig_failover/testdata/1-ff00_0_111/sig/sig.toml
+++ b/acceptance/sig_failover/testdata/1-ff00_0_111/sig/sig.toml
@@ -10,7 +10,5 @@ allow_run_as_root = true
 [sciond_connection]
 fake_data = "/fake_sciond.json"
 
-[log.file]
-flush_interval = 1
+[log.console]
 level = "debug"
-path = "/share/logs/sig1-ff00_0_111.log"
diff --git a/acceptance/sig_short_exp_time/test b/acceptance/sig_short_exp_time/test
index 3f790bc8b..66a39f26a 100755
--- a/acceptance/sig_short_exp_time/test
+++ b/acceptance/sig_short_exp_time/test
@@ -96,8 +96,8 @@ RC=$?
 OUTPUT_DIR=$TEST_UNDECLARED_OUTPUTS_DIR
 mkdir -p $OUTPUT_DIR/logs
 
-for FILE in sig1-ff00_0_110.log sig1-ff00_0_111.log disp_1-ff00_0_110.log disp_1-ff00_0_111.log; do
-    docker-compose -f acceptance/sig_short_exp_time/docker-compose.yml run log_exporter cat /share/logs/$FILE > $OUTPUT_DIR/logs/$FILE
+for CNTR in sig1 sig2 dispatcher1 dispatcher2; do
+    docker-compose -f acceptance/sig_short_exp_time/docker-compose.yml logs "$CNTR" > "$OUTPUT_DIR/logs/$CNTR.log"
 done
 
 docker-compose -f acceptance/sig_short_exp_time/docker-compose.yml down -v
diff --git a/acceptance/sig_short_exp_time/testdata/1-ff00_0_110/dispatcher/disp.toml b/acceptance/sig_short_exp_time/testdata/1-ff00_0_110/dispatcher/disp.toml
index a338e76e7..bdac3aa86 100644
--- a/acceptance/sig_short_exp_time/testdata/1-ff00_0_110/dispatcher/disp.toml
+++ b/acceptance/sig_short_exp_time/testdata/1-ff00_0_110/dispatcher/disp.toml
@@ -4,6 +4,5 @@ id = "disp_1-ff00_0_110"
 [features]
 allow_run_as_root = true
 
-[log.file]
+[log.console]
 level = "debug"
-path = "/share/logs/disp_1-ff00_0_110.log"
diff --git a/acceptance/sig_short_exp_time/testdata/1-ff00_0_110/sig/sig.toml b/acceptance/sig_short_exp_time/testdata/1-ff00_0_110/sig/sig.toml
index a515b8b0f..8ae421502 100644
--- a/acceptance/sig_short_exp_time/testdata/1-ff00_0_110/sig/sig.toml
+++ b/acceptance/sig_short_exp_time/testdata/1-ff00_0_110/sig/sig.toml
@@ -10,7 +10,5 @@ allow_run_as_root = true
 [sciond_connection]
 fake_data = "/fake_sciond.json"
 
-[log.file]
-flush_interval = 1
+[log.console]
 level = "debug"
-path = "/share/logs/sig1-ff00_0_110.log"
diff --git a/acceptance/sig_short_exp_time/testdata/1-ff00_0_111/dispatcher/disp.toml b/acceptance/sig_short_exp_time/testdata/1-ff00_0_111/dispatcher/disp.toml
index 14e542dfd..596ceb162 100644
--- a/acceptance/sig_short_exp_time/testdata/1-ff00_0_111/dispatcher/disp.toml
+++ b/acceptance/sig_short_exp_time/testdata/1-ff00_0_111/dispatcher/disp.toml
@@ -4,6 +4,5 @@ id = "disp_1-ff00_0_111"
 [features]
 allow_run_as_root = true
 
-[log.file]
+[log.console]
 level = "debug"
-path = "/share/logs/disp_1-ff00_0_111.log"
diff --git a/acceptance/sig_short_exp_time/testdata/1-ff00_0_111/sig/sig.toml b/acceptance/sig_short_exp_time/testdata/1-ff00_0_111/sig/sig.toml
index 0f3887251..5ab481ce6 100644
--- a/acceptance/sig_short_exp_time/testdata/1-ff00_0_111/sig/sig.toml
+++ b/acceptance/sig_short_exp_time/testdata/1-ff00_0_111/sig/sig.toml
@@ -10,7 +10,5 @@ allow_run_as_root = true
 [sciond_connection]
 fake_data = "/fake_sciond.json"
 
-[log.file]
-flush_interval = 1
+[log.console]
 level = "debug"
-path = "/share/logs/sig1-ff00_0_111.log"
diff --git a/go/lib/log/log_test.go b/go/lib/log/log_test.go
index e5a5488a6..029ff4c7e 100644
--- a/go/lib/log/log_test.go
+++ b/go/lib/log/log_test.go
@@ -16,19 +16,14 @@
 package log_test
 
 import (
-	"path/filepath"
 	"testing"
 
 	"github.com/stretchr/testify/assert"
 
 	"github.com/scionproto/scion/go/lib/log"
-	"github.com/scionproto/scion/go/lib/xtest"
 )
 
 func TestSetup(t *testing.T) {
-	tmpDir, cleanF := xtest.MustTempDir("", "test-folder")
-	defer cleanF()
-
 	tests := map[string]struct {
 		cfg       log.Config
 		assertErr assert.ErrorAssertionFunc
@@ -37,23 +32,10 @@ func TestSetup(t *testing.T) {
 			cfg:       log.Config{},
 			assertErr: assert.NoError,
 		},
-		"invalid file level": {
-			cfg:       log.Config{File: log.FileConfig{Path: "test/foo", Level: "invalid"}},
-			assertErr: assert.Error,
-		},
 		"invalid console level": {
 			cfg:       log.Config{Console: log.ConsoleConfig{Level: "invalid"}},
 			assertErr: assert.Error,
 		},
-		"cannot create, errors": {
-			cfg:       log.Config{File: log.FileConfig{Path: "/sys/aka/doesnt/exist"}},
-			assertErr: assert.Error,
-		},
-
-		"can create, nil": {
-			cfg:       log.Config{File: log.FileConfig{Path: filepath.Join(tmpDir, "new")}},
-			assertErr: assert.NoError,
-		},
 	}
 
 	for name, test := range tests {
diff --git a/go/lib/log/logtest/config.go b/go/lib/log/logtest/config.go
index ea13343d2..8c5c30ffc 100644
--- a/go/lib/log/logtest/config.go
+++ b/go/lib/log/logtest/config.go
@@ -15,7 +15,6 @@
 package logtest
 
 import (
-	"fmt"
 	"testing"
 
 	"github.com/stretchr/testify/assert"
@@ -28,13 +27,6 @@ func InitTestLogging(cfg *log.Config) {}
 
 // CheckTestLogging checks that the given config matches the sample values.
 func CheckTestLogging(t *testing.T, cfg *log.Config, id string) {
-	assert.Equal(t, fmt.Sprintf("/var/log/scion/%s.log", id), cfg.File.Path)
-	assert.Equal(t, log.DefaultFileLevel, cfg.File.Level)
-	assert.Equal(t, log.DefaultFileSizeMiB, int(cfg.File.Size))
-	assert.Equal(t, log.DefaultFileMaxAgeDays, int(cfg.File.MaxAge))
-	assert.Equal(t, log.DefaultFileMaxBackups, int(cfg.File.MaxBackups))
-	assert.Equal(t, log.DefaultFileFlushSeconds, *cfg.File.FlushInterval)
 	assert.Equal(t, log.DefaultConsoleLevel, cfg.Console.Level)
-	assert.Equal(t, "human", cfg.File.Format)
 	assert.Equal(t, "human", cfg.Console.Format)
 }
diff --git a/integration/service_filelog/test.py b/integration/service_filelog/test.py
deleted file mode 100644
index 4c08074cc..000000000
--- a/integration/service_filelog/test.py
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/usr/bin/env python3
-
-# Copyright 2020 Anapaya Systems
-
-from pathlib import Path
-import shutil
-import sys
-import tempfile
-
-from plumbum import cli, local
-from plumbum.cmd import docker
-
-
-class Test(cli.Application):
-    """
-    Tests that the CS application logs to a file.
-    """
-    def main(self):
-        tmpdir = tempfile.mkdtemp(prefix='service_filelog.')
-        print(docker('image', 'load', '-i', './integration/service_filelog/cs.tar'))
-        name = 'service_filelog_test'
-        try:
-            args = ['run', '--name', name, '-v', '{}:/share/logs'.format(tmpdir),
-                    'bazel/integration/service_filelog:cs']
-            print('docker', *args)
-            print(docker(*args, retcode=1))
-            logfile = Path('{}/cs.log'.format(tmpdir))
-            if not logfile.is_file():
-                print('{} is not a file'.format(logfile))
-                sys.exit(1)
-            if logfile.stat().st_size == 0:
-                print('{} is empty'.format(logfile))
-                sys.exit(1)
-        finally:
-            docker('logs', name)
-            docker('rm', '-f', name)
-            docker('rmi', 'bazel/integration/service_filelog:cs')
-            shutil.rmtree(tmpdir, ignore_errors=True)
-
-if __name__ == "__main__":
-    Test.run()
diff --git a/integration/service_filelog/testdata/cs.toml b/integration/service_filelog/testdata/cs.toml
deleted file mode 100644
index a3cd313a2..000000000
--- a/integration/service_filelog/testdata/cs.toml
+++ /dev/null
@@ -1,4 +0,0 @@
-[general]
-    id = "cs-1"
-[log.file]
-    path = "/share/logs/cs.log"