autotoc_md2068
doc_id: "LOG-MIGR-004" doc_title: "Logger System Migration Guide" doc_version: "1.0.0" doc_date: "2026-04-04" doc_status: "Released" project: "logger_system"
category: "MIGR"
Language: English | 한국어
Logger System Migration Guide
SSOT: This document is the single source of truth for Logger System Migration Guide.
Version: 0.4.0.0 Last Updated: 2026-01-23
Table of Contents
- Overview
- CMake Configuration Changes
- Version Migration
- From v3.x to v4.0
- From v2.x to v3.0
- From v1.x to v2.x
- API Changes
- Configuration Migration
- Migration from Other Libraries
- Compatibility Wrappers
- Step-by-Step Migration
- Common Issues and Solutions
Overview
This guide helps you migrate to Logger System from:
- Earlier versions of Logger System (v3.x to v4.0, v2.x to v3.0, v1.x to v2.x)
- Other popular logging libraries (spdlog, Boost.Log, glog, log4cpp)
- Custom logging solutions
Breaking Changes Summary
| Version | Component | Change | Impact |
| v4.0 | Writers | Decorator pattern architecture | High for custom writers |
| v4.0 | Context IDs | Convenience methods removed | Medium |
| v4.0 | Context API | Unified context() method replaces 3 separate APIs | Medium |
| v3.0 | Namespace | logger_module → kcenon::logger | High |
| v3.0 | Interface | Implements common::interfaces::ILogger | High |
| v3.0 | Dependencies | thread_system now optional | Medium |
| v3.0 | C++ Standard | Requires C++20 | Medium |
| v3.0 | Result Types | Uses common::VoidResult | Medium |
| v2.0 | Error Handling | Exceptions → Result types | High |
| v2.0 | Memory Management | Raw pointers → Smart pointers | High |
| v2.0 | Configuration | Direct setters → Builder pattern | Medium |
From v3.x to v4.0
Version 4.0 introduces a decorator pattern-based writer architecture. This primarily affects users with custom writer implementations.
What Changed
- Decorator Pattern Writers: Cross-cutting concerns (filtering, buffering, formatting) are now separate decorator classes
- Context ID API Simplification: Specialized context ID methods removed in favor of generic API
- New Writer Components:
decorator_writer_base, filtered_writer, buffered_writer, formatted_writer
Migration for Standard Users
No changes required if you only use built-in writers via logger_builder:
auto logger = logger_builder()
.add_writer("console", std::make_unique<console_writer>())
.add_writer("file", std::make_unique<file_writer>("app.log"))
.with_min_level(log_level::info)
.build();
Migration for Custom Writer Authors
If you have custom writer implementations, see the detailed Decorator Migration Guide.
Quick summary:
class my_writer : public base_writer {
if (!should_log(entry)) return {};
auto formatted = format(entry);
buffer_.push(formatted);
return do_output(formatted);
}
};
class my_writer : public thread_safe_writer {
protected:
return do_output(entry);
}
};
auto writer = std::make_unique<formatted_writer>(
std::make_unique<buffered_writer>(
std::make_unique<filtered_writer>(
std::make_unique<my_writer>(),
std::make_unique<level_filter>(log_level::info)
),
buffered_writer::config{}
),
std::make_unique<json_formatter>()
);
Context ID API Changes
logger->set_trace_id(
"abc123");
logger->set_span_id(
"def456");
logger->set_context_id(
"trace_id",
"abc123");
logger->set_context_id(
"span_id",
"def456");
logger->clear_context_id(
"trace_id");
Unified Context API (New in v4.0)
Version 4.0 introduces the unified_log_context class that consolidates all context management into a single, type-safe API. The previous three overlapping APIs (set_context(), set_context_id(), set_otel_context()) are now deprecated in favor of the new context() method.
Why This Change?
| Issue | Impact |
| Confusion: When to use which API? | Developer friction |
Duplication: trace_id settable via all 3 APIs | Inconsistent state |
| Maintenance: 3 storage mechanisms | Code complexity |
| Testing: Must test all 3 paths | Test burden |
Migration Table
| Deprecated API | New API | Notes |
set_context(key, value) | context().set(key, value) | For custom fields |
remove_context(key) | context().remove(key) | |
clear_context() | context().clear() | Clears all categories |
has_context() | !context().empty() | |
get_context() | context().to_fields() | Returns log_fields |
set_context_id(key, value) | context().set(key, value, context_category::trace) | For trace/request IDs |
get_context_id(key) | context().get_string(key) | |
clear_context_id(key) | context().remove(key) | |
has_context_id(key) | context().has(key) | |
clear_all_context_ids() | context().clear(context_category::trace) | Clears only trace category |
set_otel_context(ctx) | context().set_otel(ctx) | OpenTelemetry context |
get_otel_context() | Query individual fields via context().get_string() | |
clear_otel_context() | context().clear(context_category::otel) | |
has_otel_context() | context().has("otel_trace_id") | |
Context Categories
The unified API organizes context into categories:
enum class context_category {
custom,
trace,
request,
otel
};
Code Examples
Setting Custom Context:
logger->set_context(
"user_id", int64_t{12345});
logger->set_context(
"session_active",
true);
logger->context().set(
"user_id", int64_t{12345});
logger->context().set(
"session_active",
true);
Setting Trace Context:
logger->set_context_id(
"trace_id",
"0af7651916cd43dd8448eb211c80319c");
logger->set_context_id(
"span_id",
"b7ad6b7169203331");
logger->context().set_trace(
"0af7651916cd43dd8448eb211c80319c",
"b7ad6b7169203331");
logger->context().set_trace(
"trace_id",
"span_id",
"parent_span_id");
Setting Request Context:
logger->set_context_id(
"request_id",
"req-123");
logger->set_context_id(
"correlation_id",
"corr-456");
logger->context().set_request(
"req-123",
"corr-456");
Setting OpenTelemetry Context:
otlp::otel_context otel_ctx{
.trace_id = "0af7651916cd43dd8448eb211c80319c",
.span_id = "b7ad6b7169203331",
.trace_flags = "01"
};
logger->set_otel_context(otel_ctx);
logger->context().set_otel(otel_ctx);
Clearing Context:
logger->clear_all_context_ids();
logger->context().clear(context_category::custom);
logger->context().clear(context_category::trace);
logger->context().clear(context_category::otel);
Querying Context:
std::string trace_id =
logger->get_context_id(
"trace_id");
bool has_trace =
logger->has_context_id(
"trace_id");
std::string trace_id =
logger->context().get_string(
"trace_id");
bool has_trace =
logger->context().has(
"trace_id");
auto user_id =
logger->context().get_as<int64_t>(
"user_id");
if (user_id) {
}
Method Chaining:
.set("user_id", int64_t{12345})
.set_trace("trace-abc", "span-123")
.set_request("req-456", "corr-789");
logger->log_structured(log_level::info)
.message("Processing request")
.emit();
Thread Safety
The unified_log_context class is thread-safe internally:
- Read operations use shared locks
- Write operations use exclusive locks
- No external synchronization required
Migration Script
#!/bin/bash
# migrate_context_api.sh
# Migrate set_context to context().set
find . -name "*.cpp" -o -name "*.h" | xargs sed -i '' \
-e 's/->set_context(\([^,]*\), /->context().set(\1, /g' \
-e 's/->remove_context(/->context().remove(/g' \
-e 's/->clear_context()/->context().clear()/g' \
-e 's/->has_context()/!context().empty()/g' \
-e 's/->get_context()/->context().to_fields()/g'
# Migrate set_context_id to context().set with category
find . -name "*.cpp" -o -name "*.h" | xargs sed -i '' \
-e 's/->set_context_id(\([^,]*\), \([^)]*\))/->context().set(\1, \2, context_category::trace)/g' \
-e 's/->get_context_id(/->context().get_string(/g' \
-e 's/->clear_context_id(/->context().remove(/g' \
-e 's/->has_context_id(/->context().has(/g' \
-e 's/->clear_all_context_ids()/->context().clear(context_category::trace)/g'
# Migrate OTEL context
find . -name "*.cpp" -o -name "*.h" | xargs sed -i '' \
-e 's/->set_otel_context(/->context().set_otel(/g' \
-e 's/->clear_otel_context()/->context().clear(context_category::otel)/g' \
-e 's/->has_otel_context()/->context().has("otel_trace_id")/g'
Deprecation Timeline
- v4.0 (Current): Old APIs marked with
[[deprecated]] - compiler warnings generated
- v5.0 (Future): Deprecated APIs will be removed
CMake Configuration Changes
v2.x (Previous)
# CMakeLists.txt for v2.x
find_package(thread_system REQUIRED) # Was required
find_package(logger_system REQUIRED)
target_link_libraries(your_app PRIVATE
thread_system::thread_system
logger_system::logger_system
)
# Build flags for v2.x
cmake -DUSE_THREAD_SYSTEM=ON .. # Old flag name
v3.0 (Current)
# CMakeLists.txt for v3.0
find_package(common_system REQUIRED) # New required dependency
find_package(logger_system REQUIRED)
# find_package(thread_system) # Optional now
target_link_libraries(your_app PRIVATE
kcenon::common
kcenon::logger
# kcenon::thread # Optional
)
# Build flags for v3.0
cmake -DLOGGER_USE_THREAD_SYSTEM=ON .. # New flag name (optional)
cmake -DLOGGER_STANDALONE_MODE=ON .. # Standalone mode (default)
CMake Flag Changes Summary
| v2.x Flag | v3.0 Flag | Default | Description |
USE_THREAD_SYSTEM=ON | LOGGER_USE_THREAD_SYSTEM=ON | OFF | Enable thread_system integration |
| N/A | LOGGER_STANDALONE_MODE=ON | ON | Use standalone std::jthread worker |
BUILD_TESTS=ON | BUILD_TESTS=ON | ON | Build test suite |
BUILD_EXAMPLES=ON | BUILD_EXAMPLES=ON | ON | Build examples |
Target Name Changes
| v2.x Target | v3.0 Target |
logger_system::logger_system | kcenon::logger |
thread_system::thread_system | kcenon::thread (optional) |
| N/A | kcenon::common (required) |
Dependency Changes
v2.x Dependency Tree:
logger_system
└── thread_system (required)
v3.0 Dependency Tree:
logger_system
├── common_system (required)
└── thread_system (optional, for async logging with thread pool)
└── common_system (required)
Version Migration
From v2.x to v3.0
Summary of Changes
| Aspect | v2.x | v3.0 |
| Namespace | logger_module | kcenon::logger |
| Interface | thread_module::logger_interface | common::interfaces::ILogger |
| Header Path | <logger_system/...> | <kcenon/logger/...> |
| Result Type | result_void | common::VoidResult |
| thread_system | Required | Optional |
| C++ Standard | C++17 | C++20 |
1. Namespace Migration
Old (v2.x):
#include <logger_system/logger.h>
#include <logger_system/logger_builder.h>
#include <logger_system/writers/console_writer.h>
auto logger = logger_builder()
.use_template("production")
.build();
New (v3.0):
Builder pattern for logger construction with validation.
logger_builder & use_template(const std::string &name)
result< std::unique_ptr< logger > > build()
Console writer for logging to stdout/stderr.
High-performance, thread-safe logging system with asynchronous capabilities.
Builder pattern implementation for flexible logger configuration kcenon.
2. Interface Migration
Old (v2.x):
class logger :
public thread_module::logger_interface {
result_void log(thread_module::log_level level,
const std::string& message) override;
};
logger->log(thread_module::log_level::info,
"Message");
New (v3.0):
class logger :
public common::interfaces::ILogger {
const std::string& message) override;
};
logger->log(common::interfaces::log_level::info,
"Message");
logger->log(log_level::info,
"Message");
3. Dual API Support
v3.0 provides both ILogger interface and native API:
.
add_writer(
"console", std::make_unique<console_writer>())
.value();
logger->log(common::interfaces::log_level::info,
"Using ILogger interface");
logger->log(common::interfaces::log_level::debug,
"Source location captured automatically");
logger->log(log_level::info,
"Using native API");
logger->log(log_level::error,
"Error message");
logger_builder & add_writer(const std::string &name, log_writer_ptr writer)
Add a writer to the logger.
4. Result Type Migration
Old (v2.x):
std::cerr <<
result.error().message() <<
"\n";
}
New (v3.0):
std::cerr <<
result.error().message <<
"\n";
}
}
5. thread_system Dependency Changes
Old (v2.x):
target_link_libraries(your_app PRIVATE thread_system::thread_system)
New (v3.0):
# find_package(thread_system OPTIONAL) # Only if needed
target_link_libraries(your_app PRIVATE
)
6. Backend Selection (New in v3.0)
logger_builder & with_standalone_backend()
Use standalone backend explicitly.
logger_builder & with_backend(std::unique_ptr< backends::integration_backend > backend)
Set integration backend explicitly.
7. C++20 Source Location
New in v3.0:
logger->log(common::interfaces::log_level::info,
"Debug message");
logger->log(common::interfaces::log_level::info,
"Message",
common::source_location::current());
8. Configuration Strategies (Enhanced in v3.0)
logger_builder & auto_configure()
Auto-configure from environment variables.
logger_builder & with_performance_tuning(performance_level level)
Apply performance tuning.
logger_builder & for_environment(deployment_env env)
Configure for a specific deployment environment.
9. Monitoring Integration (New in v3.0)
#include <kcenon/monitoring/monitoring.h>
auto monitor = std::make_shared<kcenon::monitoring::monitoring>();
logger_builder & with_monitoring(std::shared_ptr< common::interfaces::IMonitor > monitor)
Set monitoring interface (Phase 2.2.4)
logger_builder & with_health_check_interval(std::chrono::milliseconds interval)
Set health check interval.
Migration Script
For automated migration, use this script pattern:
#!/bin/bash
# migrate_v2_to_v3.sh
# Update includes
find . -name "*.cpp" -o -name "*.h" | xargs sed -i '' \
-e 's|#include <logger_system/|#include <kcenon/logger/|g' \
-e 's|#include "logger_system/|#include "kcenon/logger/|g'
# Update namespaces
find . -name "*.cpp" -o -name "*.h" | xargs sed -i '' \
-e 's|logger_module::|kcenon::logger::|g' \
-e 's|namespace logger_module|namespace kcenon::logger|g' \
-e 's|using namespace logger_module|using namespace kcenon::logger|g'
# Update interface references
find . -name "*.cpp" -o -name "*.h" | xargs sed -i '' \
-e 's|thread_module::logger_interface|common::interfaces::ILogger|g' \
-e 's|thread_module::log_level|common::interfaces::log_level|g'
# Update result types
find . -name "*.cpp" -o -name "*.h" | xargs sed -i '' \
-e 's|result_void|common::VoidResult|g'
From v1.x to v2.x
1. Error Handling Migration
Old (v1.x):
try {
} catch (const std::exception& e) {
std::cerr << "Failed: " << e.what() << std::endl;
}
Core file writer for logging to files.
New (v2.x):
auto result =
logger->add_writer(std::make_unique<file_writer>(
"app.log"));
std::cerr <<
"Failed: " <<
result.error().message() << std::endl;
}
2. Memory Management Migration
Old (v1.x):
Abstract base class for all log output writers.
New (v2.x):
auto writer = std::make_unique<file_writer>("app.log");
logger->add_writer(std::move(writer));
3. Configuration Migration
Old (v1.x):
log->set_min_level(log_level::info);
log->set_async(true);
log->set_buffer_size(10000);
log->add_console_writer();
log->add_file_writer("app.log");
New (v2.x):
.with_async_mode(true)
.with_console_writer()
.with_file_writer("app.log")
logger_builder & with_min_level(log_level level)
logger_builder & with_buffer_size(std::size_t size)
Set buffer size.
4. Logging API Migration
Old (v1.x):
LOG_INFO(
logger,
"Message with %s", param);
LOG_DEBUG_F(
logger,
"Formatted: {}", value);
New (v2.x):
logger->info(
"Message with param", {{
"param", param}});
logger->debug(
"Message", {{
"value", value}});
API Changes
v3.0 API Changes Summary
| v2.x | v3.0 | Notes |
logger_module::logger | kcenon::logger::logger | Namespace change |
thread_module::logger_interface | common::interfaces::ILogger | Interface change |
thread_module::log_level | common::interfaces::log_level | Level type change |
result_void | common::VoidResult | Result type change |
set_min_level(level) | set_level(level) | Method rename (deprecated) |
get_min_level() | get_level() | Method rename (deprecated) |
| N/A | log(level, msg, source_location) | New C++20 overload |
| N/A | with_standalone_backend() | New backend selection |
| N/A | for_environment(env) | New configuration strategy |
| N/A | with_performance_tuning(level) | New configuration strategy |
| N/A | with_monitoring(monitor) | New monitoring integration |
Deprecated Native log_level API (Planned for Removal in v3.0.0)
The following native logger_system::log_level APIs are deprecated in favor of common::interfaces::log_level:
| Deprecated API | Recommended Alternative | Status |
logger_system::log_level enum | common::interfaces::log_level | Deprecated, will be removed in v3.0.0 |
log(log_level, const std::string&) | log(common::interfaces::log_level, const std::string&) | Deprecated |
log(log_level, msg, file, line, func) | log(common::interfaces::log_level, std::string_view, source_location) | Deprecated |
log(log_level, msg, log_context) | log(common::interfaces::log_level, std::string_view, source_location) | Deprecated |
is_enabled(log_level) | is_enabled(common::interfaces::log_level) | Deprecated |
set_min_level(log_level) | set_level(common::interfaces::log_level) | Deprecated |
get_min_level() | get_level() | Deprecated |
log_level_to_string() | common::interfaces::log_level_to_string() | Deprecated |
string_to_log_level() | common::interfaces::string_to_log_level() | Deprecated |
to_logger_system_level() | Use common::interfaces::log_level directly | Deprecated |
to_common_level() | Use common::interfaces::log_level directly | Deprecated |
Migration Example:
logger->log(log_level::info,
"Message");
logger->set_min_level(log_level::debug);
if (
logger->is_enabled(log_level::trace)) { ... }
#include <kcenon/common/interfaces/logger_interface.h>
logger->log(common::interfaces::log_level::info,
"Message");
logger->set_level(common::interfaces::log_level::debug);
if (
logger->is_enabled(common::interfaces::log_level::trace)) { ... }
using common::interfaces::log_level;
logger->log(log_level::info,
"Message");
Common types and enumerations for logger system.
Timeline:
- Current: APIs marked with
[[deprecated]] attribute - compiler warnings will be generated
- v3.0.0: Deprecated APIs will be removed
Core Logger API
| v1.x Method | v2.x Equivalent | v3.0 Equivalent |
log(level, msg) | log(level, msg, fields) | log(level, msg) via ILogger |
set_min_level(level) | Builder: with_min_level(level) | set_level(level) + Builder |
add_writer(writer*) | add_writer(unique_ptr<writer>) | Same as v2.x |
flush() | flush() → result<void> | flush() → VoidResult |
Configuration Migration
From INI/XML Configuration
Old (config.ini):
[logger]
level = INFO
async = true
buffer_size = 10000
[console]
enabled = true
colored = true
[file]
enabled = true
path = app.log
rotation = 10485760
max_files = 5
New (code-based, v3.0):
auto create_logger_from_config() {
.
add_writer(
"console", std::make_unique<console_writer>(
true))
.
add_writer(
"file", std::make_unique<rotating_file_writer>(
"app.log", 10 * 1024 * 1024, 5))
}
logger_builder & with_async(bool async=true)
Rotating file writer with size and time-based rotation.
Environment-based Configuration (v3.0)
Migration from Other Libraries
From spdlog
#include "spdlog/spdlog.h"
#include "spdlog/sinks/basic_file_sink.h"
auto logger = spdlog::basic_logger_mt(
"my_logger",
"logs/my_log.txt");
logger->set_level(spdlog::level::info);
logger->info(
"Hello {}",
"World");
logger->error(
"Error code: {}", 404);
.
add_writer(
"file", std::make_unique<file_writer>(
"logs/my_log.txt"))
.value();
logger->log(common::interfaces::log_level::info,
"Hello World");
logger->log(common::interfaces::log_level::error,
"Error code: 404");
logger->log(log_level::info,
"Hello World");
logger->log(log_level::error,
"Error code: 404");
File writer for logging to files with optional buffering.
From Boost.Log
#include <boost/log/trivial.hpp>
#include <boost/log/utility/setup/file.hpp>
namespace logging = boost::log;
logging::add_file_log("sample.log");
BOOST_LOG_TRIVIAL(info) << "An informational message";
BOOST_LOG_TRIVIAL(error) << "An error message";
.
add_writer(
"file", std::make_unique<file_writer>(
"sample.log"))
.value();
logger->log(common::interfaces::log_level::info,
"An informational message");
logger->log(common::interfaces::log_level::error,
"An error message");
From Google glog
#include <glog/logging.h>
google::InitGoogleLogging(argv[0]);
LOG(INFO) << "Found " << num_cookies << " cookies";
CHECK(condition) << "Condition failed";
.value();
logger->log(common::interfaces::log_level::info,
"Found " + std::to_string(num_cookies) + " cookies");
logger->log(common::interfaces::log_level::error,
if (!condition) {
logger->log(common::interfaces::log_level::fatal,
"Condition failed");
std::abort();
}
logger_error_code
Error codes specific to the logger system.
Compatibility Wrappers
v2.x to v3.0 Compatibility Header
#pragma once
template<typename T>
namespace thread_module {
using log_level = common::interfaces::log_level;
}
Legacy API Wrapper (v1.x compatibility)
#pragma once
#define LOG_INFO(logger, msg, ...) \
logger->log(common::interfaces::log_level::info, format_string(msg, ##__VA_ARGS__))
#define LOG_ERROR(logger, msg, ...) \
logger->log(common::interfaces::log_level::error, format_string(msg, ##__VA_ARGS__))
#define LOG_DEBUG(logger, msg, ...) \
logger->log(common::interfaces::log_level::debug, format_string(msg, ##__VA_ARGS__))
namespace logger_v1_compat {
[[deprecated("Use kcenon::logger::logger_builder instead")]]
inline auto create_logger() {
}
}
Step-by-Step Migration
Phase 1: Preparation
- Check C++ Standard
# Ensure C++20 is enabled
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
- Update Dependencies
# v3.0 requires common_system
find_package(common_system REQUIRED)
find_package(logger_system REQUIRED)
# thread_system is now optional
# find_package(thread_system OPTIONAL)
- Create Migration Branch
git checkout -b migration/logger-v3.0
Phase 2: Namespace Migration
- Update Include Paths
#include <logger_system/logger.h>
- Update Namespace Usage
Phase 3: Interface Migration
- Update Interface References
class MyLogger : public thread_module::logger_interface { ... };
class MyLogger : public common::interfaces::ILogger { ... };
- Update Log Level Types
thread_module::log_level::info
common::interfaces::log_level::info
kcenon::logger::log_level::info
Phase 4: Validation
- Run Tests
mkdir build && cd build
cmake .. -DCMAKE_CXX_STANDARD=20
make -j$(nproc)
ctest --output-on-failure
- Check Sanitizers
cmake .. -DCMAKE_CXX_FLAGS="-fsanitize=address,undefined"
make && ctest
Common Issues and Solutions
Issue 1: Namespace Not Found
Error:
error: 'logger_module' is not a namespace-name
Solution:
Issue 2: Interface Type Mismatch
Error:
error: 'thread_module::logger_interface' is not a base of 'kcenon::logger::logger'
Solution:
thread_module::logger_interface*
logger = ...;
common::interfaces::ILogger*
logger = ...;
Issue 3: Result Type Mismatch
Error:
error: cannot convert 'common::VoidResult' to 'result_void'
Solution:
Issue 4: Missing thread_system
Error:
error: 'thread_module' has not been declared
Solution:
#include <thread_system/logger_interface.h>
#include <common/interfaces/logger_interface.h>
Issue 5: C++20 Not Enabled
Error:
error: 'source_location' is not a member of 'std'
Solution:
# Ensure C++20 is enabled
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
Migration Checklist
v2.x to v3.0 Migration
- Enable C++20 in build system
- Update common_system dependency
- Update include paths (
logger_system/ → kcenon/logger/)
- Update interface references (
thread_module::logger_interface → common::interfaces::ILogger)
- Update log level types (
thread_module::log_level → common::interfaces::log_level)
- Update result types (
result_void → common::VoidResult)
- Remove thread_system dependency if not needed
- Update deprecated method calls (
set_min_level → set_level)
v1.x to v2.x Migration
- Add compatibility headers
- Update build system (CMake/Make)
- Migrate logger creation to builder pattern
- Update writer management to smart pointers
Support and Resources
For migration assistance, please file an issue with the migration label.
Last Updated: 2026-01-23