Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Add file based log driver #772

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions conmon-rs/server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ strum = { version = "0.24.1", features = ["derive"] }
shadow-rs = "=0.16.1"
multimap = "0.8.3"
tracing = "0.1.36"
tracing-appender = "0.2.2"
tracing-journald = "0.3.0"
tracing-subscriber = "0.3.15"
uuid = { version = "1.1.2", features = ["v4", "fast-rng", "macro-diagnostics"] }
Expand Down
21 changes: 13 additions & 8 deletions conmon-rs/server/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,18 @@ pub struct Config {
/// The logging level of the conmon server.
log_level: String,

#[get_copy = "pub"]
#[get = "pub"]
#[clap(
default_value(LogDriver::Systemd.into()),
env(concat!(prefix!(), "LOG_DRIVER")),
long("log-driver"),
env(concat!(prefix!(), "LOG_DRIVERS")),
multiple(true),
long("log-drivers"),
short('d'),
possible_values(LogDriver::iter().map(|x| x.into()).collect::<Vec<&str>>()),
value_name("DRIVER")
value_name("DRIVERS")
)]
/// The logging driver used by the conmon server.
log_driver: LogDriver,
/// The logging drivers used by the server. Can be specified multiple times.
log_drivers: Vec<LogDriver>,

#[get = "pub"]
#[clap(
Expand Down Expand Up @@ -128,11 +129,15 @@ pub struct Config {
#[strum(serialize_all = "lowercase")]
/// Available log drivers.
pub enum LogDriver {
/// Log to stdout
/// Log to stdout.
Stdout,

/// Use systemd journald as log driver
/// Use systemd journald as log driver.
Systemd,

/// Use a file destination as log driver. The log file path fill be generated to match
/// `[--runtime-dir]/logs/conmonrs.YYYY-MM-DD` and rotates on a daily basis.
File,
}

#[derive(
Expand Down
66 changes: 42 additions & 24 deletions conmon-rs/server/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use crate::{
use anyhow::{format_err, Context, Result};
use capnp::text_list::Reader;
use capnp_rpc::{rpc_twoparty_capnp::Side, twoparty, RpcSystem};
use clap::crate_name;
use conmon_common::conmon_capnp::conmon;
use futures::{AsyncReadExt, FutureExt};
use getset::Getters;
Expand Down Expand Up @@ -58,8 +59,8 @@ impl Server {
process::exit(0);
}

server.init_logging().context("set log verbosity")?;
server.config().validate().context("validate config")?;
server.init_logging().context("init logging")?;

Self::init().context("init self")?;
Ok(server)
Expand Down Expand Up @@ -108,30 +109,47 @@ impl Server {
LevelFilter::from_str(self.config().log_level()).context("convert log level filter")?;
let registry = tracing_subscriber::registry();

match self.config().log_driver() {
LogDriver::Stdout => {
let layer = tracing_subscriber::fmt::layer()
.with_target(true)
.with_line_number(true)
.with_filter(level);
registry
.with(layer)
.try_init()
.context("init stdout fmt layer")?;
info!("Using stdout logger");
}
LogDriver::Systemd => {
let layer = tracing_journald::layer()
.context("unable to connect to journald")?
.with_filter(level);
registry
.with(layer)
.try_init()
.context("init journald layer")?;
info!("Using systemd/journald logger");
}
}
let stdout = if self.config().log_drivers().contains(&LogDriver::Stdout) {
tracing_subscriber::fmt::layer()
.with_target(true)
.with_line_number(true)
.with_filter(level)
.into()
} else {
None
};

let systemd = if self.config().log_drivers().contains(&LogDriver::Systemd) {
tracing_journald::layer()
.context("unable to connect to journald")?
.with_filter(level)
.into()
} else {
None
};

let file = if self.config().log_drivers().contains(&LogDriver::File) {
let path = self.config().runtime_dir().join("logs");
let appender = tracing_appender::rolling::daily(path, crate_name!());
tracing_subscriber::fmt::layer()
.with_target(true)
.with_ansi(false)
.with_line_number(true)
.with_writer(appender)
.with_filter(level)
.into()
} else {
None
};

registry
.with(stdout)
.with(systemd)
.with(file)
.try_init()
.context("init registry")?;
info!("Set log level to: {}", self.config().log_level());

Ok(())
}

Expand Down
28 changes: 19 additions & 9 deletions pkg/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ type ConmonServerConfig struct {
// Can be "trace", "debug", "info", "warn", "error" or "off".
LogLevel string

// LogDriver is the possible server logging driver.
// Can be "stdout" or "systemd".
LogDriver string
// LogDrivers are the possible server logging drivers.
// Can be "stdout", "systemd" or both.
LogDrivers []string

// Runtime is the binary path of the OCI runtime to use to operate on the
// containers.
Expand Down Expand Up @@ -106,7 +106,7 @@ func NewConmonServerConfig(
) *ConmonServerConfig {
return &ConmonServerConfig{
LogLevel: LogLevelDebug,
LogDriver: LogDriverStdout,
LogDrivers: []string{LogDriverStdout},
Runtime: runtime,
RuntimeRoot: runtimeRoot,
ServerRunDir: serverRunDir,
Expand Down Expand Up @@ -212,7 +212,7 @@ func (c *ConmonClient) startServer(config *ConmonServerConfig) error {
Setpgid: true,
}

if config.LogDriver == LogDriverStdout {
if contains(config.LogDrivers, LogDriverStdout) {
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if config.Stdout != nil {
Expand All @@ -230,6 +230,16 @@ func (c *ConmonClient) startServer(config *ConmonServerConfig) error {
return nil
}

func contains[T comparable](haystack []T, needle T) bool {
for _, value := range haystack {
if value == needle {
return true
}
}

return false
}

func (c *ConmonClient) toArgs(config *ConmonServerConfig) (entrypoint string, args []string, err error) {
if c == nil {
return "", args, nil
Expand Down Expand Up @@ -263,11 +273,11 @@ func (c *ConmonClient) toArgs(config *ConmonServerConfig) (entrypoint string, ar
args = append(args, "--log-level", config.LogLevel)
}

if config.LogDriver != "" {
if err := validateLogDriver(config.LogDriver); err != nil {
for _, driver := range config.LogDrivers {
if err := validateLogDriver(driver); err != nil {
return "", args, fmt.Errorf("validate log driver: %w", err)
}
args = append(args, "--log-driver", config.LogDriver)
args = append(args, "--log-drivers", driver)
}

const cgroupManagerFlag = "--cgroup-manager"
Expand Down Expand Up @@ -297,7 +307,7 @@ func validateLogDriver(driver string) error {
return validateStringSlice(
"log driver",
driver,
LogDriverStdout, LogDriverSystemd,
LogDriverStdout, LogDriverSystemd, LogDriverFile,
)
}

Expand Down
9 changes: 9 additions & 0 deletions pkg/client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,15 @@ var _ = Describe("ConmonClient", func() {
} else {
Expect(version.CargoTree).To(BeEmpty())
}

// Validate the log file
logPath := filepath.Join(tr.tmpDir, "logs")
files, err := os.ReadDir(logPath)
Expect(err).To(BeNil())
Expect(files).To(HaveLen(1))
content, err := os.ReadFile(filepath.Join(logPath, files[0].Name()))
Expect(err).To(BeNil())
Expect(string(content)).To(ContainSubstring("Got a version request"))
})
}
})
Expand Down
5 changes: 5 additions & 0 deletions pkg/client/consts.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ const (
// LogDriverSystemd is the log driver printing to systemd journald.
LogDriverSystemd = "systemd"

// LogDriverFile is the file based log driver. The log file path fill be
// generated to match / `[config.ServerRunDir]/logs/conmonrs.YYYY-MM-DD`
// and rotates on a daily basis.
LogDriverFile = "file"

// LogLevelTrace is the log level printing only "trace" messages.
LogLevelTrace = "trace"

Expand Down
1 change: 1 addition & 0 deletions pkg/client/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ func (tr *testRunner) configGivenEnv() *client.ConmonClient {
logger := logrus.StandardLogger()
logger.Level = logrus.TraceLevel
cfg.ClientLogger = logger
cfg.LogDrivers = []string{client.LogDriverStdout, client.LogDriverFile}

sut, err := client.New(cfg)
Expect(err).To(BeNil())
Expand Down