Ecng.Logging 1.0.108

There is a newer version of this package available.
See the version list below for details.
dotnet add package Ecng.Logging --version 1.0.108
                    
NuGet\Install-Package Ecng.Logging -Version 1.0.108
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Ecng.Logging" Version="1.0.108" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Ecng.Logging" Version="1.0.108" />
                    
Directory.Packages.props
<PackageReference Include="Ecng.Logging" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Ecng.Logging --version 1.0.108
                    
#r "nuget: Ecng.Logging, 1.0.108"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Ecng.Logging@1.0.108
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Ecng.Logging&version=1.0.108
                    
Install as a Cake Addin
#tool nuget:?package=Ecng.Logging&version=1.0.108
                    
Install as a Cake Tool

Ecng.Logging

A flexible and powerful logging framework for .NET applications providing multiple log outputs, severity filtering, and hierarchical log sources.

Table of Contents

Overview

Ecng.Logging provides a comprehensive logging solution with support for multiple output targets (console, file, email, debug output), configurable log levels, hierarchical logging sources, and both synchronous and asynchronous operations.

Key Features

  • Multiple Log Targets: Console, File, Debug Output, Email
  • Severity Filtering: Verbose, Debug, Info, Warning, Error levels
  • Hierarchical Logging: Parent-child log source relationships with inherited settings
  • Async Support: Asynchronous message processing with configurable flush intervals
  • File Management: Rolling file support, date-based separation, compression, and archival
  • Flexible Formatting: Customizable date/time formats
  • Message Filtering: Custom filters for selective message processing
  • Performance Optimized: Lazy message evaluation and efficient batch processing

Getting Started

Basic Setup

using Ecng.Logging;

// Create log manager
var logManager = new LogManager();

// Add console listener
logManager.Listeners.Add(new ConsoleLogListener());

// Get application log source
var log = logManager.Application;

// Write messages
log.LogInfo("Application started");
log.LogWarning("This is a warning");
log.LogError("An error occurred");

Quick Example

// Create and configure logging
var logManager = new LogManager();
logManager.Listeners.Add(new FileLogListener("app.log"));
logManager.Listeners.Add(new ConsoleLogListener());

// Set log level
logManager.Application.LogLevel = LogLevels.Info;

// Log messages
logManager.Application.LogInfo("Processing data...");
logManager.Application.LogWarning("Cache miss detected");
logManager.Application.LogError("Failed to connect: {0}", ex.Message);

// Cleanup
logManager.Dispose();

Core Concepts

ILogSource

The base interface for any object that can produce log messages. Every log source has:

  • Id: Unique identifier
  • Name: Display name for the source
  • Parent: Optional parent source for hierarchical logging
  • LogLevel: Minimum severity level to log
  • IsRoot: Whether this source is a root source
  • Log Event: Raised when a message is logged
public interface ILogSource : IDisposable
{
    Guid Id { get; }
    string Name { get; set; }
    ILogSource Parent { get; set; }
    LogLevels LogLevel { get; set; }
    DateTime CurrentTimeUtc { get; }
    bool IsRoot { get; }
    event Action<LogMessage> Log;
}

ILogReceiver

Extends ILogSource with methods to write log messages at different severity levels.

public interface ILogReceiver : ILogSource
{
    void AddLog(LogMessage message);
    void LogVerbose(string message, params object[] args);
    void LogDebug(string message, params object[] args);
    void LogInfo(string message, params object[] args);
    void LogWarning(string message, params object[] args);
    void LogError(string message, params object[] args);
}

Creating Custom Log Sources

// Using the built-in implementation
var logSource = new LogReceiver("MyComponent");
logSource.LogLevel = LogLevels.Debug;
logSource.LogInfo("Component initialized");

// Creating a custom log receiver
public class MyService : BaseLogReceiver
{
    public MyService()
    {
        Name = "MyService";
        LogLevel = LogLevels.Info;
    }

    public void ProcessData()
    {
        LogDebug("Starting data processing");
        try
        {
            // ... processing logic ...
            LogInfo("Processed {0} records", recordCount);
        }
        catch (Exception ex)
        {
            LogError(ex);
        }
    }
}

