autotoc_md1404
doc_id: "LOG-GUID-001b" doc_title: "Configuration Strategies - Advanced" doc_version: "1.0.0" doc_date: "2026-04-04" doc_status: "Released" project: "logger_system"
category: "GUID"
Configuration Strategies - Advanced
Split from: CONFIGURATION_STRATEGIES.md
Composite strategies, custom strategy implementation, priority-based conflict resolution, and production tuning patterns.
Table of Contents
- Composite Strategy
- Custom Strategy Implementation
- Strategy Priority and Conflict Resolution
- Best Practices
- Summary
Composite Strategy
Header: include/kcenon/logger/core/strategies/composite_strategy.h
Purpose: Combine multiple strategies into a single strategy.
How It Works
- Add strategies to the composite (via
add())
- Sort by priority (descending: 100 -> 75 -> 50 -> ...)
- Apply each applicable strategy in order
- Later strategies override earlier ones (conflict resolution)
API
class composite_strategy : public config_strategy_interface {
public:
composite_strategy& add(std::unique_ptr<config_strategy_interface> strategy);
template<typename Strategy, typename... Args>
composite_strategy& add(Args&&... args);
composite_strategy& clear();
std::size_t size() const;
bool empty() const;
};
Method Details
add(std::unique_ptr<config_strategy_interface> strategy)
Purpose: Add a pre-constructed strategy to the composite.
Parameters:
strategy – Ownership is transferred to the composite
Returns: Reference to this (for method chaining)
Example:
composite_strategy composite;
composite.add(std::make_unique<deployment_strategy>(deployment_env::production));
composite.add(std::make_unique<performance_strategy>(performance_level::high_throughput));
add<Strategy, Args...>(Args&&... args)
Purpose: Construct and add a strategy in-place (template method).
Template parameters:
Strategy – Strategy type to construct
Args... – Constructor argument types
Parameters:
args... – Constructor arguments (forwarded)
Returns: Reference to this (for method chaining)
Example:
composite_strategy composite;
composite.add<deployment_strategy>(deployment_env::staging)
.add<performance_strategy>(performance_level::balanced)
.add<environment_strategy>();
Priority-Based Application
Example scenario:
composite_strategy composite;
composite.add<environment_strategy>();
composite.add<deployment_strategy>(deployment_env::production);
composite.add<performance_strategy>(performance_level::balanced);
logger_config config;
composite.apply(config);
Application order:
environment_strategy (priority 100) – Sets config from environment variables
deployment_strategy (priority 75) – Applies production settings (may override environment)
performance_strategy (priority 50) – Applies balanced settings (may override deployment)
Conflict resolution:
- If environment sets
LOG_ASYNC=false, but deployment sets async=true:
environment_strategy applies first -> config.async = false
deployment_strategy applies second -> config.async = true (overrides)
performance_strategy applies third -> config.async = true (keeps deployment value)
- Result:
config.async = true (deployment/performance wins over environment)
To prioritize environment variables:
class low_priority_deployment : public deployment_strategy {
int priority() const override { return 25; }
};
composite.add<low_priority_deployment>(deployment_env::production);
composite.add<performance_strategy>(performance_level::balanced);
Explicit Composite Strategy Example
#include <kcenon/logger/logger_builder.h>
composite_strategy composite;
composite.add<deployment_strategy>(deployment_env::production)
.add<performance_strategy>(performance_level::high_throughput)
.add<environment_strategy>();
auto logger = logger_builder::create()
.with_strategy(std::make_unique<composite_strategy>(std::move(composite)))
.with_file_writer("/var/log/app.log")
.build();
}
Composite configuration strategy for combining multiple strategies.
Deployment environment configuration strategies.
Environment variable-based configuration strategy.
Custom Strategy Implementation
Basic Custom Strategy
class cloud_vendor_strategy : public config_strategy_interface {
public:
enum class vendor {
aws,
gcp,
azure
};
explicit cloud_vendor_strategy(vendor v) : vendor_(v) {}
std::string get_name() const override {
return "cloud:" + vendor_to_string(vendor_);
}
void apply(logger_config& config) const override {
switch (vendor_) {
case vendor::aws:
apply_aws(config);
break;
case vendor::gcp:
apply_gcp(config);
break;
case vendor::azure:
apply_azure(config);
break;
}
}
int priority() const override {
return 60;
}
private:
vendor vendor_;
static void apply_aws(logger_config& config) {
config.enable_structured_logging = true;
config.enable_batch_writing = true;
config.batch_size = 500;
config.flush_interval = std::chrono::milliseconds(5000);
}
static void apply_gcp(logger_config& config) {
config.enable_structured_logging = true;
config.enable_compression = true;
config.batch_size = 250;
}
static void apply_azure(logger_config& config) {
config.enable_structured_logging = true;
config.enable_batch_writing = true;
config.batch_size = 300;
}
static std::string vendor_to_string(vendor v) {
switch (v) {
case vendor::aws: return "aws";
case vendor::gcp: return "gcp";
case vendor::azure: return "azure";
default: return "unknown";
}
}
};
Interface for logger configuration strategies (Strategy Pattern)
Configuration structure for logger with validation.
Usage:
auto logger = logger_builder::create()
.with_strategy<deployment_strategy>(deployment_env::production)
.with_strategy<cloud_vendor_strategy>(cloud_vendor_strategy::vendor::aws)
.with_file_writer("/var/log/app.log")
.build();
Conditional Strategy (is_applicable)
class region_strategy : public config_strategy_interface {
public:
explicit region_strategy(std::string region)
: region_(std::move(region)) {}
std::string get_name() const override {
return "region:" + region_;
}
bool is_applicable() const override {
const char* env_region = std::getenv("REGION");
return env_region != nullptr && env_region == region_;
}
void apply(logger_config& config) const override {
if (region_ == "us-east-1") {
config.buffer_size = 65536;
config.batch_size = 500;
} else if (region_ == "eu-west-1") {
config.enable_metrics = false;
config.enable_source_location = false;
}
}
int priority() const override {
return 90;
}
private:
std::string region_;
};
Usage:
composite_strategy composite;
composite.add<region_strategy>("us-east-1");
composite.add<region_strategy>("eu-west-1");
composite.add<deployment_strategy>(deployment_env::production);
auto logger = logger_builder::create()
.with_strategy(std::make_unique<composite_strategy>(std::move(composite)))
.build();
Strategy Priority and Conflict Resolution
Priority Values
| Strategy | Priority | Rationale |
| environment_strategy | 100 | Environment variables should override all other settings |
| deployment_strategy | 75 | Deployment context is more specific than performance |
| performance_strategy | 50 | Performance tuning is general-purpose |
| Custom strategies | 0 (default) | Applied last unless overridden |
Conflict Resolution Rules
- Strategies are sorted by priority (descending)
- Higher priority -> applied first
- Lower priority -> applied last (and overrides earlier settings)
- Later strategies override earlier ones
composite.add<deployment_strategy>(deployment_env::production);
composite.add<environment_strategy>();
To make environment variables win:
class low_priority_deployment : public deployment_strategy {
int priority() const override { return 25; }
};
composite.add<low_priority_deployment>(deployment_env::production);
class high_priority_environment : public environment_strategy {
int priority() const override { return 25; }
};
composite.add<deployment_strategy>(deployment_env::production);
Wait, this is confusing. Let me re-read the composite_strategy code:
std::sort(sorted.begin(), sorted.end(),
[](const auto* a, const auto* b) {
return a->priority() > b->priority();
});
for (const auto* strategy : sorted) {
if (strategy->is_applicable()) {
strategy->apply(config);
}
}
Analysis:
- Strategies are sorted in descending order by priority (100 -> 75 -> 50 -> ...)
- Applied in that order (highest priority first, lowest last)
- Last applied strategy wins (overwrites previous values)
- Therefore, LOWER priority values win (applied last, override earlier)
Correction (final): To make environment variables win, give environment_strategy a LOWER priority:
class low_priority_deployment : public deployment_strategy {
int priority() const override { return 25; }
};
composite.add<low_priority_deployment>(deployment_env::production);
class high_priority_environment : public environment_strategy {
int priority() const override { return 10; }
};
composite.add<deployment_strategy>(deployment_env::production);
- Summary:
- Higher priority number -> Applied first
- Lower priority number -> Applied last (wins conflicts)
- Default
environment_strategy priority (100) means it's applied first, so other strategies override it
- To make environment variables the final word, give it a lower priority (e.g., 10)
Best Practice: Environment Variables as Final Override
class final_environment_strategy : public environment_strategy {
int priority() const override {
return 10;
}
};
composite.add<deployment_strategy>(deployment_env::production);
composite.add<performance_strategy>(performance_level::balanced);
logger_config config;
deployment_strategy(deployment_env::production).apply(config);
performance_strategy(performance_level::balanced).apply(config);
environment_strategy().apply(config);
Best Practices
1. Start with Defaults, Override as Needed
auto dev_logger = logger_builder::create()
.with_strategy<deployment_strategy>(deployment_env::development)
.build();
auto prod_logger = logger_builder::create()
.with_strategy<deployment_strategy>(deployment_env::production)
.with_strategy<performance_strategy>(performance_level::high_throughput)
.with_strategy<environment_strategy>()
.build();
2. Use Environment Variables for Runtime Configuration
auto logger = logger_builder::create()
.with_strategy<environment_strategy>()
.with_file_writer("/var/log/app.log")
.build();
Deployment:
# Development
LOG_LEVEL=trace LOG_COLOR=true ./myapp
# Production
LOG_LEVEL=warn LOG_ASYNC=true LOG_BUFFER_SIZE=65536 ./myapp
3. Combine Strategies for Complex Requirements
composite_strategy composite;
composite.add<deployment_strategy>(deployment_env::production);
composite.add<performance_strategy>(performance_level::high_throughput);
composite.add<cloud_vendor_strategy>(cloud_vendor_strategy::vendor::aws);
composite.add<region_strategy>("us-east-1");
composite.add<environment_strategy>();
auto logger = logger_builder::create()
.with_strategy(std::make_unique<composite_strategy>(std::move(composite)))
.build();
4. Test Strategies in Isolation
TEST(StrategyTest, DeploymentProduction) {
logger_config config;
deployment_strategy(deployment_env::production).apply(config);
ASSERT_TRUE(config.async);
ASSERT_EQ(config.min_level, log_level::warn);
ASSERT_TRUE(config.enable_compression);
}
TEST(StrategyTest, PerformanceHighThroughput) {
logger_config config;
performance_strategy(performance_level::high_throughput).apply(config);
ASSERT_EQ(config.buffer_size, 65536);
ASSERT_EQ(config.batch_size, 500);
ASSERT_TRUE(config.enable_compression);
}
5. Document Custom Strategies
class my_custom_strategy : public config_strategy_interface {
};
Summary
The logger_system configuration strategies framework provides:
- Flexible configuration – Adapt logger behavior to environment/performance needs
- Composability – Combine multiple strategies with priority-based conflict resolution
- Reusability – Share configurations across projects
- Testability – Mock strategies for unit tests
- 12-factor compliance – Environment variable support for containerized deployments
Built-in strategies:
- Deployment – 4 environments (development, staging, production, testing)
- Environment – 11 environment variables (LOG_LEVEL, LOG_ASYNC, etc.)
- Performance – 4 levels (low_latency, balanced, high_throughput, minimal_overhead)
- Composite – Combine multiple strategies with priority ordering
Next steps:
- Review ARCHITECTURE.md for logger architecture overview
- Review API.md for full API reference
- Review EXAMPLES.md for usage examples
Last updated: 2025-02-09 logger_system version: 2.x