Repository: firecracker-microvm/firecracker-containerd
Pull request #430 (2020-05-29 23:48:05)

Measure only CreateVM

*Issue #, if available:*

NA

*Description of changes:*

Previously the benchmark was measuring both CreateVM and StopVM due to
Go's benchmark's limitation.

Since we mostly care CreateVM, this change removes StopVM from
the measurement.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.



Patch:
diff --git a/config/config.go b/config/config.go
index 49ef485..acc1499 100644
--- a/config/config.go
+++ b/config/config.go
@@ -20,7 +20,6 @@ import (
 
 	"github.com/pkg/errors"
 
-	"github.com/firecracker-microvm/firecracker-containerd/internal/debug"
 	"github.com/firecracker-microvm/firecracker-containerd/proto"
 	models "github.com/firecracker-microvm/firecracker-go-sdk/client/models"
 )
@@ -41,13 +40,14 @@ const (
 
 // Config represents runtime configuration parameters
 type Config struct {
-	FirecrackerBinaryPath string   `json:"firecracker_binary_path"`
-	KernelImagePath       string   `json:"kernel_image_path"`
-	KernelArgs            string   `json:"kernel_args"`
-	RootDrive             string   `json:"root_drive"`
-	CPUTemplate           string   `json:"cpu_template"`
-	LogLevels             []string `json:"log_levels"`
-	HtEnabled             bool     `json:"ht_enabled"`
+	FirecrackerBinaryPath string `json:"firecracker_binary_path"`
+	KernelImagePath       string `json:"kernel_image_path"`
+	KernelArgs            string `json:"kernel_args"`
+	RootDrive             string `json:"root_drive"`
+	CPUTemplate           string `json:"cpu_template"`
+	LogLevel              string `json:"log_level"`
+	HtEnabled             bool   `json:"ht_enabled"`
+	Debug                 bool   `json:"debug"`
 	// If a CreateVM call specifies no network interfaces and DefaultNetworkInterfaces is non-empty,
 	// the VM will default to using the network interfaces as specified here. This is especially
 	// useful when a CNI-based network interface is provided in DefaultNetworkInterfaces.
@@ -57,8 +57,6 @@ type Config struct {
 	// directory.
 	ShimBaseDir  string       `json:"shim_base_dir"`
 	JailerConfig JailerConfig `json:"jailer"`
-
-	DebugHelper *debug.Helper `json:"-"`
 }
 
 // JailerConfig houses a set of configurable values for jailing
@@ -94,11 +92,6 @@ func LoadConfig(path string) (*Config, error) {
 		},
 	}
 
-	cfg.DebugHelper, err = debug.New(cfg.LogLevels...)
-	if err != nil {
-		return nil, err
-	}
-
 	if err := json.Unmarshal(data, cfg); err != nil {
 		return nil, errors.Wrapf(err, "failed to unmarshal config from %q", path)
 	}
diff --git a/config/config.json.example b/config/config.json.example
index 33dae8f..fbee8e6 100644
--- a/config/config.json.example
+++ b/config/config.json.example
@@ -4,6 +4,6 @@
   "kernel_args": "console=ttyS0 noapic reboot=k panic=1 pci=off nomodules rw",
   "root_drive": "./vsock.img",
   "cpu_template": "T2",
-  "log_levels": ["debug"],
+  "log_level": "Debug",
   "ht_enabled": false
-}
+}
\ No newline at end of file
diff --git a/docs/logging.md b/docs/logging.md
deleted file mode 100644
index a3d5716..0000000
--- a/docs/logging.md
+++ /dev/null
@@ -1,65 +0,0 @@
-## Logging Congiguration
---
-
-firecracker-containerd allows for users to specify per application/library
-logging. We do this by setting the `log_levels` field in the
-firecracker-runtime.json file.
-
-```json
-{
-  "firecracker_binary_path": "/usr/local/bin/firecracker",
-  "kernel_image_path": "/var/lib/firecracker-containerd/runtime/default-vmlinux.bin",
-  "kernel_args": "ro console=ttyS0 noapic reboot=k panic=1 pci=off nomodules systemd.journald.forward_to_console systemd.unit=firecracker.target init=/sbin/overlay-init",
-  "root_drive": "/var/lib/firecracker-containerd/runtime/default-rootfs.img",
-  "cpu_count": 1,
-  "cpu_template": "T2",
-  "log_levels": ["debug"],
-  "jailer": {
-    "runc_binary_path": "/usr/local/bin/runc"
-  }
-}
-```
-
-| log levels                     | description                                                                     |
-| :---------------------------:  | :-----------------------------------------------------------------------------: |
-| error                          | This will set all log levels to error                                           |
-| warning                        | This will set all log levels to warning                                         |
-| info                           | This will set all log levels to info                                            |
-| debug                          | This will set all log levels to debug                                           |
-| firecracker:error              | Logs any error information in Firecracker's lifecycle                           |
-| firecracker:warning            | Logs any error and warning information in Firecracker's lifecycle               |
-| firecracker:info               | Logs any error, warning, info information in Firecracker's lifecycle            |
-| firecracker:debug              | Most verbose log level for firecracker                                          |
-| firecracker:output             | Logs Firecracker's stdout and stderr. Can be used with other firecracker levels |
-| firecracker-go-sdk:error       | Logs any errors information in firecracker-go-sdk                               |
-| firecracker-go-sdk:warning     | Logs any errors or warnings in firracker-go-sdk                                 |
-| firecracker-go-sdk:info        | Logs any errors, warnings, or infos in firecracker-go-sdk                       |
-| firecracker-go-sdk:debug       | Most verbose logging for firecracker-go-sdk                                     |
-| firecracker-containerd:error   | Logs any error information during the container/vm lifecycle                    |
-| firecracker-containerd:warning | Logs any error level logs along with any warn level logs                        |
-| firecracker-containerd:info    | Logs any error, warn, and info level logs                                       |
-| firecracker-containerd:debug   | Most verbose logging for firecracker-containerd                                 |
-
-The firecracker:XX are mutually exclusive with other firecracker-YY meaning only one of the log levels can be set at a time. 
-However, firecracker:output may be set with other firecracker:YY settings.
-The firecracker-containerd:XX are also mutually exclusive with other firecracker-containerd-YY levels
-info, error, warning, and debug are mutually exclusive and only one can be set at a time.
-
-```json
-{
-  "firecracker_binary_path": "/usr/local/bin/firecracker",
-  "kernel_image_path": "/var/lib/firecracker-containerd/runtime/default-vmlinux.bin",
-  "kernel_args": "ro console=ttyS0 noapic reboot=k panic=1 pci=off nomodules systemd.journald.forward_to_console systemd.unit=firecracker.target init=/sbin/overlay-init",
-  "root_drive": "/var/lib/firecracker-containerd/runtime/default-rootfs.img",
-  "cpu_count": 1,
-  "cpu_template": "T2",
-  "log:levels": ["info","firecracker:debug","firecracker-containerd:error"],
-  "jailer": {
-    "runc_binary_path": "/usr/local/bin/runc"
-  }
-}
-```
-
-The example above shows that setting the log levels to info, but specifies that
-firecracker to be on a debug level and firecracker-containerd to be logging at
-the error level
diff --git a/examples/etc/containerd/firecracker-runtime.json b/examples/etc/containerd/firecracker-runtime.json
index d826c4d..b3ca085 100644
--- a/examples/etc/containerd/firecracker-runtime.json
+++ b/examples/etc/containerd/firecracker-runtime.json
@@ -5,7 +5,8 @@
   "root_drive": "/var/lib/firecracker-containerd/runtime/default-rootfs.img",
   "cpu_count": 1,
   "cpu_template": "T2",
