diff --git a/examples/Logging/Program.cs b/examples/Logging/Program.cs index 4cba6c0..68b3da7 100644 --- a/examples/Logging/Program.cs +++ b/examples/Logging/Program.cs @@ -12,6 +12,7 @@ using Iceoryx2; using System; +using System.IO; class Program { @@ -34,9 +35,9 @@ static void Main(string[] args) Console.WriteLine("Usage: dotnet run [basic|custom|file]"); Console.WriteLine(); Console.WriteLine("Examples:"); - Console.WriteLine(" dotnet run basic - Use console logger with environment variable"); + Console.WriteLine(" dotnet run basic - Use default console logger with environment variable"); Console.WriteLine(" dotnet run custom - Use custom logger callback"); - Console.WriteLine(" dotnet run file - Use file logger"); + Console.WriteLine(" dotnet run file - Use custom file logger (via SetLogger callback)"); } } @@ -44,16 +45,12 @@ static void RunBasicLoggingExample() { Console.WriteLine("=== Basic Logging Example ==="); Console.WriteLine(); + Console.WriteLine("Note: Starting with iceoryx2 v0.8.0, the console logger is enabled by default."); + Console.WriteLine(); // Set log level from environment variable IOX2_LOG_LEVEL (or default to Info) Iox2Log.SetLogLevelFromEnvOrDefault(); - // Use the built-in console logger - if (Iox2Log.UseConsoleLogger()) - { - Console.WriteLine("Console logger initialized successfully"); - } - Console.WriteLine($"Current log level: {Iox2Log.GetLogLevel()}"); Console.WriteLine(); @@ -151,25 +148,57 @@ static void RunCustomLoggerExample() static void RunFileLoggerExample() { - Console.WriteLine("=== File Logger Example ==="); + Console.WriteLine("=== File Logger Example (via Custom Logger) ==="); + Console.WriteLine(); + Console.WriteLine("Note: Starting with iceoryx2 v0.8.0, file logging requires rebuilding"); + Console.WriteLine("iceoryx2 with specific feature flags. This example demonstrates"); + Console.WriteLine("implementing file logging using a custom logger callback instead."); Console.WriteLine(); var logFile = "/tmp/iceoryx2_csharp.log"; - // Use file logger - if (Iox2Log.UseFileLogger(logFile)) + // Create or truncate the log file + using (var writer = new StreamWriter(logFile, append: false)) + { + writer.WriteLine($"=== iceoryx2 Log File - Started at {DateTime.Now:yyyy-MM-dd HH:mm:ss} ==="); + } + + // Use a custom logger that writes to file + var success = Iox2Log.SetLogger((level, origin, message) => + { + var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"); + var levelStr = level.ToString().ToUpper().PadRight(5); + var logLine = string.IsNullOrEmpty(origin) + ? $"[{timestamp}] [{levelStr}] {message}" + : $"[{timestamp}] [{levelStr}] {origin} - {message}"; + + // Write to file + try + { + File.AppendAllText(logFile, logLine + Environment.NewLine); + } + catch (Exception ex) + { + Console.Error.WriteLine($"Failed to write to log file: {ex.Message}"); + } + + // Also write to console for visibility + Console.WriteLine(logLine); + }); + + if (success) { - Console.WriteLine($"File logger initialized: {logFile}"); + Console.WriteLine($"Custom file logger initialized: {logFile}"); } else { - Console.WriteLine("Failed to initialize file logger"); + Console.WriteLine("Failed to set custom logger (may have been set already)"); return; } // Set log level Iox2Log.SetLogLevel(LogLevel.Debug); - Console.WriteLine($"Iox2Log level set to: {Iox2Log.GetLogLevel()}"); + Console.WriteLine($"Log level set to: {Iox2Log.GetLogLevel()}"); Console.WriteLine(); // Write some log messages @@ -180,6 +209,7 @@ static void RunFileLoggerExample() Iox2Log.Write(LogLevel.Error, "FileLogging", "Error message to file"); // Create a node to generate library logs + Console.WriteLine(); Console.WriteLine("Creating iceoryx2 node (logs will be written to file)..."); var node = NodeBuilder.New() .Name("file_logging_example") diff --git a/examples/Logging/README.md b/examples/Logging/README.md index d5b8c22..6fd62a3 100644 --- a/examples/Logging/README.md +++ b/examples/Logging/README.md @@ -2,10 +2,36 @@ This example demonstrates how to use the iceoryx2 logging functionality in C#. +## Logging Backend Changes in v0.8.0 + +Starting with iceoryx2 v0.8.0, the logging backend has changed: + +* **Console logger is now enabled by default** - No explicit initialization required +* **File logger requires rebuilding iceoryx2** with specific feature flags +* **Custom loggers** can be set at runtime using `SetLogger()` + +### Available Loggers (via feature flags on iceoryx2-loggers crate) + +1. **console** - outputs log messages to the console (default) +2. **buffer** - outputs log messages to a buffer +3. **file** - outputs log messages to a file +4. **log** - utilizes the `log` crate +5. **tracing** - utilizes the `tracing` crate + +### Enabling File Logger + +To use the native file logger, rebuild iceoryx2 with: + +```bash +cargo build --package iceoryx2-ffi-c --features iceoryx2-loggers/std --features iceoryx2-loggers/file --no-default-features --release +``` + +Alternatively, use a custom logger callback (demonstrated in this example). + ## Features -* **Console Logging**: Use the built-in console logger -* **File Logging**: Write logs to a file +* **Console Logging**: Enabled by default in iceoryx2 v0.8.0+ +* **Custom File Logging**: Implement file logging via custom logger callback * **Custom Logger**: Implement custom log formatting and handling * **Log Levels**: Control verbosity with log levels (Trace, Debug, Info, Warn, Error, Fatal) @@ -16,20 +42,20 @@ This example demonstrates how to use the iceoryx2 logging functionality in C#. ### Basic Console Logging ```bash -dotnet run basic +dotnet run --framework net9.0 -- basic ``` This example shows: * Setting log level from environment variable -* Using the console logger +* Using the default console logger (enabled automatically in v0.8.0+) * Writing messages at different log levels * Seeing library-generated logs ### Custom Logger with Color ```bash -dotnet run custom +dotnet run --framework net9.0 -- custom ``` This example demonstrates: @@ -38,16 +64,17 @@ This example demonstrates: * Adding timestamps and colored output * Formatting log messages -### File Logging +### File Logging (via Custom Logger) ```bash -dotnet run file +dotnet run --framework net9.0 -- file ``` This example shows: +* Implementing file logging using a custom logger callback * Writing logs to a file (`/tmp/iceoryx2_csharp.log`) -* Viewing library logs in the file +* Viewing library logs in both console and file ## Log Levels @@ -67,66 +94,71 @@ Set the log level using the `IOX2_LOG_LEVEL` environment variable: ```bash # Set to Debug level export IOX2_LOG_LEVEL=DEBUG -dotnet run basic +dotnet run --framework net9.0 -- basic # Set to Trace level (most verbose) export IOX2_LOG_LEVEL=TRACE -dotnet run basic +dotnet run --framework net9.0 -- basic # Set to Warn level (less verbose) export IOX2_LOG_LEVEL=WARN -dotnet run basic +dotnet run --framework net9.0 -- basic ``` ## API Usage -### Basic Logging +### Basic Logging (v0.8.0+) ```csharp using Iceoryx2; -// Use console logger -Log.UseConsoleLogger(); +// Console logger is enabled by default - no initialization needed! // Set log level -Log.SetLogLevel(LogLevel.Debug); +Iox2Log.SetLogLevel(LogLevel.Debug); // Write log message -Log.Write(LogLevel.Info, "MyApp", "Application started"); +Iox2Log.Write(LogLevel.Info, "MyApp", "Application started"); ``` ### Environment-based Configuration ```csharp // Set log level from IOX2_LOG_LEVEL environment variable, default to Info -Log.SetLogLevelFromEnvOrDefault(); +Iox2Log.SetLogLevelFromEnvOrDefault(); // Or with custom default -Log.SetLogLevelFromEnvOr(LogLevel.Debug); +Iox2Log.SetLogLevelFromEnvOr(LogLevel.Debug); ``` ### Custom Logger ```csharp -// Set custom logger (can only be called once) -bool success = Log.SetLogger((level, origin, message) => +// Set custom logger (can only be called once, before any log messages) +bool success = Iox2Log.SetLogger((level, origin, message) => { Console.WriteLine($"[{level}] {origin}: {message}"); }); ``` -### File Logger +### Custom File Logger ```csharp -// Write logs to file -Log.UseFileLogger("/tmp/myapp.log"); -Log.Write(LogLevel.Info, "MyApp", "This goes to the file"); +// Implement file logging via custom logger callback +Iox2Log.SetLogger((level, origin, message) => +{ + var logLine = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] [{level}] {message}"; + File.AppendAllText("/tmp/myapp.log", logLine + Environment.NewLine); +}); +Iox2Log.Write(LogLevel.Info, "MyApp", "This goes to the file"); ``` ## Notes -* The custom logger can only be set once and must be set before any log messages +* The console logger is enabled by default in iceoryx2 v0.8.0+ +* Custom loggers can only be set once and must be set before any log messages are created -* The built-in loggers (console/file) handle this restriction automatically * Library-generated logs (from iceoryx2 itself) will use the configured logger * Origin can be null or empty if not needed +* For native file logging support, rebuild iceoryx2 with the appropriate + feature flags diff --git a/examples/LoggingIntegration/README.md b/examples/LoggingIntegration/README.md index d8b561e..a29dc19 100644 --- a/examples/LoggingIntegration/README.md +++ b/examples/LoggingIntegration/README.md @@ -4,6 +4,11 @@ This example demonstrates how to integrate iceoryx2's internal logging with the Microsoft.Extensions.Logging framework, allowing you to see iceoryx2's debug logs through your existing logging infrastructure. +> **Note:** Starting with iceoryx2 v0.8.0, the console logger is enabled by +> default. The integration examples in this project use `SetLogger()` to +> redirect logs to Microsoft.Extensions.Logging, which continues to work +> as before. + ## Features The example showcases **4 different logging approaches**: diff --git a/iceoryx2 b/iceoryx2 index d746214..1979e6e 160000 --- a/iceoryx2 +++ b/iceoryx2 @@ -1 +1 @@ -Subproject commit d7462142e4fc15ec3dce5387dfa31dfe5acaadf0 +Subproject commit 1979e6edf2316ebe7b30751c7172972ed3452c5b diff --git a/src/Iceoryx2/Iox2Log.cs b/src/Iceoryx2/Iox2Log.cs index 4fadba9..6c48041 100644 --- a/src/Iceoryx2/Iox2Log.cs +++ b/src/Iceoryx2/Iox2Log.cs @@ -18,26 +18,45 @@ namespace Iceoryx2; /// /// Provides logging functionality for iceoryx2. -/// Allows configuration of log levels, custom loggers, and built-in file/console logging. +/// Allows configuration of log levels, custom loggers, and built-in console/file logging. /// +/// +/// +/// Starting with iceoryx2 v0.8.0, the console logger is enabled by default. +/// The file logger requires rebuilding iceoryx2 with specific feature flags. +/// +/// +/// Available loggers (configured via feature flags on iceoryx2-loggers crate): +/// +/// console - outputs to console (default) +/// buffer - outputs to a buffer +/// file - outputs to a file (requires rebuild with features) +/// log - utilizes the log crate +/// tracing - utilizes the tracing crate +/// +/// +/// +/// To enable the file logger, rebuild iceoryx2 with: +/// +/// cargo build --package iceoryx2-ffi-c --features iceoryx2-loggers/std --features iceoryx2-loggers/file --no-default-features --release +/// +/// +/// +/// Supported log levels: trace, debug, info, warning, error, fatal +/// +/// /// /// /// // Set log level from environment variable IOX2_LOG_LEVEL, default to Info /// Iox2Log.SetLogLevelFromEnvOrDefault(); -/// +/// /// // Or set specific log level /// Iox2Log.SetLogLevel(LogLevel.Debug); -/// -/// // Use console logger -/// Iox2Log.UseConsoleLogger(); -/// -/// // Or use file logger -/// Iox2Log.UseFileLogger("/tmp/iceoryx2.log"); -/// +/// /// // Manual logging /// Iox2Log.Write(LogLevel.Info, "MyApp", "Application started"); -/// -/// // Custom logger +/// +/// // Custom logger (set at runtime, must be done before any log messages) /// Iox2Log.SetLogger((level, origin, message) => /// { /// Console.WriteLine($"[{level}] {origin}: {message}"); @@ -81,26 +100,62 @@ public static void Write(LogLevel logLevel, string? origin, string message) /// /// Sets the console logger as the default logger. /// - /// True if the logger was set successfully, false otherwise + /// + /// + /// Starting with iceoryx2 v0.8.0, the console logger is enabled by default. + /// This method is now a no-op and always returns true for backward compatibility. + /// + /// + /// To use a different logger backend, you can either: + /// + /// Use to set a custom logger callback at runtime + /// Rebuild iceoryx2 with different feature flags (e.g., file, log, tracing) + /// + /// + /// + /// Always returns true as the console logger is enabled by default + [Obsolete("Console logger is now enabled by default in iceoryx2 v0.8.0+. This method is a no-op.")] public static bool UseConsoleLogger() { - return Iox2NativeMethods.iox2_use_console_logger(); + // Console logger is now enabled by default in iceoryx2 v0.8.0+ + // This method is kept for backward compatibility + return true; } /// /// Sets the file logger as the default logger. /// + /// + /// + /// Starting with iceoryx2 v0.8.0, the file logger requires rebuilding the iceoryx2 native library + /// with specific feature flags. This method will throw if the + /// native library was not built with file logger support. + /// + /// + /// To enable file logging, rebuild iceoryx2 with: + /// + /// cargo build --package iceoryx2-ffi-c --features iceoryx2-loggers/std --features iceoryx2-loggers/file --no-default-features --release + /// + /// + /// + /// Alternative: Use to implement custom file logging at runtime. + /// + /// /// Path to the log file /// True if the logger was set successfully, false otherwise + /// + /// Thrown when the native library was not built with file logger support. + /// + [Obsolete("File logger requires rebuilding iceoryx2 with --features iceoryx2-loggers/file. Consider using SetLogger() for custom file logging.")] public static bool UseFileLogger(string logFile) { - unsafe - { - fixed (byte* logFilePtr = System.Text.Encoding.UTF8.GetBytes(logFile + "\0")) - { - return Iox2NativeMethods.iox2_use_file_logger((IntPtr)logFilePtr); - } - } + // File logger requires rebuilding iceoryx2 with specific feature flags in v0.8.0+ + // The native function iox2_use_file_logger has been removed from default builds + throw new NotSupportedException( + "File logger is not available in the default iceoryx2 build. " + + "To enable file logging, either:\n" + + "1. Rebuild iceoryx2 with: cargo build --package iceoryx2-ffi-c --features iceoryx2-loggers/std --features iceoryx2-loggers/file --no-default-features --release\n" + + "2. Use Iox2Log.SetLogger() to implement custom file logging at runtime."); } /// diff --git a/src/Iceoryx2/Native/Iox2NativeMethods.cs b/src/Iceoryx2/Native/Iox2NativeMethods.cs index 8c74cac..43e150d 100644 --- a/src/Iceoryx2/Native/Iox2NativeMethods.cs +++ b/src/Iceoryx2/Native/Iox2NativeMethods.cs @@ -1183,13 +1183,8 @@ internal static extern int iox2_pending_response_receive( [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)] internal static extern void iox2_log(iox2_log_level_e log_level, IntPtr origin, IntPtr message); - [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)] - [return: MarshalAs(UnmanagedType.U1)] - internal static extern bool iox2_use_console_logger(); - - [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)] - [return: MarshalAs(UnmanagedType.U1)] - internal static extern bool iox2_use_file_logger(IntPtr log_file); + // Note: iox2_use_console_logger() was removed in iceoryx2 v0.8.0 - console logger is now the default + // Note: iox2_use_file_logger() was removed in iceoryx2 v0.8.0 - requires rebuild with --features iceoryx2-loggers/file [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)] internal static extern void iox2_set_log_level_from_env_or_default();