Declaring Log Methods
Log methods are declared as static partial methods inside partial classes. The generator provides the implementation.
public static partial class NetworkLog
{
[LogMessage(LogLevel.Information, "Connection established to {endpoint} in {latencyMs}ms")]
public static partial void ConnectionEstablished(string endpoint, double latencyMs);
[LogMessage(LogLevel.Warning, "Packet loss detected: {lossPercent}% over {windowSeconds}s")]
public static partial void PacketLoss(float lossPercent, int windowSeconds);
[LogMessage(LogLevel.Critical, "Connection to {endpoint} lost")]
public static partial void ConnectionLost(string endpoint, Exception ex);
}
Requirements:
- The containing class must be
partial. - The method must be
static partial. - The method must return
void. - Parameter names referenced in the message template are matched case-insensitively.
- Parameters may use the
inmodifier to pass large structs by reference (see Performance).
Categories
The [LogCategory] attribute sets the category string attached to every log entry from that class. If omitted, the class name is used. The generator emits a public const string CategoryName field on each log class, which can be used for type-safe per-category configuration via SetMinimumLevel<T>().
[LogCategory("Audio")]
public static partial class AudioLog { ... }
// Generated: public const string CategoryName = "Audio";
// No attribute: category defaults to "PhysicsLog"
public static partial class PhysicsLog { ... }
// Generated: public const string CategoryName = "PhysicsLog";
Message Templates
Explicit templates
Provide a message string with {parameterName} placeholders that map to method parameters by name (case-insensitive):
[LogMessage(LogLevel.Debug, "Frame {frameId} rendered {triangleCount} triangles in {elapsedMs}ms")]
public static partial void FrameRendered(int frameId, long triangleCount, double elapsedMs);
The generator pre-splits the template at compile time into alternating literal segments and parameter slots. At runtime, it writes UTF8 literals directly and formats each parameter through its IUtf8SpanFormattable implementation.
Template-free mode
Omit the message string. The generator constructs the message automatically from the method name and parameter names:
[LogMessage(LogLevel.Debug)]
public static partial void FrameRendered(int frameId, long triangleCount, double elapsedMs);
// Generated message: "FrameRendered frameId={frameId} triangleCount={triangleCount} elapsedMs={elapsedMs}"
This mode guarantees that renaming a parameter via IDE refactoring keeps the message in sync. The method name is split from PascalCase for the structured event name.
EventId
Each log method receives a stable EventId derived from a hash of the fully qualified method name. To override:
[LogMessage(LogLevel.Information, "Player joined: {playerName}", EventId = 5001)]
public static partial void PlayerJoined(string playerName);