### Setup ZLogger with LoggerFactory Source: https://github.com/cysharp/zlogger/blob/master/README.md Illustrates how to manually configure and create a LoggerFactory with ZLogger, setting the minimum log level and adding the console provider. ```csharp using Microsoft.Extensions.Logging; using ZLogger; using var factory = LoggerFactory.Create(logging => { logging.SetMinimumLevel(LogLevel.Trace); // Add ZLogger provider to ILoggingBuilder logging.AddZLoggerConsole(); // Output Structured Logging, setup options // logging.AddZLoggerConsole(options => options.UseJsonFormatter()); }); var logger = factory.CreateLogger("Program"); var name = "John"; var age = 33; // Use **Z**Log method and string interpolation to log message logger.ZLogInformation($"Hello my name is {name}, {age} years old."); ``` -------------------------------- ### Asynchronous Producer-Consumer Example Source: https://github.com/cysharp/zlogger/blob/master/src/ZLogger.Unity/Assets/Packages/System.Threading.Channels.8.0.0/PACKAGE.md Demonstrates a basic producer-consumer pattern using an unbounded channel. The producer writes integers to the channel, and the consumer reads and prints them asynchronously. ```C# using System; using System.Threading.Channels; using System.Threading.Tasks; Channel channel = Channel.CreateUnbounded(); Task producer = Task.Run(async () => { int i = 0; while (true) { channel.Writer.TryWrite(i++); await Task.Delay(TimeSpan.FromSeconds(1)); } }); Task consumer = Task.Run(async () => { await foreach (int value in channel.Reader.ReadAllAsync()) { Console.WriteLine(value); } }); await Task.WhenAll(producer, consumer); ``` -------------------------------- ### Using IChangeToken with Configuration Source: https://github.com/cysharp/zlogger/blob/master/src/ZLogger.Unity/Assets/Packages/Microsoft.Extensions.Primitives.8.0.0/PACKAGE.md Demonstrates how to monitor configuration changes in an application using IChangeToken. Attach a callback to be notified when the configuration is reloaded, for example, after modifying appsettings.json. ```C# using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Primitives; using System; class Program { static void Main(string[] args) { // Create a configuration builder var configurationBuilder = new ConfigurationBuilder() .SetBasePath(Environment.CurrentDirectory) // appsettings.json expected to have the following contents: // { // "SomeKey": "SomeValue" // } .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true); // Build the configuration IConfiguration configuration = configurationBuilder.Build(); // Create a change token for the configuration IChangeToken changeToken = configuration.GetReloadToken(); // Attach a change callback IDisposable changeTokenRegistration = changeToken.RegisterChangeCallback(state => { Console.WriteLine("Configuration changed!"); IConfigurationRoot root = (IConfigurationRoot)state; var someValue = root["SomeKey"]; // Access the updated configuration value Console.WriteLine($"New value of SomeKey: {someValue}"); }, configuration); // go and update the value of the key SomeKey in appsettings.json. // The change callback will be invoked when the file is saved. Console.WriteLine("Listening for configuration changes. Press any key to exit."); Console.ReadKey(); // Clean up the change token registration when no longer needed changeTokenRegistration.Dispose(); } } ``` -------------------------------- ### Configure MessagePack Formatter Source: https://github.com/cysharp/zlogger/blob/master/README.md Shows how to set up ZLogger to use the MessagePack formatter for binary log output. Ensure the ZLogger.MessagePack package is installed. ```csharp logging.AddZLoggerFile("log.bin", options => { options.UseMessagePackFormatter(); }); ``` -------------------------------- ### Basic Dependency Injection Usage Source: https://github.com/cysharp/zlogger/blob/master/src/ZLogger.Unity/Assets/Packages/Microsoft.Extensions.DependencyInjection.8.0.0/PACKAGE.md Demonstrates how to register a service, build a service provider, and resolve an instance using the DI pattern. This example shows the typical workflow for setting up and using dependency injection in a .NET application. ```csharp ServiceCollection services = new (); services.AddSingleton(); using ServiceProvider provider = services.BuildServiceProvider(); // The code below, following the IoC pattern, is typically only aware of the IMessageWriter interface, not the implementation. IMessageWriter messageWriter = provider.GetService()!; messageWriter.Write("Hello"); public interface IMessageWriter { void Write(string message); } internal class MessageWriter : IMessageWriter { public void Write(string message) { Console.WriteLine($"MessageWriter.Write(message: \"{message}\")"); } } ``` -------------------------------- ### Basic ZLogger Setup in Unity Source: https://github.com/cysharp/zlogger/blob/master/README.md Create a LoggerFactory to configure ZLogger for Unity's debug output. Set the minimum log level and add the ZLoggerUnityDebug provider. Then, create a logger instance for your class. ```csharp var loggerFactory = LoggerFactory.Create(logging => { logging.SetMinimumLevel(LogLevel.Trace); logging.AddZLoggerUnityDebug(); // log to UnityDebug }); var logger = loggerFactory.CreateLogger(); var name = "foo"; logger.ZLogInformation($"Hello, {name}!"); ``` -------------------------------- ### Setup Unity C# Compiler for ZLogger Source: https://github.com/cysharp/zlogger/blob/master/README.md Configure the C# compiler for Unity by creating a csc.rsp file in the Assets folder. This ensures C# 10 features are available. For newer Unity versions and C# 11 preview features, use 'langVersion:preview'. ```text -langVersion:10 -nullable ``` -------------------------------- ### Using Async Iterators with C# Source: https://github.com/cysharp/zlogger/blob/master/src/ZLogger.Unity/Assets/Packages/Microsoft.Bcl.AsyncInterfaces.8.0.0/PACKAGE.md Demonstrates how to consume an asynchronous iterator using the 'await foreach' syntax. This example shows a simple producer (`GetValuesAsync`) that yields values asynchronously with delays. ```C# using System; using System.Collections.Generic; using System.Threading.Tasks; internal static class Program { private static async Task Main() { Console.WriteLine("Starting..."); await foreach (var value in GetValuesAsync()) { Console.WriteLine(value); } Console.WriteLine("Finished!"); static async IAsyncEnumerable GetValuesAsync() { for (int i = 0; i < 10; i++) { await Task.Delay(TimeSpan.FromSeconds(1)); yield return i; } } } } ``` -------------------------------- ### Setup IDE C# Compiler for ZLogger Source: https://github.com/cysharp/zlogger/blob/master/README.md Configure the C# compiler for your IDE by creating a LangVersion.props file and adding it to your project settings. This enables C# 10 and nullable reference types. For source generators, use 'LangVersion:11'. ```xml 10.0 enable ``` -------------------------------- ### Using Source Generator for Log Messages Source: https://github.com/cysharp/zlogger/blob/master/src/ZLogger.Unity/Assets/Packages/Microsoft.Extensions.Logging.Abstractions.8.0.0/PACKAGE.md Demonstrates how to use the LoggerMessage attribute with a source generator to define custom, efficient log methods. Includes examples for static extension methods and instance methods. ```csharp public static partial class Log { [LoggerMessage( EventId = 0, Level = LogLevel.Critical, Message = "Could not open socket to `{hostName}`")] public static partial void CouldNotOpenSocket(this ILogger logger, string hostName); } public partial class InstanceLoggingExample { private readonly ILogger _logger; public InstanceLoggingExample(ILogger logger) { _logger = logger; } [LoggerMessage( EventId = 0, Level = LogLevel.Critical, Message = "Could not open socket to `{hostName}`")] public partial void CouldNotOpenSocket(string hostName); } ``` -------------------------------- ### Add ZLogger Console Provider to ASP.NET Core Source: https://github.com/cysharp/zlogger/blob/master/README.md This snippet shows the basic setup for ZLogger in an ASP.NET Core application by adding the console logging provider. ```csharp using ZLogger; var builder = WebApplication.CreateBuilder(args); builder.Logging.ClearProviders(); builder.Logging.AddZLoggerConsole(); ``` -------------------------------- ### ZLoggerMessage Source Generator Example Source: https://github.com/cysharp/zlogger/blob/master/README.md Define a static partial class with a ZLoggerMessage attribute to generate log methods at compile time. This enables high performance logging. ```csharp public static partial class MyLogger { [ZLoggerMessage(LogLevel.Information, "Bar: {x} {y}")] public static partial void Bar(this ILogger logger, int x, int y); } ``` -------------------------------- ### Register Custom Formatter Source: https://github.com/cysharp/zlogger/blob/master/README.md Use the UseFormatter extension method to register your custom formatter with ZLogger. This is typically done during the ZLogger setup. ```csharp options.UseFormatter(() => new MyFormatter()); ``` -------------------------------- ### Add Custom Log Processor to ZLogger Source: https://github.com/cysharp/zlogger/blob/master/README.md Registers a custom log processor with ZLogger. This example shows how to add the SimpleInMemoryLogProcessor and attach a console output handler. ```csharp var processor = new SimpleInMemoryLogProcessor(); processor.OnMessageReceived += msg => Console.WriteLine(msg); logging.AddZLoggerLogProcessor(processor); ``` -------------------------------- ### Implement Batching HTTP Log Processor Source: https://github.com/cysharp/zlogger/blob/master/README.md An example of a BatchingAsyncLogProcessor that batches log entries and sends them via HTTP POST. Log entries are formatted as UTF-8 and sent in a single request. The LogEntry is NonReturnable, so Return() does not need to be called. ```csharp public class BatchingHttpLogProcessor : BatchingAsyncLogProcessor { HttpClient httpClient; ArrayBufferWriter bufferWriter; IZLoggerFormatter formatter; public BatchingHttpLogProcessor(int batchSize, ZLoggerOptions options) : base(batchSize, options) { httpClient = new HttpClient(); bufferWriter = new ArrayBufferWriter(); formatter = options.CreateFormatter(); } protected override async ValueTask ProcessAsync(IReadOnlyList list) { foreach (var item in list) { item.FormatUtf8(bufferWriter, formatter); } var byteArrayContent = new ByteArrayContent(bufferWriter.WrittenSpan.ToArray()); await httpClient.PostAsync("http://foo", byteArrayContent).ConfigureAwait(false); bufferWriter.Clear(); } protected override ValueTask DisposeAsyncCore() { httpClient.Dispose(); return default; } } ``` -------------------------------- ### ZLogger Source Generator Example Source: https://github.com/cysharp/zlogger/blob/master/README.md Utilize ZLogger's source generator for efficient logging in Unity (requires Unity 2022.3.12f1 and preview C# features). Define log messages using the ZLoggerMessage attribute. ```csharp public static partial class LogExtensions { [ZLoggerMessage(LogLevel.Debug, "Hello, {name}")] public static partial void Hello(this ILogger logger, string name); } ``` -------------------------------- ### ZLogger File Logging with JSON Formatting Source: https://github.com/cysharp/zlogger/blob/master/README.md Configure ZLogger to write logs to a file with JSON formatting. This setup uses the AddZLoggerFile provider and enables JSON output via UseJsonFormatter. ```csharp var loggerFactory = LoggerFactory.Create(logging => { logging.AddZLoggerFile("/path/to/logfile", options => { options.UseJsonFormatter(); }); }); ``` -------------------------------- ### Options Validation Source Generator Example Source: https://github.com/cysharp/zlogger/blob/master/src/ZLogger.Unity/Assets/Packages/Microsoft.Extensions.Options.8.0.0/PACKAGE.md Utilize the Options Validation Source Generator to automatically generate validation code for options classes marked with [OptionsValidator]. ```csharp using System; using System.ComponentModel.DataAnnotations; using Microsoft.Extensions.Options; public class MyConfigOptions { [RegularExpression(@"^[a-zA-Z''-\s]{1,40}$")] public string Key1 { get; set; } [Range(0, 1000, ErrorMessage = "Value for {0} must be between {1} and {2}.")] public int Key2 { get; set; } public int Key3 { get; set; } } [OptionsValidator] public partial class MyConfigValidation : IValidateOptions { // Source generator will automatically provide the implementation of IValidateOptions // Then you can add the validation to the DI Container using the following code: // // builder.Services.AddSingleton, MyConfigValidation>(); // builder.Services.AddOptions() // .Bind(builder.Configuration.GetSection(MyConfigOptions.MyConfig)) // .ValidateDataAnnotations(); } ``` -------------------------------- ### Basic Logging with ZLogger Source: https://github.com/cysharp/zlogger/blob/master/README.md Demonstrates how to use ZLogger's ZLog* methods for structured logging with interpolated strings. Supports plain-text and JSON output formats. ```cs using Microsoft.Extensions.Logging; using ZLogger; // get ILogger from DI. public class MyClass(ILogger logger) { // name = "Bill", city = "Kumamoto", age = 21 public void Foo(string name, string city, int age) { // plain-text: // Hello, Bill lives in Kumamoto 21 years old. // json: // {"Timestamp":"2023-11-30T17:28:35.869211+09:00","LogLevel":"Information","Category":"MyClass","Message":"Hello, Bill lives in Kumamoto 21 years old.","name":"Bill","city":"Kumamoto","age":21} // json(IncludeProperties.ParameterKeyValues): // {"name":"Bill","city":"Kumamoto","age":21} logger.ZLogInformation($"Hello, {name} lives in {city} {age} years old."); // Explicit property name, you can use custom format string start with '@' logger.ZLogInformation($"Hello, {name:@user-name} id:{100:@id} {age} years old."); // Dump variables as JSON, you can use custom format string `json` var user = new User(1, "Alice"); // user: {"Id":1,"Name":"Bob"} logger.ZLogInformation($"user: {user:json}"); } } ``` -------------------------------- ### Configuring ZLogger Console Provider with Service Provider Source: https://github.com/cysharp/zlogger/blob/master/README.md Illustrates adding the ZLoggerConsole provider and configuring its options using both the options object and the service provider. ```cs builder.Logging .ClearProviders() // Configure options with service provider .AddZLoggerConsole((options, services) => { options.TimeProvider = services.GetService(); }); ``` -------------------------------- ### Using StringValues Source: https://github.com/cysharp/zlogger/blob/master/src/ZLogger.Unity/Assets/Packages/Microsoft.Extensions.Primitives.8.0.0/PACKAGE.md Illustrates how to create and use StringValues to represent single or multiple string values efficiently. Shows how to access values, check for emptiness, and perform comparisons. ```C# using System; using Microsoft.Extensions.Primitives; namespace StringValuesSample { class Program { static void Main(string[] args) { // Create a StringValues object from a single string or an array of strings StringValues single = "Hello"; StringValues multiple = new string[] { "Hello", "World" }; // Use the implicit conversion to string or the ToString method to get the values Console.WriteLine($"Single: {single}"); // Single: Hello Console.WriteLine($"Multiple: {multiple}"); // Multiple: Hello,World // Use the indexer, the Count property, and the IsNullOrEmpty method to access the values Console.WriteLine($"Multiple[1]: {multiple[1]}"); // Multiple[1]: World Console.WriteLine($"Single.Count: {single.Count}"); // Single.Count: 1 Console.WriteLine($"Multiple.IsNullOrEmpty: {StringValues.IsNullOrEmpty(multiple)}"); // Multiple.IsNullOrEmpty: False // Use the Equals method or the == operator to compare two StringValues objects Console.WriteLine($"single == \"Hello\": {single == "Hello"}"); // single == "Hello": True Console.WriteLine($"multiple == \"Hello\": {multiple == "Hello"}"); // multiple == "Hello": False } } } ``` -------------------------------- ### Generate Hashes with System.IO.Hashing Source: https://github.com/cysharp/zlogger/blob/master/src/ZLogger.Unity/Assets/Packages/System.IO.Hashing.8.0.0/PACKAGE.md Demonstrates how to generate hash codes for byte arrays using various algorithms provided by the System.IO.Hashing package, including CRC-32, CRC-64, XxHash3, XxHash32, XxHash64, and XxHash128. Ensure the System.IO.Hashing namespace is imported. ```csharp using System; using System.IO.Hashing; byte[] data = new byte[] { 1, 2, 3, 4 }; byte[] crc32Value = Crc32.Hash(data); Console.WriteLine($"CRC-32 Hash: {BitConverter.ToString(crc32Value)}"); // CRC-32 Hash: CD-FB-3C-B6 byte[] crc64Value = Crc64.Hash(data); Console.WriteLine($"CRC-64 Hash: {BitConverter.ToString(crc64Value)}"); // CRC-64 Hash: 58-8D-5A-D4-2A-70-1D-B2 byte[] xxHash3Value = XxHash3.Hash(data); Console.WriteLine($"XxHash3 Hash: {BitConverter.ToString(xxHash3Value)}"); // XxHash3 Hash: 98-8B-7B-90-33-AC-46-22 byte[] xxHash32Value = XxHash32.Hash(data); Console.WriteLine($"XxHash32 Hash: {BitConverter.ToString(xxHash32Value)}"); // XxHash32 Hash: FE-96-D1-9C byte[] xxHash64Value = XxHash64.Hash(data); Console.WriteLine($"XxHash64 Hash: {BitConverter.ToString(xxHash64Value)}"); // XxHash64 Hash: 54-26-20-E3-A2-A9-2E-D1 byte[] xxHash128Value = XxHash128.Hash(data); Console.WriteLine($"XxHash128 Hash: {BitConverter.ToString(xxHash128Value)}"); // XxHash128 Hash: 49-A0-48-99-59-7A-35-67-53-76-53-A0-D9-95-5B-86 ``` -------------------------------- ### Basic Logging with ILogger Source: https://github.com/cysharp/zlogger/blob/master/src/ZLogger.Unity/Assets/Packages/Microsoft.Extensions.Logging.8.0.0/PACKAGE.md Demonstrates a basic logging approach using ILogger for informational messages. This method can be less efficient due to string parsing and parameter processing. ```csharp public class LoggingSample1 { private ILogger _logger; public LoggingSample1(ILogger logger) { _logger = logger; } public void LogMethod(string name) { _logger.LogInformation("Hello {name}", name); } } ``` -------------------------------- ### Configuring ZLogger Console Provider Source: https://github.com/cysharp/zlogger/blob/master/README.md Demonstrates how to add and configure the ZLoggerConsole logger provider with custom options, such as setting the log level threshold. ```cs builder.Logging .ClearProviders() // Configure options .AddZLoggerConsole(options => { options.LogToStandardErrorThreshold = LogLevel.Error; }); ``` -------------------------------- ### Efficient Logging with LoggerMessage.Define Source: https://github.com/cysharp/zlogger/blob/master/src/ZLogger.Unity/Assets/Packages/Microsoft.Extensions.Logging.8.0.0/PACKAGE.md Illustrates an optimized logging approach using LoggerMessage.Define, which improves performance by pre-compiling log messages. This is the recommended best practice for runtime efficiency. ```csharp public class LoggingSample2 { private ILogger _logger; public LoggingSample2(ILogger logger) { _logger = logger; } public void LogMethod(string name) { Log.LogName(_logger, name); } private static class Log { private static readonly Action _logName = LoggerMessage.Define(LogLevel.Information, 0, @"Hello {name}"); public static void LogName(ILogger logger, string name) { _logName(logger, name, null!); } } } ``` -------------------------------- ### Custom Date Formatting with ZLogger Source: https://github.com/cysharp/zlogger/blob/master/README.md Shows how to use custom format strings with ZLogger's ZLog* methods to format specific properties, like dates, for structured logging. ```cs // Today is 2023-12-19. // {"date":"2023-12-19T11:25:34.3642389+09:00"} logger.ZLogDebug($"Today is {DateTime.Now:@date:yyyy-MM-dd}."); ``` -------------------------------- ### Using TimeProvider for UTC Time Source: https://github.com/cysharp/zlogger/blob/master/src/ZLogger.Unity/Assets/Packages/Microsoft.Bcl.TimeProvider.8.0.0/PACKAGE.md Demonstrates how to use TimeProvider to abstract time operations, specifically for obtaining the current UTC time. Includes a class that injects TimeProvider and a custom TimeProvider implementation. ```csharp using System; // A class that uses TimeProvider to get the current time in Utc coordinates public class UtcClock { private readonly TimeProvider _timeProvider; // Constructor that takes a TimeProvider as a dependency public Clock(TimeProvider timeProvider) { _timeProvider = timeProvider; } // A method that returns the current time as a string public string GetTime() { return _timeProvider.GetLocalNow().ToString("HH:mm:ss"); } } // A class that inherits from TimeProvider and overrides the GetLocalNow method public class UtcTimeProvider : TimeProvider { // Override the GetLocalNow method to always return UTC time public override DateTimeOffset GetLocalNow() { return TimeProvider.System.GetUtcNow(); } } ``` -------------------------------- ### Configure PlainText Formatter with Prefix and Suffix Source: https://github.com/cysharp/zlogger/blob/master/README.md Sets up a plain text formatter for console logging. It customizes the prefix to include timestamp and log level, and the suffix to include the log category. Exception formatting is also defined. ```csharp logging.AddZLoggerConsole(options => { // Text format // e.g) "2023-12-01 16:41:55.775|Information|This is log message. (MyNamespace.MyApp) options.UsePlainTextFormatter(formatter => { formatter.SetPrefixFormatter($"{0}|{1}|", (in MessageTemplate template, in LogInfo info) => template.Format(info.Timestamp, info.LogLevel)); formatter.SetSuffixFormatter($" ({0})", (in MessageTemplate template, in LogInfo info) => template.Format(info.Category)); formatter.SetExceptionFormatter((writer, ex) => Utf8StringInterpolation.Utf8String.Format(writer, $"{ex.Message}")); }); }); ``` -------------------------------- ### Configure Console and File Loggers with Different Formatters Source: https://github.com/cysharp/zlogger/blob/master/README.md Configure the console logger to use plain text formatting and the file logger to use JSON formatting. This demonstrates how to set up multiple providers with specific formatters. ```csharp // Show plain text log for console, json log for file logging.AddZLoggerConsole(options => options.UsePlainTextFormatter()); logging.AddZLoggerFile("json.log", options => options.UseJsonFormatter()); ``` -------------------------------- ### Worker Class Using ILogger Source: https://github.com/cysharp/zlogger/blob/master/src/ZLogger.Unity/Assets/Packages/Microsoft.Extensions.Logging.Abstractions.8.0.0/PACKAGE.md A sample worker class that demonstrates how to use dependency injection to obtain an ILogger instance and log information messages periodically. ```csharp // Worker class that uses logger implementation of teh interface ILogger public sealed class Worker : BackgroundService { private readonly ILogger _logger; public Worker(ILogger logger) => _logger = logger; protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { _logger.LogInformation("Worker running at: {time}", DateTimeOffset.UtcNow); await Task.Delay(1_000, stoppingToken); } } } ``` -------------------------------- ### Use Static Logger from LogManager Source: https://github.com/cysharp/zlogger/blob/master/README.md Demonstrates how to use the globally managed logger instance within a class. This avoids the need for DI to obtain a logger. ```csharp public class Foo { static readonly ILogger logger = LogManager.GetLogger(); public void Foo(int x) { logger.ZLogDebug($"do do do: {x}"); } } ``` -------------------------------- ### Configuring ZLogger via JSON Configuration Source: https://github.com/cysharp/zlogger/blob/master/README.md Shows how to set log levels for ZLogger providers, specifically the ZLoggerConsoleLoggerProvider, using JSON configuration. ```json { "Logging": { "LogLevel": { "Default": "Information" }, "ZLoggerConsoleLoggerProvider": { "LogLevel": { "Default": "Debug" } } } } ``` -------------------------------- ### Configure Multiple ZLogger Providers Source: https://github.com/cysharp/zlogger/blob/master/README.md Shows how to configure various ZLogger providers including Console, File, RollingFile, InMemory, Stream, and a custom LogProcessor within a Generic Host builder. ```csharp using ZLogger; var builder = Host.CreateApplicationBuilder(); builder.Logging // optional(MS.E.Logging):clear default providers(recommend to remove all) .ClearProviders() // optional(MS.E.Logging):setup minimum log level .SetMinimumLevel(LogLevel.Trace) // Add to output to console .AddZLoggerConsole(); // Add to output to the file .AddZLoggerFile("/path/to/file.log") // Add to output the file that rotates at constant intervals. .AddZLoggerRollingFile(options => { // File name determined by parameters to be rotated options.FilePathSelector = (timestamp, sequenceNumber) => $"logs/{timestamp.ToLocalTime():yyyy-MM-dd}_{sequenceNumber:000}.log"; // The period of time for which you want to rotate files at time intervals. options.RollingInterval = RollingInterval.Day; // Limit of size if you want to rotate by file size. (KB) options.RollingSizeKB = 1024; }) // Add to output of simple rendered strings into memory. You can subscribe to this and use it. .AddZLoggerInMemory(processor => { processor.MessageReceived += renderedLogString => { System.Console.WriteLine(renderedLogString); }; }) // Add output to any steram (`System.IO.Stream`) .AddZLoggerStream(stream); // Add custom output .AddZLoggerLogProcessor(new YourCustomLogExporter()); // Format as json .AddZLoggerConsole(options => { options.UseJsonFormatter(); }) // Format as json and configure output .AddZLoggerConsole(options => { options.UseJsonFormatter(formatter => { formatter.IncludeProperties = IncludeProperties.ParameterKeyValues; }); }) // Further common settings .AddZLoggerConsole(options => { // Enable LoggerExtensions.BeginScope ``` -------------------------------- ### Configure and Validate Options with DataAnnotations Source: https://github.com/cysharp/zlogger/blob/master/src/ZLogger.Unity/Assets/Packages/Microsoft.Extensions.Options.8.0.0/PACKAGE.md Use AddOptions and ValidateDataAnnotations to bind configuration to strongly typed options and validate them using attributes. ```csharp using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllersWithViews(); // Load the configuration and validate it builder.Services.AddOptions() .Bind(builder.Configuration.GetSection(MyConfigOptions.MyConfig)) .ValidateDataAnnotations(); var app = builder.Build(); // Declare the option class to validate public class MyConfigOptions { public const string MyConfig = "MyConfig"; [RegularExpression(@"^[a-zA-Z''-\s]{1,40}$")] public string Key1 { get; set; } [Range(0, 1000, ErrorMessage = "Value for {0} must be between {1} and {2}.")] public int Key2 { get; set; } public int Key3 { get; set; } } ``` -------------------------------- ### Configuring Activity Tracking Options Source: https://github.com/cysharp/zlogger/blob/master/src/ZLogger.Unity/Assets/Packages/Microsoft.Extensions.Logging.8.0.0/PACKAGE.md Demonstrates how to configure LoggerFactory to include tracing context like Span Id, Trace Id, Baggage, and Tags in the logging scope. This requires .NET 5.0 or later for basic tracking and .NET 6.0 Preview 1 for extended properties. ```csharp var loggerFactory = LoggerFactory.Create(logging => { logging.Configure(options => { options.ActivityTrackingOptions = ActivityTrackingOptions.Tags | ActivityTrackingOptions.Baggage; }).AddSimpleConsole(options => { options.IncludeScopes = true; }); }); ``` -------------------------------- ### Compile-Time Logging with Source Generators Source: https://github.com/cysharp/zlogger/blob/master/src/ZLogger.Unity/Assets/Packages/Microsoft.Extensions.Logging.8.0.0/PACKAGE.md Shows how to use the LoggerMessage source generator for compile-time log message creation. This approach offers a balance between performance and usability, requiring .NET 6 or later. ```csharp public partial class InstanceLoggingExample { private readonly ILogger _logger; public InstanceLoggingExample(ILogger logger) { _logger = logger; } [LoggerMessage( EventId = 0, Level = LogLevel.Critical, Message = "Could not open socket to `{hostName}`")] public partial void CouldNotOpenSocket(string hostName); } ``` -------------------------------- ### Default JSON Key Name Output Source: https://github.com/cysharp/zlogger/blob/master/README.md Demonstrates the default behavior where JSON key names are output as is. This is useful for understanding the baseline before applying mutators. ```csharp var user = new User(1, "Alice"); logger.ZLogInformation($"Name: {user.Name}"); ``` -------------------------------- ### Implement Custom Log Formatter Interface Source: https://github.com/cysharp/zlogger/blob/master/README.md Implement the IZLoggerFormatter interface to create custom log output formats. This interface requires defining a property for line breaks and a method for formatting log entries. ```csharp public interface IZLoggerFormatter { bool WithLineBreak { get; } void FormatLogEntry(IBufferWriter writer, TEntry entry) where TEntry : IZLoggerEntry; } ``` -------------------------------- ### JSON Serialization with Source Generation Source: https://github.com/cysharp/zlogger/blob/master/src/ZLogger.Unity/Assets/Packages/System.Text.Json.8.0.0/PACKAGE.md Shows how to use the source generator for System.Text.Json to improve performance. This method generates serialization and deserialization code at compile time. ```csharp using System.Text.Json; using System.Text.Json.Serialization; WeatherForecast forecast = new (DateTimeOffset.Now, 26.6f, "Sunny"); var serialized = JsonSerializer.Serialize(forecast, SourceGenerationContext.Default.WeatherForecast); Console.WriteLine(serialized); // {"Date":"2023-08-02T16:01:20.9025406+00:00","TemperatureCelsius":26.6,"Summary":"Sunny"} var forecastDeserialized = JsonSerializer.Deserialize(serialized, SourceGenerationContext.Default.WeatherForecast); Console.WriteLine(forecast == forecastDeserialized); // True public record WeatherForecast(DateTimeOffset Date, float TemperatureCelsius, string? Summary); [JsonSourceGenerationOptions(WriteIndented = true)] [JsonSerializable(typeof(WeatherForecast))] internal partial class SourceGenerationContext : JsonSerializerContext { } ``` -------------------------------- ### Set Global LoggerFactory using Host Builder Source: https://github.com/cysharp/zlogger/blob/master/README.md Configure a global logger factory using the Host builder pattern. This allows accessing a logger per type without dependency injection. ```csharp using var host = Host.CreateDefaultBuilder() .ConfigureLogging(logging => { logging.ClearProviders(); logging.AddZLoggerConsole(); }) .Build(); // use Build instead of Run directly // get configured loggerfactory. var loggerFactory = host.Services.GetRequiredService(); LogManager.SetLoggerFactory(loggerFactory, "Global"); // Run after set global logger. await host.RunAsync(); // ----- // Own static logger manager public static class LogManager { static ILogger globalLogger = default!; static ILoggerFactory loggerFactory = default!; public static void SetLoggerFactory(ILoggerFactory loggerFactory, string categoryName) { LogManager.loggerFactory = loggerFactory; LogManager.globalLogger = loggerFactory.CreateLogger(categoryName); } public static ILogger Logger => globalLogger; // standardLoggerFactory caches logger per category so no need to cache in this manager public static ILogger GetLogger() where T : class => loggerFactory.CreateLogger(); public static ILogger GetLogger(string categoryName) => loggerFactory.CreateLogger(categoryName); } ``` -------------------------------- ### Implement Simple In-Memory Log Processor Source: https://github.com/cysharp/zlogger/blob/master/README.md A basic implementation of IAsyncLogProcessor that captures log messages as strings and invokes a callback. Remember to call Return() on IZLoggerEntry as it is pooled. ```csharp public class SimpleInMemoryLogProcessor : IAsyncLogProcessor { public event Action? OnMessageReceived; public void Post(IZLoggerEntry log) { var msg = log.ToString(); log.Return(); OnMessageReceived?.Invoke(msg); } public ValueTask DisposeAsync() { return default; } } ``` -------------------------------- ### Basic JSON Serialization and Deserialization Source: https://github.com/cysharp/zlogger/blob/master/src/ZLogger.Unity/Assets/Packages/System.Text.Json.8.0.0/PACKAGE.md Demonstrates how to serialize a C# object to a JSON string and deserialize a JSON string back into a C# object using JsonSerializer. This is suitable for general-purpose JSON handling. ```csharp using System; using System.Text.Json; WeatherForecast forecast = new (DateTimeOffset.Now, 26.6f, "Sunny"); var serialized = JsonSerializer.Serialize(forecast); Console.WriteLine(serialized); // {"Date":"2023-08-02T16:01:20.9025406+00:00","TemperatureCelsius":26.6,"Summary":"Sunny"} var forecastDeserialized = JsonSerializer.Deserialize(serialized); Console.WriteLine(forecast == forecastDeserialized); // True public record WeatherForecast(DateTimeOffset Date, float TemperatureCelsius, string? Summary); ``` -------------------------------- ### Low-Level JSON Writing with Utf8JsonWriter Source: https://github.com/cysharp/zlogger/blob/master/src/ZLogger.Unity/Assets/Packages/System.Text.Json.8.0.0/PACKAGE.md Demonstrates using Utf8JsonWriter for efficient, low-level JSON creation. This is suitable for scenarios requiring fine-grained control over JSON output or when writing to streams. ```csharp using System; using System.IO; using System.Text; using System.Text.Json; var writerOptions = new JsonWriterOptions { Indented = true }; using var stream = new MemoryStream(); using var writer = new Utf8JsonWriter(stream, writerOptions); writer.WriteStartObject(); writer.WriteString("date", DateTimeOffset.Parse("8/2/2023 9:00 AM")); writer.WriteNumber("temp", 42); writer.WriteEndObject(); writer.Flush(); ``` -------------------------------- ### Configure PlainText Formatter with UTC Timestamp and Short Log Level Source: https://github.com/cysharp/zlogger/blob/master/README.md Configures the plain text formatter to use a UTC long date format for the timestamp and a short, three-character notation for the log level in the prefix. ```csharp logging.AddZLoggerConsole(options => { options.UsePlainTextFormatter(formatter => { // 2023-12-19 02:46:14.289 [DBG]...... formatter.SetPrefixFormatter($"{0:utc-longdate} [{1:short}]", (template, info) => template.Format(info.Timestamp, info.LogLevel)); }); }); ``` -------------------------------- ### Custom Logger Provider Implementation Source: https://github.com/cysharp/zlogger/blob/master/src/ZLogger.Unity/Assets/Packages/Microsoft.Extensions.Logging.Abstractions.8.0.0/PACKAGE.md Implements the ILogger interface to create a custom logger that writes messages to the console with color-coding based on log level. Requires a configuration object to map log levels to console colors. ```csharp using Microsoft.Extensions.Logging; public sealed class ColorConsoleLogger : ILogger { private readonly string _name; private readonly Func _getCurrentConfig; public ColorConsoleLogger( string name, Func getCurrentConfig) => (_name, _getCurrentConfig) = (name, getCurrentConfig); public IDisposable? BeginScope(TState state) where TState : notnull => default!; public bool IsEnabled(LogLevel logLevel) => _getCurrentConfig().LogLevelToColorMap.ContainsKey(logLevel); public void Log( LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter) { if (!IsEnabled(logLevel)) { return; } ColorConsoleLoggerConfiguration config = _getCurrentConfig(); if (config.EventId == 0 || config.EventId == eventId.Id) { ConsoleColor originalColor = Console.ForegroundColor; Console.ForegroundColor = config.LogLevelToColorMap[logLevel]; Console.WriteLine($"[{eventId.Id,2}: {logLevel,-12}]"); Console.ForegroundColor = originalColor; Console.Write($" {_name} - "); Console.ForegroundColor = config.LogLevelToColorMap[logLevel]; Console.Write($"{formatter(state, exception)}"); Console.ForegroundColor = originalColor; Console.WriteLine(); } } } ``` -------------------------------- ### Access Logger via Dependency Injection in Blazor Source: https://github.com/cysharp/zlogger/blob/master/README.md Demonstrates how to inject and use ILogger in a Blazor component to log information, including request path. ```csharp @page @using ZLogger @inject ILogger logger @{ logger.ZLogInformation($"Requested path: {this.HttpContext.Request.Path}"); } ``` -------------------------------- ### Custom JSON Reader Options Source: https://github.com/cysharp/zlogger/blob/master/src/ZLogger.Unity/Assets/Packages/System.Text.Json.8.0.0/PACKAGE.md Configures a Utf8JsonReader with specific options like allowing trailing commas and skipping comments. ```csharp var readerOptions = new JsonReaderOptions { AllowTrailingCommas = true, CommentHandling = JsonCommentHandling.Skip }; var reader = new Utf8JsonReader(jsonBytes, readerOptions); ``` -------------------------------- ### Configure Banned API Analyzers for ZLogger Source: https://github.com/cysharp/zlogger/blob/master/README.md Prepare a configuration file to prohibit the use of standard Log methods and encourage the use of ZLogger's ZLog method. This is done using Microsoft.CodeAnalysis.BannedApiAnalyzers. ```text T:Microsoft.Extensions.Logging.LoggerExtensions;Don't use this, use ZLog*** instead. T:System.Console;Don't use this, use logger instead. ``` -------------------------------- ### Validate Options using IValidateOptions Interface Source: https://github.com/cysharp/zlogger/blob/master/src/ZLogger.Unity/Assets/Packages/Microsoft.Extensions.Options.8.0.0/PACKAGE.md Implement IValidateOptions to provide custom validation logic for your options class. Register this implementation with the DI container. ```csharp using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllersWithViews(); // Configuration to validate builder.Services.Configure(builder.Configuration.GetSection( MyConfigOptions.MyConfig)); // OPtions validation through the DI container builder.Services.AddSingleton, MyConfigValidation>(); var app = builder.Build(); public class MyConfigValidation : IValidateOptions { public MyConfigOptions _config { get; private set; } public MyConfigValidation(IConfiguration config) { _config = config.GetSection(MyConfigOptions.MyConfig) .Get(); } public ValidateOptionsResult Validate(string name, MyConfigOptions options) { string? vor = null; var rx = new Regex(@"^[a-zA-Z''-\s]{1,40}$"); var match = rx.Match(options.Key1!); if (string.IsNullOrEmpty(match.Value)) { vor = $"{options.Key1} doesn't match RegEx \n"; } if ( options.Key2 < 0 || options.Key2 > 1000) { vor = $"{options.Key2} doesn't match Range 0 - 1000 \n"; } if (_config.Key2 != default) { if(_config.Key3 <= _config.Key2) { vor += "Key3 must be > than Key2."; } } if (vor != null) { return ValidateOptionsResult.Fail(vor); } return ValidateOptionsResult.Success; } } ``` -------------------------------- ### Add ZLogger File Logging Source: https://github.com/cysharp/zlogger/blob/master/README.md Adds file logging to the logging builder, writing logs to a specified file in append mode. Ensure the file path is correctly specified. ```csharp logging.AddZLoggerFile("log.txt"); ``` -------------------------------- ### Working with JSON DOM (JsonNode) Source: https://github.com/cysharp/zlogger/blob/master/src/ZLogger.Unity/Assets/Packages/System.Text.Json.8.0.0/PACKAGE.md Illustrates how to parse JSON strings into a traversable DOM structure using JsonNode. This is useful for inspecting or modifying JSON without full object deserialization. ```csharp using System; using System.Text.Json; using System.Text.Json.Nodes; string jsonString = @"{ "Date": "2019-08-01T00:00:00", "Temperature": 25, "Summary": "Hot", "DatesAvailable": [ "2019-08-01T00:00:00", "2019-08-02T00:00:00" ], "TemperatureRanges": { "Cold": { "High": 20, "Low": -10 }, "Hot": { "High": 60, "Low": 20 } } } "; JsonNode forecastNode = JsonNode.Parse(jsonString)!; // Get value from a JsonNode. JsonNode temperatureNode = forecastNode["Temperature"]!; Console.WriteLine($"Type={temperatureNode.GetType()}"); Console.WriteLine($"JSON={temperatureNode.ToJsonString()}"); //output: //Type = System.Text.Json.Nodes.JsonValue`1[System.Text.Json.JsonElement] //JSON = 25 // Get a typed value from a JsonNode. int temperatureInt = (int)forecastNode["Temperature"]!; Console.WriteLine($"Value={temperatureInt}"); //output: //Value=25 // Get a typed value from a JsonNode by using GetValue. temperatureInt = forecastNode["Temperature"]!.GetValue(); Console.WriteLine($"TemperatureInt={temperatureInt}"); //output: //Value=25 // Get a JSON object from a JsonNode. JsonNode temperatureRanges = forecastNode["TemperatureRanges"]!; Console.WriteLine($"Type={temperatureRanges.GetType()}"); Console.WriteLine($"JSON={temperatureRanges.ToJsonString()}"); //output: //Type = System.Text.Json.Nodes.JsonObject //JSON = { "Cold":{ "High":20,"Low":-10},"Hot":{ "High":60,"Low":20} } // Get a JSON array from a JsonNode. JsonNode datesAvailable = forecastNode["DatesAvailable"]!; Console.WriteLine($"Type={datesAvailable.GetType()}"); Console.WriteLine($"JSON={datesAvailable.ToJsonString()}"); //output: //datesAvailable Type = System.Text.Json.Nodes.JsonArray //datesAvailable JSON =["2019-08-01T00:00:00", "2019-08-02T00:00:00"] // Get an array element value from a JsonArray. JsonNode firstDateAvailable = datesAvailable[0]!; Console.WriteLine($"Type={firstDateAvailable.GetType()}"); Console.WriteLine($"JSON={firstDateAvailable.ToJsonString()}"); //output: //Type = System.Text.Json.Nodes.JsonValue`1[System.Text.Json.JsonElement] //JSON = "2019-08-01T00:00:00" // Get a typed value by chaining references. int coldHighTemperature = (int)forecastNode["TemperatureRanges"]!["Cold"]!["High"]!; Console.WriteLine($"TemperatureRanges.Cold.High={coldHighTemperature}"); //output: //TemperatureRanges.Cold.High = 20 // Parse a JSON array JsonNode datesNode = JsonNode.Parse(@"[\"2019-08-01T00:00:00\",\"2019-08-02T00:00:00\"]")!; JsonNode firstDate = datesNode[0]!.GetValue(); Console.WriteLine($"firstDate={ firstDate}"); //output: //firstDate = "2019-08-01T00:00:00" ``` -------------------------------- ### Customize ZLogger to Cloud Logging JSON Format Source: https://github.com/cysharp/zlogger/blob/master/README.md This extension method configures ZLogger to output logs in a format compatible with Google Cloud Logging. It customizes property names, includes specific log details, and nests payload data under 'jsonPayload'. ```csharp using System.Text.Json; using ZLogger; using ZLogger.Formatters; namespace ConsoleApp; using static IncludeProperties; using static JsonEncodedText; // JsonEncodedText.Encode public static class CloudLoggingExtensions { // Cloud Logging Json Field // https://cloud.google.com/logging/docs/structured-logging?hl=en public static ZLoggerOptions UseCloudLoggingJsonFormat(this ZLoggerOptions options) { return options.UseJsonFormatter(formatter => { // Category and ScopeValues is manually write in AdditionalFormatter at labels so remove from include properties. formatter.IncludeProperties = Timestamp | LogLevel | Message | ParameterKeyValues; formatter.JsonPropertyNames = JsonPropertyNames.Default with { LogLevel = Encode("severity"), LogLevelNone = Encode("DEFAULT"), LogLevelTrace = Encode("DEBUG"), LogLevelDebug = Encode("DEBUG"), LogLevelInformation = Encode("INFO"), LogLevelWarning = Encode("WARNING"), LogLevelError = Encode("ERROR"), LogLevelCritical = Encode("CRITICAL"), Message = Encode("message"), Timestamp = Encode("timestamp"), }; formatter.PropertyKeyValuesObjectName = Encode("jsonPayload"); // cache JsonEncodedText outside of AdditionalFormatter var labels = Encode("logging.googleapis.com/labels"); var category = Encode("category"); var eventId = Encode("eventId"); var userId = Encode("userId"); formatter.AdditionalFormatter = (Utf8JsonWriter writer, in LogInfo) => { writer.WriteStartObject(labels); writer.WriteString(category, logInfo.Category.JsonEncoded); writer.WriteString(eventId, logInfo.EventId.Name); if (logInfo.ScopeState != null && !logInfo.ScopeState.IsEmpty) { foreach (var item in logInfo.ScopeState.Properties) { if (item.Key == "userId") { writer.WriteString(userId, item.Value!.ToString()); break; } } } writer.WriteEndObject(); }; }); } } ``` -------------------------------- ### Configure ZLogger for In-Memory Logging Source: https://github.com/cysharp/zlogger/blob/master/README.md Adds an in-memory logger provider to ZLogger. It allows retrieving rendered log strings as they are generated. A callback can be registered to receive log messages. ```csharp logging.AddZLoggerInMemory(processor => { processor.MessageReceived += msg => { Console.WriteLine($"Received:{msg}"); }; }); ``` -------------------------------- ### Add ZLogger Rolling File Logging Source: https://github.com/cysharp/zlogger/blob/master/README.md Adds rolling file logging, which dynamically changes the output file based on conditions like date or size. The file name selector and roll size can be configured. ```csharp // output to yyyy-MM-dd_*.log, roll by 1MB or changed date logging.AddZLoggerRollingFile((dt, index) => $"{dt:yyyy-MM-dd}_{index}.log", 1024 * 1024); ``` -------------------------------- ### Add ZLogger Stream Logging Source: https://github.com/cysharp/zlogger/blob/master/README.md Adds stream logging, allowing logs to be directed to any arbitrary stream, such as a MemoryStream or NetworkStream. This provides flexibility for custom log destinations. ```csharp var ms = new MemoryStream(); logging.AddZLoggerStream(ms); ``` -------------------------------- ### Add ZLogger Console Logging Source: https://github.com/cysharp/zlogger/blob/master/README.md Adds console logging to the logging builder. By default, it outputs logs to standard output and configures UTF8 encoding. ```csharp logging.AddZLoggerConsole(); ``` -------------------------------- ### Define IAsyncLogProcessor Interface Source: https://github.com/cysharp/zlogger/blob/master/README.md Defines the interface for asynchronous log processors in ZLogger. Implementations must handle log entries and asynchronous disposal. ```csharp public interface IAsyncLogProcessor : IAsyncDisposable { void Post(IZLoggerEntry log); } ``` -------------------------------- ### Configure Console Logging to Standard Error Source: https://github.com/cysharp/zlogger/blob/master/README.md Configures ZLogger console logging to direct logs to standard error when a certain log level threshold is met. This is useful for environments where standard output is used for data input/output. ```csharp var logger = Microsoft.Extensions.Logging.LoggerFactory.Create(x => { // Configure all logs to go to stderr x.AddZLoggerConsole(x => x.LogToStandardErrorThreshold = Microsoft.Extensions.Logging.LogLevel.Trace); }); ``` -------------------------------- ### Iterating Through JSON Tokens Source: https://github.com/cysharp/zlogger/blob/master/src/ZLogger.Unity/Assets/Packages/System.Text.Json.8.0.0/PACKAGE.md Reads through JSON data token by token using Utf8JsonReader and handles different token types like PropertyName, String, and Number. ```csharp while (reader.Read()) { Console.Write(reader.TokenType); switch (reader.TokenType) { case JsonTokenType.PropertyName: case JsonTokenType.String: { string? text = reader.GetString(); Console.Write(" "); Console.Write(text); break; } case JsonTokenType.Number: { int intValue = reader.GetInt32(); Console.Write(" "); Console.Write(intValue); break; } // Other token types elided for brevity } Console.WriteLine(); } // StartObject // PropertyName date // String 2023-08-02T09:00:00+00:00 // PropertyName temp // Number 42 // EndObject ``` -------------------------------- ### Reading JSON Bytes to String Source: https://github.com/cysharp/zlogger/blob/master/src/ZLogger.Unity/Assets/Packages/System.Text.Json.8.0.0/PACKAGE.md Converts a byte array containing JSON data into a UTF-8 encoded string for display or further processing. ```csharp var jsonBytes = stream.ToArray(); string json = Encoding.UTF8.GetString(jsonBytes); Console.WriteLine(json); // { // "date": "2023-08-02T09:00:00+00:00" // "temp": 42 // } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.