-  "log_levels": ["debug"],
+  "log_level": "Debug",
+  "debug": true,
   "jailer": {
     "runc_binary_path": "/usr/local/bin/runc"
   }
diff --git a/internal/debug/debug.go b/internal/debug/debug.go
deleted file mode 100644
index 2f22871..0000000
--- a/internal/debug/debug.go
+++ /dev/null
@@ -1,326 +0,0 @@
-// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License"). You may
-// not use this file except in compliance with the License. A copy of the
-// License is located at
-//
-//	http://aws.amazon.com/apache2.0/
-//
-// or in the "license" file accompanying this file. This file 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 debug
-
-import (
-	"fmt"
-	"strings"
-
-	"github.com/sirupsen/logrus"
-)
-
-const (
-	// LogLevelDebug will enable debugging for all applciations and SDKs. This
-	// uses log levels of firecracker:debug, firecracker-go-sdk:debug,
-	// firecracker:output, and firecracker-containerd:debug
-	LogLevelDebug = "debug"
-	// LogLevelError will enable error logging for all applciations and SDKs.
-	// This uses log levels of firecracker:error, firecracker-go-sdk:error,
-	// and firecracker-containerd:error
-	LogLevelError = "error"
-	// LogLevelInfo will enable info logging for all applciations and SDKs.
-	// This uses log levels of firecracker:info, firecracker-go-sdk:info,
-	// and firecracker-containerd:info
-	LogLevelInfo = "info"
-	// LogLevelWarning will enable warning logging for all applciations and SDKs.
-	// This uses log levels of firecracker:warning, firecracker-go-sdk:warning,
-	// firecracker:output, and firecracker-containerd:warning
-	LogLevelWarning = "warning"
-	// LogLevelFirecrackerDebug enables debug level logging on Firecracker
-	// MicroVMs
-	LogLevelFirecrackerDebug = "firecracker:debug"
-	// LogLevelFirecrackerError enables error level logging on Firecracker
-	// MicroVMs
-	LogLevelFirecrackerError = "firecracker:error"
-	// LogLevelFirecrackerInfo enables info level logging on Firecracker MicroVMs
-	LogLevelFirecrackerInfo = "firecracker:info"
-	// LogLevelFirecrackerWarning enables warning level logging on Firecracker
-	// MicroVMs
-	LogLevelFirecrackerWarning = "firecracker:warning"
-	// LogLevelFirecrackerOutput will redirect stdout and stderr of Firecracker
-	// to logging. By default, stdout and stderr is ignored
-	LogLevelFirecrackerOutput = "firecracker:output"
-	// LogLevelFirecrackerSDKDebug enables debug level logging on
-	// firecracker-go-sdk
-	LogLevelFirecrackerSDKDebug = "firecracker-go-sdk:debug"
-	// LogLevelFirecrackerSDKError enables error level logging on
-	// firecracker-go-sdk
-	LogLevelFirecrackerSDKError = "firecracker-go-sdk:error"
-	// LogLevelFirecrackerSDKInfo enables info level logging on
-	// firecracker-go-sdk
-	LogLevelFirecrackerSDKInfo = "firecracker-go-sdk:info"
-	// LogLevelFirecrackerSDKWarning enables warning level logging on
-	// firecracker-go-sdk
-	LogLevelFirecrackerSDKWarning = "firecracker-go-sdk:warning"
-	// LogLevelFirecrackerContainerdDebug enables debug level logging on
-	// firecracker-containerd
-	LogLevelFirecrackerContainerdDebug = "firecracker-containerd:debug"
-	// LogLevelFirecrackerContainerdError enables error level logging on
-	// firecracker-containerd
-	LogLevelFirecrackerContainerdError = "firecracker-containerd:error"
-	// LogLevelFirecrackerContainerdInfo enables info level logging on
-	// firecracker-containerd
-	LogLevelFirecrackerContainerdInfo = "firecracker-containerd:info"
-	// LogLevelFirecrackerContainerdWarning enables warning level logging on
-	// firecracker-containerd
-	LogLevelFirecrackerContainerdWarning = "firecracker-containerd:warning"
-)
-
-// ErrLogLevelAlreadySet will return if a log level has been previously set.
-var ErrLogLevelAlreadySet = fmt.Errorf("only one value for top level log level can be set")
-
-// ErrFCLogLevelAlreadySet will return if a log level has been previously set.
-var ErrFCLogLevelAlreadySet = fmt.Errorf("only one value of firecracker log level can be set")
-
-// ErrFCSDKLogLevelAlreadySet will return if a log level has been previously set.
-var ErrFCSDKLogLevelAlreadySet = fmt.Errorf("only one value of firecracker-go-sdk log level can be set")
-
-// ErrFCContainerdLogLevelAlreadySet will return if a log level has been previously set.
-var ErrFCContainerdLogLevelAlreadySet = fmt.Errorf("only one value of firecracker-containerd log level can be set")
-
-// Helper is used to abstract away the complications of multilevel log levels.
-type Helper struct {
-	logLevels []string
-	ShimDebug bool
-
-	logDebug        bool
-	logError        bool
-	logInfo         bool
-	logWarning      bool
-	logFCSDK        logrus.Level
-	logFCOutput     bool
-	logFC           string
-	logFCContainerd logrus.Level
-
-	fcSDKLogLevelSet        bool
-	fcContainerdLogLevelSet bool
-}
-
-// New will return a new Helper in the event an error does not occur. This will
-// parse the logLevel provided to figure out what logging is enabled. New will
-// also validate that the log level is a valid value along with any mutually
-// exclusive values.
-func New(logLevels ...string) (*Helper, error) {
-	h := &Helper{
-		logLevels: logLevels,
-	}
-
-	if err := h.setLogLevels(logLevels); err != nil {
-		return nil, err
-	}
-
-	return h, nil
-}
-
-// GetFirecrackerLogLevel will return the current log level for Firecracker.
-func (h *Helper) GetFirecrackerLogLevel() string {
-	if h.logFC != "" {
-		return h.logFC
-	}
-
-	if h.logDebug {
-		return "Debug"
-	}
-
-	if h.logError {
-		return "Error"
-	}
-
-	if h.logInfo {
-		return "Info"
-	}
-
-	if h.logWarning {
-		return "Warning"
-	}
-
-	return h.logFC
-}
-
-// LogFirecrackerOutput will return whether our not we want to redirect stdout
-// and stderr to our logging
-func (h *Helper) LogFirecrackerOutput() bool {
-	return h.logDebug || h.logFCOutput
-}
-
-// GetFirecrackerSDKLogLevel returns what log level to log the
-// firecracker-go-sdk at. This also return whether or not the value was set
-func (h *Helper) GetFirecrackerSDKLogLevel() (logrus.Level, bool) {
-	if h.fcSDKLogLevelSet {
-		return h.logFCSDK, true
-	}
-
-	if h.logDebug {
-		return logrus.DebugLevel, true
-	}
-
-	if h.logError {
-		return logrus.ErrorLevel, true
-	}
-
-	if h.logInfo {
-		return logrus.InfoLevel, true
-	}
-
-	if h.logWarning {
-		return logrus.WarnLevel, true
-	}
-
-	return h.logFCSDK, false
-}
-
-// GetFirecrackerContainerdLogLevel return the log level for
-// firecracker-containerd
-func (h *Helper) GetFirecrackerContainerdLogLevel() (logrus.Level, bool) {
-	if h.fcContainerdLogLevelSet {
-		return h.logFCContainerd, h.fcContainerdLogLevelSet
-	}
-
-	if h.logDebug || h.ShimDebug {
-		return logrus.DebugLevel, true
-	}
-
-	if h.logError {
-		return logrus.ErrorLevel, true
-	}
-
-	if h.logInfo {
-		return logrus.InfoLevel, true
-	}
-
-	if h.logWarning {
-		return logrus.WarnLevel, true
-	}
-
-	return logrus.PanicLevel, false
-}
-
-func (h *Helper) setFirecrackerLogLevel(level string) error {
-	if h.logFC != "" {
-		return ErrFCLogLevelAlreadySet
-	}
-
-	h.logFC = level
-	return nil
-}
-
-func (h *Helper) setFirecrackerContainerdLogLevel(level logrus.Level) error {
-	if h.fcContainerdLogLevelSet {
-		return ErrFCContainerdLogLevelAlreadySet
-	}
-
-	h.fcContainerdLogLevelSet = true
-	h.logFCContainerd = level
-	return nil
-}
-
-func (h *Helper) setFirecrackerSDKLogLevel(level logrus.Level) error {
-	if h.fcSDKLogLevelSet {
-		return ErrFCSDKLogLevelAlreadySet
-	}
-	h.fcSDKLogLevelSet = true
-	h.logFCSDK = level
-	return nil
-}
-
-func (h *Helper) isTopLogLevelSet() bool {
-	return h.logDebug || h.logError || h.logInfo || h.logWarning
-}
-
-func (h *Helper) setLogLevels(logLevels []string) error {
-	if len(logLevels) == 0 {
-		return nil
-	}
-
-	for _, level := range logLevels {
-		cleanedLevel := strings.TrimSpace(level)
-
-		switch cleanedLevel {
-		case LogLevelDebug:
-			if h.isTopLogLevelSet() {
-				return ErrLogLevelAlreadySet
-			}
-			h.logDebug = true
-		case LogLevelError:
-			if h.isTopLogLevelSet() {
-				return ErrLogLevelAlreadySet
-			}
-			h.logError = true
-		case LogLevelInfo:
-			if h.isTopLogLevelSet() {
-				return ErrLogLevelAlreadySet
-			}
-			h.logInfo = true
-		case LogLevelWarning:
-			if h.isTopLogLevelSet() {
-				return ErrLogLevelAlreadySet
-			}
-			h.logWarning = true
-		case LogLevelFirecrackerDebug:
-			if err := h.setFirecrackerLogLevel("Debug"); err != nil {
-				return err
-			}
-		case LogLevelFirecrackerError:
-			if err := h.setFirecrackerLogLevel("Error"); err != nil {
-				return err
-			}
-		case LogLevelFirecrackerInfo:
-			if err := h.setFirecrackerLogLevel("Info"); err != nil {
-				return err
-			}
-		case LogLevelFirecrackerWarning:
-			if err := h.setFirecrackerLogLevel("Warning"); err != nil {
-				return err
-			}
-		case LogLevelFirecrackerOutput:
-			h.logFCOutput = true
-		case LogLevelFirecrackerSDKDebug:
-			if err := h.setFirecrackerSDKLogLevel(logrus.DebugLevel); err != nil {
-				return err
-			}
-		case LogLevelFirecrackerSDKError:
-			if err := h.setFirecrackerSDKLogLevel(logrus.ErrorLevel); err != nil {
-				return err
-			}
-		case LogLevelFirecrackerSDKInfo:
-			if err := h.setFirecrackerSDKLogLevel(logrus.InfoLevel); err != nil {
-				return err
-			}
-		case LogLevelFirecrackerSDKWarning:
-			if err := h.setFirecrackerSDKLogLevel(logrus.WarnLevel); err != nil {
-				return err
-			}
-		case LogLevelFirecrackerContainerdDebug:
-			if err := h.setFirecrackerContainerdLogLevel(logrus.DebugLevel); err != nil {
-				return err
-			}
-		case LogLevelFirecrackerContainerdError:
-			if err := h.setFirecrackerContainerdLogLevel(logrus.ErrorLevel); err != nil {
-				return err
-			}
-		case LogLevelFirecrackerContainerdInfo:
-			if err := h.setFirecrackerContainerdLogLevel(logrus.InfoLevel); err != nil {
-				return err
-			}
-		case LogLevelFirecrackerContainerdWarning:
-			if err := h.setFirecrackerContainerdLogLevel(logrus.WarnLevel); err != nil {
-				return err
-			}
-		default:
-			return NewInvalidLogLevelError(cleanedLevel)
-		}
-	}
-
-	return nil
-}
diff --git a/internal/debug/error.go b/internal/debug/error.go
deleted file mode 100644
index ee3bc67..0000000
--- a/internal/debug/error.go
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License"). You may
-// not use this file except in compliance with the License. A copy of the
-// License is located at
-//
-//	http://aws.amazon.com/apache2.0/
-//
-// or in the "license" file accompanying this file. This file 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 debug
-
-import (
-	"fmt"
-)
-
-// InvalidLogLevelError is an error that will be returned in the event that an
-// invalid log level was provided
-type InvalidLogLevelError struct {
-	logLevel string
-}
-
-// NewInvalidLogLevelError will constract an InvalidLogLevelError
-func NewInvalidLogLevelError(logLevel string) error {
-	return &InvalidLogLevelError{
-		logLevel: logLevel,
-	}
-}
-
-func (e *InvalidLogLevelError) Error() string {
-	return fmt.Sprintf("log level %q is an invalid log level", e.logLevel)
-}
diff --git a/runtime/Makefile b/runtime/Makefile
index 132f62e..a664a90 100644
--- a/runtime/Makefile
+++ b/runtime/Makefile
@@ -92,7 +92,7 @@ benchmark-%: logs
 		--workdir="/src/runtime" \
 		--init \
 		$(FIRECRACKER_CONTAINERD_TEST_IMAGE):$(DOCKER_IMAGE_TAG) \
