-
Notifications
You must be signed in to change notification settings - Fork 130
04a Areg SDK Logging Configuration
The Areg SDK provides a highly configurable logging system via the areg.init configuration file, enabling customization of log destinations, formats, scopes, and priorities for enhanced debugging and runtime analysis.
Tip
Start with the Quick Start section to see logging in action, then customize based on your needs.
- Quick Start
- Configuration File Overview
- Log Destinations
- Log Message Layout
- Remote Log Collector
- Log Viewing with Lusan
- Scopes and Priorities
- Common Configurations
- Troubleshooting
Step 1: Create configuration file
Create areg.init in your application directory:
# Basic logging configuration
log::*::target = file
log::*::enable::file = true
log::*::file::location = ./logs/%appname%_%time%.log
# Enable all scopes
log::*::scope::* = DEBUG | SCOPEStep 2: Initialize logging in application
#include "areg/appbase/Application.hpp"
int main()
{
// Initialize with logging enabled
Application::initApplication(
true, // Enable logging ← Important
true, // Enable service manager
false, // Disable router client (for this example)
true, // Enable timer manager
false, // Disable watchdog
"./areg.init", // Configuration file
nullptr
);
// Your application code
Application::loadModel("MyModel");
Application::waitAppQuit(NECommon::WAIT_INFINITE);
Application::releaseApplication();
return 0;
}Step 3: Run application
./myappExpected output in ./logs/myapp_20260127_103045.log:
2026-01-27 10:30:45.123: [ 12345 myapp.exe: Enter -->]
Entering scope: main
2026-01-27 10:30:45.124: [ 12345 DEBUG >>> ] Application initialized
2026-01-27 10:30:45.125: [ 12345 INFO >>> ] Loading model: MyModel
2026-01-27 10:30:45.126: [ 12345 myapp.exe: Exit <-- ]
Exiting scope: main
Setup time: ~30 seconds
Default name: areg.init
Common locations:
- Application directory:
./areg.init - Config subdirectory:
./config/areg.init - Installed location:
/usr/local/share/areg/areg.init(Linux)
Specify custom location:
Application::initApplication(
true, // Enable logging
true, true, true, false,
"./my-config/custom.init", // Custom config file
nullptr
);Settings use key-value pairs:
Format:
section::(module|*)::property[::position] = value
Components:
-
section - Configuration section (e.g.,
log,logger) -
module - Application name or
*for all - property - Setting name
- position - Optional sub-property
- value - Setting value
Examples:
# Global setting (all applications)
log::*::target = file
# Application-specific setting
log::myapp::target = file | remote
# Property with position
log::*::enable::file = trueTip
For complete syntax details, see Persistence Syntax Guide.
| Destination | Value | Description | Use Case |
|---|---|---|---|
| File | file |
Local log files | Development, production |
| Remote | remote |
Centralized log collector | Distributed systems |
| Debug Output | debug |
IDE debug console (MSVC) | Visual Studio debugging |
| Database | db |
Database storage | Long-term analysis |
Configuration:
# Enable file logging
log::*::target = file
log::*::enable::file = true
# Specify log file location
log::*::file::location = ./logs/%appname%_%time%.logFile naming masks:
| Mask | Replaced With | Example |
|---|---|---|
%appname% |
Application name | myapp |
%time% |
Timestamp (YYYYMMDD_HHMMSS) | 20260127_103045 |
%pid% |
Process ID | 12345 |
Examples:
# Single log file per application
log::*::file::location = ./logs/%appname%.log
Result: ./logs/myapp.log
# Separate log per run
log::*::file::location = ./logs/%appname%_%time%.log
Result: ./logs/myapp_20260127_103045.log
# Include process ID
log::*::file::location = ./logs/%appname%_pid%pid%.log
Result: ./logs/myapp_pid12345.logLog file output:
2026-01-27 10:30:45.123: [ 12345 DEBUG >>> ] Application started
2026-01-27 10:30:45.124: [ 12345 INFO >>> ] Connecting to service
2026-01-27 10:30:45.125: [ 12345 WARN >>> ] Connection delayed
2026-01-27 10:30:45.126: [ 12345 ERROR >>> ] Connection failed
Configuration:
# Enable remote logging
log::*::target = remote
log::*::enable::remote = true
# Connection settings
logger::*::connect = tcpip
logger::*::address::tcpip = 127.0.0.1
logger::*::port::tcpip = 8282
# Optional: Queue size for buffering
log::*::remote::queue = 100Use cases:
- Centralized log collection
- Distributed systems
- Real-time log monitoring
- Multiple applications logging to one collector
Prerequisites:
-
logcollectorservice must be running - Network connectivity to log collector
See: Log Collector Guide for setup
Configuration:
# Enable debug output
log::*::target = debug
log::*::enable::debug = trueUse cases:
- Visual Studio debugging
- Real-time log viewing in IDE
- Development on Windows
Output location: Visual Studio Debug Output window
Expected output in Visual Studio:
[12345] DEBUG: Application started
[12345] INFO: Connecting to service
[12345] WARN: Connection delayed
Configuration:
# Enable database logging
log::*::target = db
log::*::enable::db = true
# Database connection (example)
log::*::db::connection = ./logs/application.dbUse cases:
- Structured log analysis
- SQL queries on logs
- Long-term log retention
- Complex filtering and reporting
Enable multiple targets:
# Log to file AND remote collector
log::*::target = file | remote
# Enable both
log::*::enable::file = true
log::*::enable::remote = true
# File configuration
log::*::file::location = ./logs/%appname%.log
# Remote configuration
logger::*::address::tcpip = 192.168.1.100
logger::*::port::tcpip = 8282Use cases:
- Development: File + Debug
- Production: File + Remote
- Analysis: File + Database
Define how log messages appear:
# Scope entry layout
log::*::layout::enter = %d: [ %t %x.%z: Enter -->]%n
# Log message layout
log::*::layout::message = %d: [ %t %p >>> ] %m%n
# Scope exit layout
log::*::layout::exit = %d: [ %t %x.%z: Exit <-- ]%n| Specifier | Description | Example Output |
|---|---|---|
%a |
Logging object ID | 0x12345678 |
%c |
Tick count since start | 1234567 |
%d |
Date and time | 2026-01-27 10:30:45.123 |
%e |
Module (process) ID | 12345 |
%m |
Log message text | Application started |
%n |
End-of-line | (newline) |
%p |
Message priority |
DEBUG, INFO, WARN
|
%s |
Message scope ID | 0x00001234 |
%t |
Thread ID | 54321 |
%x |
Module (process) name | myapp.exe |
%y |
Thread name | WorkerThread |
%z |
Scope name | main::initialize |
Note
%m (message) and %z (scope name) are mutually exclusive in the same layout.
Example 1: Minimal layout
log::*::layout::message = %p: %m%nOutput:
DEBUG: Application started
INFO: Connecting to service
WARN: Connection delayed
Example 2: Detailed layout
log::*::layout::message = [%d] %x (thread %t) %p: %m%nOutput:
[2026-01-27 10:30:45.123] myapp.exe (thread 54321) DEBUG: Application started
[2026-01-27 10:30:45.124] myapp.exe (thread 54321) INFO: Connecting to service
Example 3: Custom layout with thread name
log::*::layout::message = %d %y [%p] %m%nOutput:
2026-01-27 10:30:45.123 MainThread [DEBUG] Application started
2026-01-27 10:30:45.124 WorkerThread [INFO] Processing request
Example 4: Scope entry/exit
log::*::layout::enter = >>> Entering %z (thread %t)%n
log::*::layout::exit = <<< Exiting %z (thread %t)%nOutput:
>>> Entering main::initialize (thread 54321)
... other log messages ...
<<< Exiting main::initialize (thread 54321)
Configuration:
log::*::layout::enter = %d [%t] --> %z%n
log::*::layout::message = %d [%t] %p: %m%n
log::*::layout::exit = %d [%t] <-- %z%nOutput:
2026-01-27 10:30:45.123 [54321] --> main
2026-01-27 10:30:45.124 [54321] DEBUG: Initializing application
2026-01-27 10:30:45.125 [54321] INFO: Configuration loaded
2026-01-27 10:30:45.126 [54321] <-- main
Enable remote logging:
# Set remote as target
log::*::target = remote
log::*::enable::remote = true
# Configure connection to log collector
logger::*::connect = tcpip
logger::*::address::tcpip = 127.0.0.1
logger::*::port::tcpip = 8282
# Optional: Message queue size
log::*::remote::queue = 100| Property | Default | Description |
|---|---|---|
logger::*::connect |
tcpip |
Protocol (TCP/IP only) |
logger::*::address::tcpip |
127.0.0.1 |
Log collector IP |
logger::*::port::tcpip |
8282 |
Log collector port |
log::*::remote::queue |
100 |
Message buffer size |
Scenario: Central log collector for distributed system
Machine 1 (192.168.1.100) - Log Collector:
# Start log collector
/usr/local/tools/areg/logcollector --consoleMachine 2 - Application A:
# app_a.init
logger::*::address::tcpip = 192.168.1.100
logger::*::port::tcpip = 8282
log::*::target = remoteMachine 3 - Application B:
# app_b.init
logger::*::address::tcpip = 192.168.1.100
logger::*::port::tcpip = 8282
log::*::target = remoteResult: Both applications send logs to centralized collector
With remote logging, use logobserver to control scopes and priorities in real-time without restarting applications:
Features:
- Change log priorities dynamically
- Enable/disable scopes on the fly
- Configure multiple applications simultaneously
Note
logobserver is a control and log collector tool only - it does not display logs. For log viewing, use Lusan GUI application.
See: Log Observer Guide for details
Lusan is a GUI application for real-time log monitoring and analysis. It connects to logcollector to display logs from all connected applications with advanced filtering and visualization features.
Features:
- Real-time log viewing from multiple applications
- Advanced filtering by priority, scope, and text
- Color-coded log levels
- Search and export capabilities
- Timeline visualization
Prerequisites:
-
logcollectorservice running - Applications configured for remote logging
See: Lusan Live Log Viewer Guide for complete setup and usage.
Tip
Lusan provides a professional GUI alternative to viewing log files. It's part of the Areg SDK and developed in areg-sdk-tools repository.
Scopes are logical groupings of code where logging occurs. They represent:
- Functions or methods
- Classes or modules
- Components or subsystems
Scope configuration:
# Enable all scopes
log::*::scope::* = DEBUG | SCOPE
# Application-specific scopes
log::myapp::scope::module_foo = DEBUG | SCOPE
log::myapp::scope::module_bar = INFO
log::myapp::scope::module_baz = NOTSET| Priority | Value | What Gets Logged |
|---|---|---|
| NOTSET | Disabled | Nothing |
| FATAL | Highest | Fatal errors only |
| ERROR | High | Errors + Fatal |
| WARN | Medium | Warnings + Errors + Fatal |
| INFO | Low | Info + Warnings + Errors + Fatal |
| DEBUG | Lowest | Everything (Debug + Info + Warn + Error + Fatal) |
| SCOPE | Special | Scope entry/exit only |
Priorities can be combined with | (OR):
Common combinations:
# All messages + scope entry/exit
log::*::scope::* = DEBUG | SCOPE
# Warnings and errors only
log::*::scope::* = WARN
# Errors, fatal, + scope tracking
log::*::scope::* = ERROR | SCOPE
# Info and above, no scope tracking
log::*::scope::* = INFO
# Disable all logging
log::*::scope::* = NOTSETExample 1: DEBUG | SCOPE
Configuration:
log::*::scope::mymodule = DEBUG | SCOPELogs:
- ✅ Scope entry/exit
- ✅ DEBUG messages
- ✅ INFO messages
- ✅ WARN messages
- ✅ ERROR messages
- ✅ FATAL messages
Result: Everything
Example 2: WARN | SCOPE
Configuration:
log::*::scope::mymodule = WARN | SCOPELogs:
- ✅ Scope entry/exit
- ❌ DEBUG messages
- ❌ INFO messages
- ✅ WARN messages
- ✅ ERROR messages
- ✅ FATAL messages
Result: Warnings and errors + scope tracking
Example 3: ERROR
Configuration:
log::*::scope::mymodule = ERRORLogs:
- ❌ Scope entry/exit
- ❌ DEBUG messages
- ❌ INFO messages
- ❌ WARN messages
- ✅ ERROR messages
- ✅ FATAL messages
Result: Only errors and fatal, no scope tracking
Example 4: NOTSET
Configuration:
log::*::scope::mymodule = NOTSETLogs:
- ❌ Everything disabled
Result: No logging for this scope
Enable groups of scopes:
# All scopes starting with "network"
log::*::scope::network_* = DEBUG | SCOPE
# All scopes in myapp
log::myapp::scope::* = INFO
# Specific patterns
log::*::scope::http_* = WARN
log::*::scope::db_* = ERRORDifferent settings per application:
# Global default
log::*::scope::* = WARN
# Application A: verbose logging
log::appA::scope::* = DEBUG | SCOPE
# Application B: errors only
log::appB::scope::* = ERROR
# Application C: specific modules
log::appC::scope::network_* = DEBUG
log::appC::scope::database_* = INFO
log::appC::scope::ui_* = NOTSETGoal: Maximum visibility for debugging
# Log to file and debug output
log::*::target = file | debug
log::*::enable::file = true
log::*::enable::debug = true
# Detailed logs with timestamps
log::*::file::location = ./logs/%appname%_%time%.log
# Log everything
log::*::scope::* = DEBUG | SCOPE
# Detailed layout
log::*::layout::enter = %d [%t] --> %x.%z%n
log::*::layout::message = %d [%t] %p: %m%n
log::*::layout::exit = %d [%t] <-- %x.%z%nGoal: Performance + essential logs
# Log to file only
log::*::target = file
log::*::enable::file = true
# Single log file
log::*::file::location = /var/log/myapp/myapp.log
# Warnings and errors only
log::*::scope::* = WARN
# Minimal layout
log::*::layout::message = %d %p: %m%nGoal: Centralized logging across network
# Remote logging
log::*::target = remote | file
log::*::enable::remote = true
log::*::enable::file = true
# Backup local file
log::*::file::location = ./logs/%appname%.log
# Remote collector settings
logger::*::connect = tcpip
logger::*::address::tcpip = 192.168.1.100
logger::*::port::tcpip = 8282
# Buffer for network delays
log::*::remote::queue = 200
# Info and above
log::*::scope::* = INFOGoal: Focus on one module
# Log to file
log::*::target = file
log::*::enable::file = true
log::*::file::location = ./logs/%appname%.log
# Most modules: warnings only
log::*::scope::* = WARN
# Target module: verbose
log::*::scope::problematic_module = DEBUG | SCOPE
# Related modules: info
log::*::scope::related_module_* = INFOGoal: Minimal logging overhead
# File only
log::*::target = file
log::*::enable::file = true
log::*::file::location = ./logs/%appname%.log
# Errors only
log::*::scope::* = ERROR
# Minimal layout
log::*::layout::message = %p: %m%n
# No scope tracking
# (no SCOPE in priorities)Problem: Application runs but no log file appears.
Solution:
1. Check logging is enabled:
Application::initApplication(
true, // Must be true ← Check this
true, true, true, false,
"./areg.init",
nullptr
);2. Check configuration file is loaded:
# Verify file exists
ls -l ./areg.init
# Check file has content
cat areg.init | grep "log::"3. Check target is enabled:
log::*::target = file # Must include 'file'
log::*::enable::file = true # Must be true4. Check directory exists:
# If log location is ./logs/app.log
mkdir -p ./logs5. Check file permissions:
# Ensure write permissions
chmod 755 ./logsProblem: Log file created but empty.
Solution:
Check scopes are enabled:
# Verify scopes are not NOTSET
log::*::scope::* = DEBUG | SCOPE # Enable all scopesCheck priority levels:
# If set to ERROR, only errors will log
log::*::scope::* = DEBUG | SCOPE # Change to log everythingVerify logging code:
// Make sure you're actually logging
LOG_DEBUG("This is a debug message");
LOG_INFO("This is an info message");Problem: Application cannot connect to log collector.
Solution:
1. Verify logcollector is running:
# Check process
ps aux | grep logcollector # Linux
tasklist | findstr logcollector # Windows2. Check network connectivity:
telnet 192.168.1.100 8282
# or
nc -zv 192.168.1.100 82823. Verify configuration:
logger::*::connect = tcpip
logger::*::address::tcpip = 192.168.1.100 # Correct address?
logger::*::port::tcpip = 8282 # Correct port?4. Check firewall:
# Linux
sudo ufw allow 8282/tcp
# Windows
New-NetFirewallRule -DisplayName "Log Collector" -Direction Inbound -Protocol TCP -LocalPort 8282 -Action Allow5. Fallback to file logging:
# Enable both remote and file
log::*::target = remote | file
log::*::enable::file = trueProblem: Log file grows too large.
Solution:
1. Reduce log level:
# Change from DEBUG to INFO or WARN
log::*::scope::* = WARN2. Disable scope tracking:
# Remove SCOPE from priorities
log::*::scope::* = WARN # No | SCOPE3. Use separate log files:
# New file per run
log::*::file::location = ./logs/%appname%_%time%.log4. Implement log rotation:
Use external tools:
- Linux:
logrotate - Windows: Task Scheduler + script
5. Disable verbose scopes:
# Most scopes: errors only
log::*::scope::* = ERROR
# Critical scopes only: detailed
log::*::scope::critical_module = DEBUG | SCOPEProblem: Log output shows %d, %m literally.
Solution:
Check layout configuration:
# Wrong (missing %)
log::*::layout::message = d: p: m%n
# Correct
log::*::layout::message = %d: %p: %m%nVerify end-of-line:
# Always include %n at end
log::*::layout::message = %d %p: %m%n
^^Problem: Seeing logs from other applications.
Solution:
Use application-specific configuration:
# Instead of wildcard
log::*::scope::* = DEBUG | SCOPE
# Use application name
log::myapp::scope::* = DEBUG | SCOPEOr use separate configuration files:
// Application A
Application::initApplication(true, true, true, true, false, "./config/appA.init", nullptr);
// Application B
Application::initApplication(true, true, true, true, false, "./config/appB.init", nullptr);Problem: Logs not appearing in Output window.
Solution:
1. Enable debug target:
log::*::target = debug
log::*::enable::debug = true2. Check Output window:
- Open Visual Studio
- View → Output (or Ctrl+Alt+O)
- Select "Debug" from dropdown
3. Verify running in Debug mode:
#ifdef _DEBUG
// Debug output only works in Debug builds
#endif4. Check output window filters:
- Ensure no filters are active in Output window
Related Guides:
- Log Collector Guide - Remote log collection service
- Log Observer Guide - Runtime scope control
- Persistence Syntax - Configuration file format
Configuration Files:
- areg.init - Default configuration
Tools:
-
logcollector- Centralized log collection service -
logobserver- Runtime scope and priority control -
Lusan- GUI log viewer and analysis tool (areg-sdk-tools repo)
Help: For questions, open a discussion or issue on GitHub.
Help us to make docs greater: See something is wrong, unclear or need a help? Submit a change, open a discussion or ask AREG SDK community a question.
Copyright © 2026, Aregtech, www.areg.tech, email: info[at]areg.tech