Hierarchical Logging

Create parent-child relationships between log sources:

var application = new LogReceiver("MyApp");
application.LogLevel = LogLevels.Info;

var database = new LogReceiver("Database");
database.Parent = application;
database.LogLevel = LogLevels.Inherit; // Inherits Info from parent

var network = new LogReceiver("Network");
network.Parent = application;
network.LogLevel = LogLevels.Debug; // Override to Debug

// Messages propagate up to parent
database.LogInfo("Connection established"); // Will be logged
database.LogDebug("Query executed"); // Won't be logged (level is Info)
network.LogDebug("Packet sent"); // Will be logged (level is Debug)

Log Levels

The framework supports six severity levels plus inheritance:

public enum LogLevels
{
    Inherit,   // Use parent's log level
    Verbose,   // Most detailed: Verbose, Debug, Info, Warning, Error
    Debug,     // Debug, Info, Warning, Error
    Info,      // Info, Warning, Error
    Warning,   // Warning, Error only
    Error,     // Errors only
    Off        // Logging disabled
}

Using Log Levels

var log = new LogReceiver("Service");

// Set minimum level to log
log.LogLevel = LogLevels.Info;

// These will be logged
log.LogInfo("Service started");
log.LogWarning("Low memory detected");
log.LogError("Service failed");

// These will be ignored
log.LogVerbose("Detailed trace information");
log.LogDebug("Variable x = {0}", x);

// Dynamically check effective level
var effectiveLevel = log.GetLogLevel();

Logging Infrastructure

LogManager

The central logging hub that manages log sources and listeners.

public class LogManager : IDisposable
{
    public ILogReceiver Application { get; set; }
    public IList<ILogListener> Listeners { get; }
    public IList<ILogSource> Sources { get; }
    public TimeSpan FlushInterval { get; set; }
    public bool ClearPendingOnDispose { get; set; }
}
Basic Configuration
// Create with async mode (default)
var logManager = new LogManager();

// Or create with synchronous mode
var logManager = new LogManager(asyncMode: false);

// Configure flush interval (async mode only)
logManager.FlushInterval = TimeSpan.FromMilliseconds(200);

// Add listeners
logManager.Listeners.Add(new ConsoleLogListener());
logManager.Listeners.Add(new FileLogListener("app.log"));

// Add custom log sources
var service = new LogReceiver("MyService");
logManager.Sources.Add(service);

// Access application-level logger
logManager.Application.LogInfo("Application initialized");

// Configure behavior on dispose
logManager.ClearPendingOnDispose = true; // Clear pending messages
Global Instance
// LogManager.Instance is automatically set to the first instance created
var logManager = new LogManager();

// Access from anywhere in the application
LogManager.Instance.Application.LogInfo("Global log message");

// Extension method for exceptions
try
{
    // ... code ...
}
catch (Exception ex)
{
    ex.LogError(); // Logs to LogManager.Instance.Application
}

LogMessage

Represents a single log entry.

public class LogMessage
{
    public ILogSource Source { get; set; }
    public DateTime TimeUtc { get; set; }
    public LogLevels Level { get; }
    public string Message { get; }
    public bool IsDispose { get; }
}
Creating Log Messages
// Direct message
var message = new LogMessage(
    source: myLogSource,
    time: DateTime.UtcNow,
    level: LogLevels.Info,
    message: "User logged in",
    args: Array.Empty<object>()
);

// With lazy message evaluation (for expensive operations)
var message = new LogMessage(
    source: myLogSource,
    time: DateTime.UtcNow,
    level: LogLevels.Debug,
    getMessage: () => GenerateExpensiveDebugInfo()
);

// Using extension methods (recommended)
receiver.AddInfoLog("Processing {0} items", count);
receiver.AddErrorLog(exception);

Log Listeners

Console Listener

Outputs log messages to the console with colored output.

var consoleListener = new ConsoleLogListener();
consoleListener.IsLocalTime = true; // Convert UTC to local time
consoleListener.TimeFormat = "HH:mm:ss.fff";
consoleListener.DateFormat = "yyyy/MM/dd";

logManager.Listeners.Add(consoleListener);

// Output format:
// 2025/12/20 14:30:45.123 | MyService      | User logged in