-		"go test $(EXTRAGOARGS) -run IGNORE -bench '$(subst benchmark-,,$@)'"
+		"go test $(EXTRAGOARGS) -run '$(subst benchmark-,,$@)'"
 
 logs:
 	mkdir logs
diff --git a/runtime/noop_jailer.go b/runtime/noop_jailer.go
index ca78d8b..110eb2f 100644
--- a/runtime/noop_jailer.go
+++ b/runtime/noop_jailer.go
@@ -59,7 +59,7 @@ func (j *noopJailer) BuildJailedMachine(cfg *config.Config, machineConfig *firec
 		WithSocketPath(relSocketPath).
 		Build(j.ctx)
 
-	if cfg.DebugHelper.LogFirecrackerOutput() {
+	if cfg.Debug {
 		cmd.Stdout = j.logger.WithField("vmm_stream", "stdout").WriterLevel(logrus.DebugLevel)
 		cmd.Stderr = j.logger.WithField("vmm_stream", "stderr").WriterLevel(logrus.DebugLevel)
 	}
diff --git a/runtime/runc_jailer.go b/runtime/runc_jailer.go
index 6c1f1e9..46c7cae 100644
--- a/runtime/runc_jailer.go
+++ b/runtime/runc_jailer.go
@@ -134,7 +134,7 @@ func (j *runcJailer) BuildJailedMachine(cfg *config.Config, machineConfig *firec
 	}
 
 	opts := []firecracker.Opt{
-		firecracker.WithProcessRunner(j.jailerCommand(vmID, cfg.DebugHelper.LogFirecrackerOutput())),
+		firecracker.WithProcessRunner(j.jailerCommand(vmID, cfg.Debug)),
 		firecracker.WithClient(client),
 		func(m *firecracker.Machine) {
 			m.Handlers.FcInit = m.Handlers.FcInit.Prepend(handler)
diff --git a/runtime/service.go b/runtime/service.go
index 7cab482..c2761bc 100644
--- a/runtime/service.go
+++ b/runtime/service.go
@@ -162,12 +162,14 @@ func NewService(shimCtx context.Context, id string, remotePublisher shim.Publish
 		return nil, err
 	}
 
-	opts, err := shimOpts(shimCtx)
-	if err != nil {
-		return nil, err
-	}
+	if !cfg.Debug {
+		opts, err := shimOpts(shimCtx)
+		if err != nil {
+			return nil, err
+		}
 
-	cfg.DebugHelper.ShimDebug = opts.Debug
+		cfg.Debug = opts.Debug
+	}
 
 	namespace, ok := namespaces.Namespace(shimCtx)
 	if !ok {
@@ -186,10 +188,9 @@ func NewService(shimCtx context.Context, id string, remotePublisher shim.Publish
 		}
 	}
 
-	logrusLevel, ok := cfg.DebugHelper.GetFirecrackerContainerdLogLevel()
-	if ok {
-		logrus.SetLevel(logrusLevel)
-		logger.Logger.SetLevel(logrusLevel)
+	if cfg.Debug {
+		logrus.SetLevel(logrus.DebugLevel)
+		logger.Logger.SetLevel(logrus.DebugLevel)
 	}
 
 	s := &service{
@@ -528,13 +529,10 @@ func (s *service) createVM(requestCtx context.Context, request *proto.CreateVMRe
 		return errors.Wrapf(err, "failed to build VM configuration")
 	}
 
-	opts := []firecracker.Opt{}
-
-	if v, ok := s.config.DebugHelper.GetFirecrackerSDKLogLevel(); ok {
-		logger := log.G(s.shimCtx)
-		logger.Logger.SetLevel(v)
-		opts = append(opts, firecracker.WithLogger(logger))
+	opts := []firecracker.Opt{
+		firecracker.WithLogger(s.logger),
 	}
+
 	relVSockPath, err := s.jailer.JailPath().FirecrackerVSockRelPath()
 	if err != nil {
 		return errors.Wrapf(err, "failed to get relative path to firecracker vsock")
@@ -736,7 +734,8 @@ func (s *service) buildVMConfiguration(req *proto.CreateVMRequest) (*firecracker
 		LogFifo:     s.shimDir.FirecrackerLogFifoPath(),
 		MetricsFifo: s.shimDir.FirecrackerMetricsFifoPath(),
 		MachineCfg:  machineConfigurationFromProto(s.config, req.MachineCfg),
-		LogLevel:    s.config.DebugHelper.GetFirecrackerLogLevel(),
+		LogLevel:    s.config.LogLevel,
+		Debug:       s.config.Debug,
 		VMID:        s.vmID,
 	}
 


Test patch:
diff --git a/internal/debug/debug_test.go b/internal/debug/debug_test.go
deleted file mode 100644
index 0b26928..0000000
--- a/internal/debug/debug_test.go
+++ /dev/null
@@ -1,228 +0,0 @@
-// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License"). You may
-// not use this file except in compliance with the License. A copy of the
-// License is located at
-//
-//	http://aws.amazon.com/apache2.0/
-//
-// or in the "license" file accompanying this file. This file 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 debug
-
-import (
-	"testing"
-
-	"github.com/sirupsen/logrus"
-	"github.com/stretchr/testify/assert"
-	"github.com/stretchr/testify/require"
-)
-
-func TestParseLogLevel(t *testing.T) {
-	cases := []struct {
-		Name           string
-		LogLevels      []string
-		ExpectedError  error
-		ExpectedHelper *Helper
-	}{
-		{
-			Name:           "empty",
-			ExpectedHelper: &Helper{},
-		},
-		{
-			Name:          "invalid",
-			LogLevels:     []string{"invalid"},
-			ExpectedError: NewInvalidLogLevelError("invalid"),
-		},
-		{
-			Name:          "multiple with invalid",
-			LogLevels:     []string{LogLevelDebug, LogLevelFirecrackerDebug, "invalid"},
-			ExpectedError: NewInvalidLogLevelError("invalid"),
-		},
-		{
-			Name:      "debug",
-			LogLevels: []string{LogLevelDebug},
-			ExpectedHelper: &Helper{
-				logDebug: true,
-			},
-		},
-		{
-			Name:      "error",
-			LogLevels: []string{LogLevelError},
-			ExpectedHelper: &Helper{
-				logError: true,
-			},
-		},
-		{
-			Name:      "info",
-			LogLevels: []string{LogLevelInfo},
-			ExpectedHelper: &Helper{
-				logInfo: true,
-			},
-		},
-		{
-			Name:      "warning",
-			LogLevels: []string{LogLevelWarning},
-			ExpectedHelper: &Helper{
-				logWarning: true,
-			},
-		},
-		{
-			Name:          "multiple top log levels",
-			LogLevels:     []string{LogLevelDebug, LogLevelError, LogLevelInfo, LogLevelWarning},
-			ExpectedError: ErrLogLevelAlreadySet,
-		},
-		{
-			Name:      "firecracker debug",
-			LogLevels: []string{LogLevelFirecrackerDebug},
-			ExpectedHelper: &Helper{
-				logFC: "Debug",
-			},
-		},
-		{
-			Name:      "firecracker error",
-			LogLevels: []string{LogLevelFirecrackerError},
-			ExpectedHelper: &Helper{
-				logFC: "Error",
-			},
-		},
-		{
-			Name:      "firecracker info",
-			LogLevels: []string{LogLevelFirecrackerInfo},
-			ExpectedHelper: &Helper{
-				logFC: "Info",
-			},
-		},
-		{
-			Name:      "firecracker warning",
-			LogLevels: []string{LogLevelFirecrackerWarning},
-			ExpectedHelper: &Helper{
-				logFC: "Warning",
-			},
-		},
-		{
-			Name:      "firecracker output",
-			LogLevels: []string{LogLevelFirecrackerOutput},
-			ExpectedHelper: &Helper{
-				logFCOutput: true,
-			},
-		},
-		{
-			Name:          "multiple firecracker log levels",
-			LogLevels:     []string{LogLevelFirecrackerWarning, LogLevelFirecrackerDebug, LogLevelFirecrackerError},
-			ExpectedError: ErrFCLogLevelAlreadySet,
-		},
-		{
-			Name:      "firecracker-go-sdk debug level",
-			LogLevels: []string{LogLevelFirecrackerSDKDebug},
-			ExpectedHelper: &Helper{
-				fcSDKLogLevelSet: true,
-				logFCSDK:         logrus.DebugLevel,
-			},
-		},
-		{
-			Name:      "firecracker-go-sdk error level",
-			LogLevels: []string{LogLevelFirecrackerSDKError},
-			ExpectedHelper: &Helper{
-				fcSDKLogLevelSet: true,
-				logFCSDK:         logrus.ErrorLevel,
-			},
-		},
-		{
-			Name:      "firecracker-go-sdk info level",
-			LogLevels: []string{LogLevelFirecrackerSDKInfo},
-			ExpectedHelper: &Helper{
-				fcSDKLogLevelSet: true,
-				logFCSDK:         logrus.InfoLevel,
-			},
-		},
-		{
-			Name:      "firecracker-go-sdk warning level",
-			LogLevels: []string{LogLevelFirecrackerSDKWarning},
-			ExpectedHelper: &Helper{
-				fcSDKLogLevelSet: true,
-				logFCSDK:         logrus.WarnLevel,
-			},
-		},
-		{
-			Name:      "firecracker-go-sdk multiple levels",
-			LogLevels: []string{LogLevelDebug, LogLevelFirecrackerSDKWarning},
-			ExpectedHelper: &Helper{
-				logFC:                   "Debug",
-				fcSDKLogLevelSet:        true,
-				logFCSDK:                logrus.WarnLevel,
-				fcContainerdLogLevelSet: true,
-				logFCContainerd:         logrus.DebugLevel,
-			},
-		},
-		{
-			Name:          "firecracker-go-sdk multiple levels",
-			LogLevels:     []string{LogLevelDebug, LogLevelFirecrackerSDKWarning, LogLevelFirecrackerSDKDebug},
-			ExpectedError: ErrFCSDKLogLevelAlreadySet,
-		},
-		{
-			Name:      "firecracker containerd debug",
-			LogLevels: []string{LogLevelFirecrackerContainerdDebug},
-			ExpectedHelper: &Helper{
-				fcContainerdLogLevelSet: true,
-				logFCContainerd:         logrus.DebugLevel,
-			},
-		},
-		{
-			Name:      "firecracker containerd error",
-			LogLevels: []string{LogLevelFirecrackerContainerdError},
-			ExpectedHelper: &Helper{
-				fcContainerdLogLevelSet: true,
-				logFCContainerd:         logrus.ErrorLevel,
-			},
-		},
-		{
-			Name:      "firecracker containerd info",
-			LogLevels: []string{LogLevelFirecrackerContainerdInfo},
-			ExpectedHelper: &Helper{
-				fcContainerdLogLevelSet: true,
-				logFCContainerd:         logrus.InfoLevel,
-			},
-		},
-		{
-			Name:      "firecracker containerd warning",
-			LogLevels: []string{LogLevelFirecrackerContainerdWarning},
-			ExpectedHelper: &Helper{
-				fcContainerdLogLevelSet: true,
-				logFCContainerd:         logrus.WarnLevel,
-			},
-		},
-		{
-			Name:          "multiple firecracker containerd log levels",
-			LogLevels:     []string{LogLevelFirecrackerContainerdWarning, LogLevelFirecrackerContainerdDebug, LogLevelFirecrackerContainerdError},
-			ExpectedError: ErrFCContainerdLogLevelAlreadySet,
-		},
-	}
-
-	for _, _c := range cases {
-		c := _c
-
-		t.Run(c.Name, func(t *testing.T) {
-			h, err := New(c.LogLevels...)
-			require.Equalf(t, c.ExpectedError, err, "expected errors to be equal")
-			if c.ExpectedError != nil {
-				return
-			}
-
-			require.NotNilf(t, h, "expected Helper to be non-nil")
-
-			assert.Equal(t, c.ExpectedHelper.GetFirecrackerLogLevel(), h.GetFirecrackerLogLevel())
-			expectedLogLevel, expectedOk := c.ExpectedHelper.GetFirecrackerSDKLogLevel()
-			logLevel, ok := h.GetFirecrackerSDKLogLevel()
-			assert.Equal(t, expectedOk, ok)
-			assert.Equal(t, expectedLogLevel, logLevel)
-			expectedLogLevel, expectedOk = c.ExpectedHelper.GetFirecrackerContainerdLogLevel()
-			logLevel, ok = h.GetFirecrackerContainerdLogLevel()
-			assert.Equal(t, expectedOk, ok)
-			assert.Equal(t, expectedLogLevel, logLevel)
-		})
-	}
-}
diff --git a/runtime/benchmark_test.go b/runtime/benchmark_test.go
index d94e5b5..0fe0056 100644
--- a/runtime/benchmark_test.go
+++ b/runtime/benchmark_test.go
@@ -27,42 +27,44 @@ import (
 	"github.com/stretchr/testify/require"
 )
 
+const benchmarkCount = 10
+
 func createAndStopVM(
 	ctx context.Context,
 	fcClient fccontrol.FirecrackerService,
 	request proto.CreateVMRequest,
-) error {
+) (time.Duration, error) {
 	uuid, err := uuid.NewV4()
 	if err != nil {
-		return err
+		return 0, err
 	}
 
 	request.VMID = uuid.String()
 
+	t0 := time.Now()
 	_, err = fcClient.CreateVM(ctx, &request)
 	if err != nil {
-		return err
+		return 0, err
 	}
+	elapsed := time.Since(t0)
 
 	_, err = fcClient.StopVM(ctx, &proto.StopVMRequest{VMID: request.VMID})
 	if err != nil {
-		return err
+		return 0, err
 	}
 
-	return nil
+	return elapsed, nil
 }
 
-func benchmarkCreateAndStopVM(b *testing.B, vcpuCount uint32, kernelArgs string, parallel int) {
-	require := require.New(b)
-
+func benchmarkCreateAndStopVM(t *testing.T, vcpuCount uint32, kernelArgs string) {
 	client, err := containerd.New(containerdSockPath, containerd.WithDefaultRuntime(firecrackerRuntime))
-	require.NoError(err, "unable to create client to containerd service at %s, is containerd running?", containerdSockPath)
+	require.NoError(t, err, "unable to create client to containerd service at %s, is containerd running?", containerdSockPath)
 	defer client.Close()
 
 	ctx := namespaces.WithNamespace(context.Background(), "default")
 
 	pluginClient, err := ttrpcutil.NewClient(containerdSockPath + ".ttrpc")
-	require.NoError(err, "failed to create ttrpc client")
+	require.NoError(t, err, "failed to create ttrpc client")
 
 	fcClient := fccontrol.NewFirecrackerClient(pluginClient.Client())
 	request := proto.CreateVMRequest{
@@ -72,52 +74,42 @@ func benchmarkCreateAndStopVM(b *testing.B, vcpuCount uint32, kernelArgs string,
 		},
 	}
 
-	ch := make(chan error, parallel)
-	for i := 0; i < parallel; i++ {
-		go func() {
-			var err error
-			defer func() {
-				ch <- err
-			}()
-
-			for i := 0; i < b.N; i++ {
-				ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
-				defer cancel()
-
-				err = createAndStopVM(ctx, fcClient, request)
-				if err != nil {
-					return
-				}
-			}
-		}()
+	var samples []time.Duration
+	for i := 0; i < benchmarkCount; i++ {
+		ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
+		defer cancel()
+
+		elapsed, err := createAndStopVM(ctx, fcClient, request)
+		if err != nil {
+			return
+		}
+		samples = append(samples, elapsed)
 	}
 
-	// Make sure all goroutines are finished successfully.
-	for i := 0; i < parallel; i++ {
-		require.NoError(<-ch)
+	var average time.Duration
+	for _, x := range samples {
+		average += x
 	}
-}
+	average = time.Duration(int64(average) / int64(len(samples)))
 
-func BenchmarkCreateAndStopVM_Vcpu1_Isolated(b *testing.B) {
-	prepareIntegTest(b)
-	benchmarkCreateAndStopVM(b, 1, defaultRuntimeConfig.KernelArgs, 1)
-}
-func BenchmarkCreateAndStopVM_Vcpu5_Isolated(b *testing.B) {
-	prepareIntegTest(b)
-	benchmarkCreateAndStopVM(b, 5, defaultRuntimeConfig.KernelArgs, 1)
+	t.Logf("%s: avg:%v samples:%v", t.Name(), average, samples)
 }
 
-func BenchmarkCreateAndStopVM_Quiet_Isolated(b *testing.B) {
-	prepareIntegTest(b)
-	benchmarkCreateAndStopVM(
-		b,
-		1,
-		// Same as https://github.com/firecracker-microvm/firecracker-demo/blob/c22499567b63b4edd85e19ca9b0e9fa398b3300b/start-firecracker.sh#L9
-		"ro noapic reboot=k panic=1 pci=off nomodules systemd.log_color=false systemd.unit=firecracker.target init=/sbin/overlay-init tsc=reliable quiet 8250.nr_uarts=0 ipv6.disable=1",
-		1,
-	)
-}
-func BenchmarkCreateAndStopVM_Parallel10_Isolated(b *testing.B) {
-	prepareIntegTest(b)
-	benchmarkCreateAndStopVM(b, 1, defaultRuntimeConfig.KernelArgs, 10)
+func TestPerf_CreateVM(t *testing.T) {
+	prepareIntegTest(t)
+
+	t.Run("vcpu=1", func(subtest *testing.T) {
+		benchmarkCreateAndStopVM(subtest, 1, defaultRuntimeConfig.KernelArgs)
+	})
+	t.Run("vcpu=5", func(subtest *testing.T) {
+		benchmarkCreateAndStopVM(subtest, 1, defaultRuntimeConfig.KernelArgs)
+	})
+	t.Run("firecracker-demo", func(subtest *testing.T) {
+		benchmarkCreateAndStopVM(
+			subtest,
+			1,
+			// Same as https://github.com/firecracker-microvm/firecracker-demo/blob/c22499567b63b4edd85e19ca9b0e9fa398b3300b/start-firecracker.sh#L9
+			"ro noapic reboot=k panic=1 pci=off nomodules systemd.log_color=false systemd.unit=firecracker.target init=/sbin/overlay-init tsc=reliable quiet 8250.nr_uarts=0 ipv6.disable=1",
+		)
+	})
 }
diff --git a/runtime/integ_test.go b/runtime/integ_test.go
index cd39304..d1fccbb 100644
--- a/runtime/integ_test.go
+++ b/runtime/integ_test.go
@@ -38,7 +38,8 @@ var defaultRuntimeConfig = config.Config{
 	KernelArgs:            "ro console=ttyS0 noapic reboot=k panic=1 pci=off nomodules systemd.journald.forward_to_console systemd.log_color=false systemd.unit=firecracker.target init=/sbin/overlay-init",
 	RootDrive:             "/var/lib/firecracker-containerd/runtime/default-rootfs.img",
 	CPUTemplate:           "T2",
-	LogLevels:             []string{"debug"},
+	LogLevel:              "Debug",
+	Debug:                 true,
 	ShimBaseDir:           shimBaseDir(),
 	JailerConfig: config.JailerConfig{
 		RuncBinaryPath: "/usr/local/bin/runc",
diff --git a/runtime/service_test.go b/runtime/service_test.go
index 7cc842a..26f1ff0 100644
--- a/runtime/service_test.go
+++ b/runtime/service_test.go
@@ -28,7 +28,6 @@ import (
 	"github.com/stretchr/testify/require"
 
 	"github.com/firecracker-microvm/firecracker-containerd/config"
-	"github.com/firecracker-microvm/firecracker-containerd/internal/debug"
 	"github.com/firecracker-microvm/firecracker-containerd/internal/vm"
 	"github.com/firecracker-microvm/firecracker-containerd/proto"
 )
@@ -39,9 +38,6 @@ const (
 )
 
 func TestBuildVMConfiguration(t *testing.T) {
-	debugHelper, err := debug.New()
-	require.NoError(t, err, "failed to create debug helper")
-
 	namespace := "TestBuildVMConfiguration"
 	testcases := []struct {
 		name                   string
@@ -58,7 +54,6 @@ func TestBuildVMConfiguration(t *testing.T) {
 				KernelImagePath: "KERNEL IMAGE",
 				RootDrive:       "ROOT DRIVE",
 				CPUTemplate:     "C3",
-				DebugHelper:     debugHelper,
 			},
 			expectedCfg: &firecracker.Config{
 				KernelArgs:      "KERNEL ARGS",
@@ -94,9 +89,7 @@ func TestBuildVMConfiguration(t *testing.T) {
 					VcpuCount:   2,
 				},
 			},
-			config: &config.Config{
-				DebugHelper: debugHelper,
-			},
+			config: &config.Config{},
 			expectedCfg: &firecracker.Config{
 				KernelArgs:      "REQUEST KERNEL ARGS",
 				KernelImagePath: "REQUEST KERNEL IMAGE",
@@ -135,7 +128,6 @@ func TestBuildVMConfiguration(t *testing.T) {
 				KernelArgs:      "KERNEL ARGS",
 				KernelImagePath: "KERNEL IMAGE",
 				CPUTemplate:     "C3",
-				DebugHelper:     debugHelper,
 			},
 			expectedCfg: &firecracker.Config{
 				KernelArgs:      "REQUEST KERNEL ARGS",
@@ -171,7 +163,6 @@ func TestBuildVMConfiguration(t *testing.T) {
 				KernelArgs:      "KERNEL ARGS",
 				KernelImagePath: "KERNEL IMAGE",
 				CPUTemplate:     "C3",
-				DebugHelper:     debugHelper,
 			},
 			expectedCfg: &firecracker.Config{
 				KernelArgs:      "REQUEST KERNEL ARGS",
@@ -201,7 +192,6 @@ func TestBuildVMConfiguration(t *testing.T) {
 				KernelImagePath: "KERNEL IMAGE",
 				RootDrive:       "ROOT DRIVE",
 				CPUTemplate:     "C3",
-				DebugHelper:     debugHelper,
 			},
 			expectedCfg: &firecracker.Config{
 				KernelArgs:      "KERNEL ARGS",
@@ -274,31 +264,42 @@ func TestBuildVMConfiguration(t *testing.T) {
 }
 
 func TestDebugConfig(t *testing.T) {
-	emptyDebugHelper, err := debug.New()
-	require.NoError(t, err, "failed to create empty debug helper")
-	fcDebugHelper, err := debug.New(debug.LogLevelFirecrackerDebug)
-	require.NoError(t, err, "failed to create firecracker debug helper")
-
 	cases := []struct {
 		name    string
 		service *service
 	}{
 		{
 			name: "empty",
+			service: &service{
+				logger: logrus.NewEntry(logrus.New()),
+				config: &config.Config{},
+			},
+		},
+		{
+			name: "LogLevel set",
 			service: &service{
 				logger: logrus.NewEntry(logrus.New()),
 				config: &config.Config{
-					DebugHelper: emptyDebugHelper,
+					LogLevel: "foo",
 				},
 			},
 		},
 		{
-			name: "LogLevel set",
+			name: "Debug set",
+			service: &service{
+				logger: logrus.NewEntry(logrus.New()),
+				config: &config.Config{
+					Debug: true,
+				},
+			},
+		},
+		{
+			name: "Both set",
 			service: &service{
 				logger: logrus.NewEntry(logrus.New()),
 				config: &config.Config{
-					LogLevels:   []string{debug.LogLevelFirecrackerDebug},
-					DebugHelper: fcDebugHelper,
+					LogLevel: "foo",
+					Debug:    true,
 				},
 			},
 		},
@@ -325,6 +326,7 @@ func TestDebugConfig(t *testing.T) {
 
 		cfg, err := c.service.buildVMConfiguration(&req)
 		assert.NoError(t, err, "failed to build firecracker configuration")
-		assert.Equal(t, c.service.config.DebugHelper.GetFirecrackerLogLevel(), cfg.LogLevel)
+		assert.Equal(t, c.service.config.LogLevel, cfg.LogLevel)
+		assert.Equal(t, c.service.config.Debug, cfg.Debug)
 	}
 }