File Listener

Writes log messages to text files with extensive configuration options.

Basic File Logging
// Log to a single file
var fileListener = new FileLogListener("application.log");
logManager.Listeners.Add(fileListener);
Advanced File Configuration
var fileListener = new FileLogListener();

// Basic settings
fileListener.FileName = "app";
fileListener.Extension = ".log";
fileListener.LogDirectory = @"C:\Logs";
fileListener.Append = true;

// Encoding
fileListener.Encoding = Encoding.UTF8;

// Time formatting
fileListener.IsLocalTime = true;
fileListener.TimeFormat = "HH:mm:ss.fff";
fileListener.DateFormat = "yyyy/MM/dd";

// Include source ID in logs
fileListener.WriteSourceId = true;

// Child data handling
fileListener.WriteChildDataToRootFile = true;

logManager.Listeners.Add(fileListener);
Rolling Files

Automatically create new files when size limit is reached:

var fileListener = new FileLogListener("app.log");

// Enable rolling when file reaches 10 MB
fileListener.MaxLength = 10 * 1024 * 1024; // 10 MB

// Keep only the last 5 rolled files
fileListener.MaxCount = 5;

logManager.Listeners.Add(fileListener);

// Creates: app.log, app.1.log, app.2.log, app.3.log, app.4.log, app.5.log
// Oldest files are deleted when MaxCount is reached
Date-Based File Separation
var fileListener = new FileLogListener();
fileListener.FileName = "app";
fileListener.LogDirectory = @"C:\Logs";

// Option 1: Separate by filename
fileListener.SeparateByDates = SeparateByDateModes.FileName;
fileListener.DirectoryDateFormat = "yyyy_MM_dd";
// Creates: app.log, 2025_12_20_app.log, 2025_12_21_app.log, etc.

// Option 2: Separate by subdirectories
fileListener.SeparateByDates = SeparateByDateModes.SubDirectories;
fileListener.DirectoryDateFormat = "yyyy_MM_dd";
// Creates: C:\Logs\2025_12_20\app.log, C:\Logs\2025_12_21\app.log, etc.

logManager.Listeners.Add(fileListener);
Log History Management

Automatically manage old log files:

var fileListener = new FileLogListener();
fileListener.SeparateByDates = SeparateByDateModes.SubDirectories;

// Delete logs older than 7 days
fileListener.HistoryPolicy = FileLogHistoryPolicies.Delete;
fileListener.HistoryAfter = TimeSpan.FromDays(7);

// Or compress logs older than 7 days
fileListener.HistoryPolicy = FileLogHistoryPolicies.Compression;
fileListener.HistoryAfter = TimeSpan.FromDays(7);
fileListener.HistoryCompressionLevel = CompressionLevel.Optimal;

// Or move logs to archive directory
fileListener.HistoryPolicy = FileLogHistoryPolicies.Move;
fileListener.HistoryAfter = TimeSpan.FromDays(7);
fileListener.HistoryMove = @"C:\Archive\Logs";

logManager.Listeners.Add(fileListener);

Debug Listener

Outputs to the debug window (System.Diagnostics.Trace).

var debugListener = new DebugLogListener();
logManager.Listeners.Add(debugListener);

// Messages appear in Visual Studio Output window or other debug output viewers

Email Listener

Sends log messages via email (typically for critical errors).

public class CustomEmailListener : EmailLogListener
{
    protected override SmtpClient CreateClient()
    {
        return new SmtpClient("smtp.example.com", 587)
        {
            Credentials = new NetworkCredential("user@example.com", "password"),
            EnableSsl = true
        };
    }
}

var emailListener = new CustomEmailListener();
emailListener.From = "app@example.com";
emailListener.To = "admin@example.com";

// Add filter to only send errors
emailListener.Filters.Add(LoggingHelper.OnlyError);

logManager.Listeners.Add(emailListener);

Custom Listener

Create custom log listeners:

// Synchronous listener
public class DatabaseLogListener : LogListener
{
    private readonly string _connectionString;

    public DatabaseLogListener(string connectionString)
    {
        _connectionString = connectionString;
    }

    protected override void OnWriteMessage(LogMessage message)
    {
        using var connection = new SqlConnection(_connectionString);
        using var command = connection.CreateCommand();

        command.CommandText =
            "INSERT INTO Logs (TimeUtc, Level, Source, Message) " +
            "VALUES (@Time, @Level, @Source, @Message)";

        command.Parameters.AddWithValue("@Time", message.TimeUtc);
        command.Parameters.AddWithValue("@Level", message.Level.ToString());
        command.Parameters.AddWithValue("@Source", message.Source.Name);
        command.Parameters.AddWithValue("@Message", message.Message);

        connection.Open();
        command.ExecuteNonQuery();
    }
}

// Asynchronous listener
public class AsyncDatabaseLogListener : LogListener
{
    private readonly string _connectionString;

    public AsyncDatabaseLogListener(string connectionString)
    {
        _connectionString = connectionString;
    }

    protected override async ValueTask OnWriteMessagesAsync(
        IEnumerable<LogMessage> messages,
        CancellationToken cancellationToken = default)
    {
        using var connection = new SqlConnection(_connectionString);
        await connection.OpenAsync(cancellationToken);

        foreach (var message in messages)
        {
            using var command = connection.CreateCommand();
            command.CommandText =
                "INSERT INTO Logs (TimeUtc, Level, Source, Message) " +
                "VALUES (@Time, @Level, @Source, @Message)";

            command.Parameters.AddWithValue("@Time", message.TimeUtc);
            command.Parameters.AddWithValue("@Level", message.Level.ToString());
            command.Parameters.AddWithValue("@Source", message.Source.Name);
            command.Parameters.AddWithValue("@Message", message.Message);

            await command.ExecuteNonQueryAsync(cancellationToken);
        }
    }
}

Advanced Features

Message Filtering

Filter messages before they are processed:

var fileListener = new FileLogListener("errors.log");

// Only log errors
fileListener.Filters.Add(LoggingHelper.OnlyError);

// Only log warnings
fileListener.Filters.Add(LoggingHelper.OnlyWarning);

// Custom filter
fileListener.Filters.Add(msg =>
    msg.Source.Name.StartsWith("Database") &&
    msg.Level >= LogLevels.Warning
);

// Multiple filters (OR logic - any filter that returns true)
fileListener.Filters.Add(LoggingHelper.OnlyError);
fileListener.Filters.Add(LoggingHelper.OnlyWarning);
// Logs warnings OR errors

logManager.Listeners.Add(fileListener);

Lazy Message Evaluation

Avoid expensive string operations when messages won't be logged:

// Bad: String is always formatted, even if not logged
log.LogDebug(string.Format("Data: {0}", ExpensiveOperation()));

// Good: Only evaluated if debug logging is enabled
log.AddDebugLog(() => $"Data: {ExpensiveOperation()}");

// Also good: Uses extension method with format args
log.LogDebug("Data: {0}", ExpensiveOperation());

// Best: Check level first for very expensive operations
if (log.LogLevel <= LogLevels.Debug)
{
    var data = VeryExpensiveOperation();
    log.LogDebug("Complex data: {0}", data);
}

Error Handling Helpers

Wrap operations with automatic error logging:

// Synchronous
Action action = () => RiskyOperation();
action.DoWithLog(); // Logs exception if thrown

Func<int> func = () => GetValue();
int result = func.DoWithLog(); // Returns default(int) on exception

// Asynchronous
Func<CancellationToken, Task> asyncAction =
    async ct => await RiskyAsyncOperation(ct);
await asyncAction.DoWithLogAsync();

Func<CancellationToken, Task<string>> asyncFunc =
    async ct => await GetValueAsync(ct);
string result = await asyncFunc.DoWithLogAsync();

// Direct exception logging
try
{
    DangerousOperation();
}
catch (Exception ex)
{
    ex.LogError(); // Logs to LogManager.Instance.Application
    ex.LogError("Custom format: {0}"); // With custom message
}

Multiple Listeners with Different Levels

var logManager = new LogManager();
var service = new LogReceiver("MyService");
logManager.Sources.Add(service);

// Console: Only errors and warnings
var consoleListener = new ConsoleLogListener();
consoleListener.Filters.Add(msg =>
    msg.Level >= LogLevels.Warning
);
logManager.Listeners.Add(consoleListener);

// File: Everything at Info and above
var fileListener = new FileLogListener("app.log");
logManager.Listeners.Add(fileListener);

// Email: Only critical errors
var emailListener = new CustomEmailListener
{
    From = "app@example.com",
    To = "admin@example.com"
};
emailListener.Filters.Add(LoggingHelper.OnlyError);
logManager.Listeners.Add(emailListener);

service.LogLevel = LogLevels.Info;
service.LogInfo("Info message");      // File only
service.LogWarning("Warning");        // Console + File
service.LogError("Critical error");   // Console + File + Email

Per-Source File Logging

// Create listener without specific filename
var fileListener = new FileLogListener();
fileListener.LogDirectory = @"C:\Logs";
fileListener.WriteChildDataToRootFile = false; // Each source gets own file

logManager.Listeners.Add(fileListener);

// Each source creates its own log file
var database = new LogReceiver("Database");
var network = new LogReceiver("Network");
var cache = new LogReceiver("Cache");

logManager.Sources.Add(database);
logManager.Sources.Add(network);
logManager.Sources.Add(cache);

// Creates: C:\Logs\Database.txt, C:\Logs\Network.txt, C:\Logs\Cache.txt

database.LogInfo("Connection opened");  // -> Database.txt
network.LogInfo("Request sent");        // -> Network.txt
cache.LogInfo("Cache hit");             // -> Cache.txt

Configuration

Saving and Loading Configuration

// Save configuration
var storage = new SettingsStorage();
logManager.Save(storage);
var json = storage.Serialize(); // Serialize to JSON or other format

// Load configuration
var storage = SettingsStorage.Deserialize(json);
var logManager = new LogManager();
logManager.Load(storage);

Example Configuration

var logManager = new LogManager();

// Application logger
logManager.Application.Name = "MyApplication";
logManager.Application.LogLevel = LogLevels.Info;

// Console listener
var consoleListener = new ConsoleLogListener
{
    IsLocalTime = true,
    TimeFormat = "HH:mm:ss",
    DateFormat = "yyyy-MM-dd"
};
logManager.Listeners.Add(consoleListener);

// File listener with rolling
var fileListener = new FileLogListener
{
    FileName = "app",
    Extension = ".log",
    LogDirectory = @"C:\Logs",
    MaxLength = 10 * 1024 * 1024, // 10 MB
    MaxCount = 10,
    SeparateByDates = SeparateByDateModes.SubDirectories,
    DirectoryDateFormat = "yyyy_MM_dd",
    HistoryPolicy = FileLogHistoryPolicies.Compression,
    HistoryAfter = TimeSpan.FromDays(30),
    HistoryCompressionLevel = CompressionLevel.Optimal,
    IsLocalTime = true
};
logManager.Listeners.Add(fileListener);

// Flush configuration
logManager.FlushInterval = TimeSpan.FromMilliseconds(500);

Best Practices

1. Use Appropriate Log Levels

// Verbose: Extremely detailed trace information
log.LogVerbose("Loop iteration {0}, variable state: {1}", i, state);

// Debug: Diagnostic information useful for debugging
log.LogDebug("Cache miss for key: {0}", key);

// Info: General informational messages
log.LogInfo("Service started successfully");

// Warning: Potentially harmful situations
log.LogWarning("Retry attempt {0} of {1}", attempt, maxAttempts);

// Error: Error events that might still allow the application to continue
log.LogError("Failed to process record {0}: {1}", id, ex.Message);

2. Use Hierarchical Logging

var app = new LogReceiver("Application");
app.LogLevel = LogLevels.Info;

var dataLayer = new LogReceiver("DataLayer") { Parent = app };
var businessLayer = new LogReceiver("BusinessLayer") { Parent = app };
var apiLayer = new LogReceiver("ApiLayer") { Parent = app };

// Override level for specific component
dataLayer.LogLevel = LogLevels.Debug;

// All inherit Info except dataLayer (Debug)

3. Dispose Properly

// Use using statement
using (var logManager = new LogManager())
{
    logManager.Listeners.Add(new FileLogListener("app.log"));
    logManager.Application.LogInfo("Application started");

    // ... application logic ...

} // Automatically flushes and disposes

// Or dispose explicitly
var logManager = new LogManager();
try
{
    // ... use logger ...
}
finally
{
    logManager.Dispose(); // Ensures all messages are flushed
}

4. Avoid String Concatenation in Log Calls

// Bad: String is always created
log.LogInfo("Processing " + count + " items at " + DateTime.Now);

// Good: Uses format string (only formatted if logged)
log.LogInfo("Processing {0} items at {1}", count, DateTime.Now);

// Better: For expensive operations
if (log.LogLevel <= LogLevels.Info)
{
    log.LogInfo("Processing {0} items at {1}", count, DateTime.Now);
}

5. Use Filters Wisely

// Create specialized listeners
var errorFileListener = new FileLogListener("errors.log");
errorFileListener.Filters.Add(LoggingHelper.OnlyError);

var warningFileListener = new FileLogListener("warnings.log");
warningFileListener.Filters.Add(LoggingHelper.OnlyWarning);

var allFileListener = new FileLogListener("all.log");
// No filters - logs everything

logManager.Listeners.Add(errorFileListener);
logManager.Listeners.Add(warningFileListener);
logManager.Listeners.Add(allFileListener);

6. Configure for Production

#if DEBUG
    logManager.Application.LogLevel = LogLevels.Debug;
    logManager.Listeners.Add(new ConsoleLogListener());
    logManager.Listeners.Add(new DebugLogListener());
#else
    logManager.Application.LogLevel = LogLevels.Info;

    var fileListener = new FileLogListener
    {
        FileName = "production",
        LogDirectory = @"C:\ProgramData\MyApp\Logs",
        MaxLength = 50 * 1024 * 1024, // 50 MB
        MaxCount = 20,
        SeparateByDates = SeparateByDateModes.SubDirectories,
        HistoryPolicy = FileLogHistoryPolicies.Compression,
        HistoryAfter = TimeSpan.FromDays(90)
    };
    logManager.Listeners.Add(fileListener);
#endif

7. Thread Safety

The framework is thread-safe. Multiple threads can log simultaneously:

var logManager = new LogManager();
var log = logManager.Application;

// Safe to call from multiple threads
Parallel.For(0, 100, i =>
{
    log.LogInfo("Processing item {0} on thread {1}",
        i, Thread.CurrentThread.ManagedThreadId);
});

8. Monitor Performance

// Async mode with appropriate flush interval
var logManager = new LogManager(asyncMode: true);
logManager.FlushInterval = TimeSpan.FromMilliseconds(500); // Adjust as needed

// For high-volume logging, increase flush interval
logManager.FlushInterval = TimeSpan.FromSeconds(1);

// For low-latency requirements, decrease flush interval
logManager.FlushInterval = TimeSpan.FromMilliseconds(100);

// For maximum performance, use synchronous mode only for low-volume scenarios
var syncLogManager = new LogManager(asyncMode: false);

License

This is part of the Ecng framework. Refer to the project root for license information.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (4)

Showing the top 4 NuGet packages that depend on Ecng.Logging:

Package Downloads
StockSharp.Messages

Trading messages (register order, cancel order, subscribe market data etc.). More info on web site https://stocksharp.com/store/

StockSharp.Web.Api.Client

StockSharp WebApi

Ecng.Nuget

Ecng system framework

Ecng.Server.Utils

Ecng system framework

GitHub repositories (1)

Showing the top 1 popular GitHub repositories that depend on Ecng.Logging:

Repository Stars
StockSharp/StockSharp
Algorithmic trading and quantitative trading open source platform to develop trading robots (stock markets, forex, crypto, bitcoins, and options).
Version Downloads Last Updated
1.0.116 37 12/26/2025
1.0.115 35 12/26/2025
1.0.114 32 12/26/2025
1.0.113 54 12/26/2025
1.0.112 123 12/25/2025
1.0.111 122 12/25/2025
1.0.110 167 12/24/2025
1.0.109 184 12/22/2025
1.0.108 201 12/21/2025
1.0.107 286 12/19/2025
1.0.106 276 12/19/2025
1.0.105 362 12/17/2025
1.0.104 364 12/15/2025
1.0.103 286 12/15/2025
1.0.102 294 12/15/2025
1.0.101 260 12/14/2025
1.0.100 195 12/14/2025
1.0.99 195 12/13/2025
1.0.98 202 12/13/2025
1.0.97 193 12/12/2025
1.0.96 159 12/12/2025
1.0.95 151 12/12/2025
1.0.94 146 12/12/2025
1.0.93 157 12/12/2025
1.0.92 161 12/12/2025
1.0.91 153 12/12/2025
1.0.90 835 12/2/2025
1.0.89 722 12/2/2025
1.0.88 726 12/2/2025
1.0.87 333 11/30/2025
1.0.86 186 11/29/2025
1.0.85 183 11/28/2025
1.0.84 196 11/28/2025
1.0.83 246 11/27/2025
1.0.82 333 11/24/2025
1.0.81 246 11/24/2025
1.0.80 254 11/23/2025
1.0.79 225 11/23/2025
1.0.78 301 11/22/2025
1.0.77 1,005 11/20/2025
1.0.76 504 11/18/2025
1.0.75 453 11/18/2025
1.0.74 435 11/13/2025
1.0.73 346 11/10/2025
1.0.72 1,184 11/1/2025
1.0.71 330 10/28/2025
1.0.70 306 10/27/2025
1.0.69 245 10/27/2025
1.0.68 191 10/25/2025
1.0.67 222 10/24/2025
1.0.66 416 10/20/2025
1.0.65 433 10/12/2025
1.0.64 200 10/11/2025
1.0.63 488 10/7/2025
1.0.62 340 10/6/2025
1.0.61 494 10/3/2025
1.0.60 332 10/1/2025
1.0.59 239 10/1/2025
1.0.58 261 9/30/2025
1.0.57 284 9/28/2025
1.0.56 314 9/25/2025
1.0.55 3,611 9/5/2025
1.0.54 293 9/2/2025
1.0.53 2,120 8/30/2025
1.0.52 298 8/30/2025
1.0.51 341 8/20/2025
1.0.50 239 8/20/2025
1.0.49 255 8/19/2025
1.0.48 293 8/15/2025
1.0.47 4,771 7/16/2025
1.0.46 1,039 7/14/2025
1.0.45 285 7/13/2025
1.0.44 234 7/13/2025
1.0.43 230 7/12/2025
1.0.42 1,496 7/8/2025
1.0.41 897 7/4/2025
1.0.40 264 7/2/2025
1.0.39 1,074 6/24/2025
1.0.38 3,877 6/16/2025
1.0.37 397 6/9/2025
1.0.36 354 6/8/2025
1.0.35 1,407 5/21/2025
1.0.34 274 5/21/2025
1.0.33 280 5/17/2025
1.0.32 1,448 5/12/2025
1.0.31 315 5/12/2025
1.0.30 323 5/12/2025
1.0.29 237 5/11/2025
1.0.28 232 5/11/2025
1.0.27 171 5/10/2025
1.0.26 174 5/10/2025
1.0.25 239 5/3/2025
1.0.24 379 4/17/2025
1.0.23 355 4/15/2025
1.0.22 238 4/12/2025
1.0.21 309 4/9/2025
1.0.20 3,565 3/22/2025
1.0.19 268 3/20/2025
1.0.18 233 3/20/2025
1.0.17 267 3/19/2025
1.0.16 2,298 2/26/2025
1.0.15 250 2/26/2025
1.0.14 2,429 2/12/2025
1.0.13 258 2/8/2025
1.0.12 257 2/8/2025
1.0.11 244 2/8/2025
1.0.10 252 2/6/2025
1.0.9 211 2/6/2025
1.0.8 218 2/6/2025
1.0.7 261 2/6/2025
1.0.6 215 2/6/2025
1.0.5 2,571 2/5/2025
1.0.4 239 2/5/2025
1.0.3 217 2/5/2025
1.0.2 229 2/4/2025
1.0.1 676 2/4/2025
1.0.0 178 2/4/2025

Added comprehensive README.md documentation for all projects