Skip to content
Back to skills

Logging

ASecurity

UTF-8 file logging with automatic date-based filenames and thread-safe operations for RocsMiddleware services

  • 666 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added February 9, 2026
developmentgobashdebugging

Security analysis

A100/100

Scanned February 12, 2026

npx -y skills add majiayu000/claude-skill-registry --skill logging --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Logging?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Logging
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/majiayu000-logging/badge)](https://www.skillsdirectory.com/skills/majiayu000-logging)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: Logging
description: UTF-8 file logging with automatic date-based filenames and thread-safe operations for RocsMiddleware services
---

# Logging

## Instructions

When helping users implement logging in RocsMiddleware services, follow these guidelines:

1. **Command-Line Option**: Always include `--log-dir` parameter for specifying log directory path

2. **UTF-8 Encoding**: All log files must use UTF-8 encoding without BOM

3. **Automatic Filename Pattern**: Use `{ProgramName}_YYYY_MM_DD.log` format with automatic date rotation

4. **Directory Path Handling**: Smart detection - if path has no extension or ends with separator, treat as directory and use directory name as base filename

5. **Error Handling**: Include console output before logger initialization since logger may fail. Always check if `_logger` is null in exception handlers.

6. **Log Levels**: Use `LogLevel.Debug` with `--debug` flag, default to `LogLevel.Information`

7. **Thread Safety**: The UTF8Writer uses locking for concurrent writes

8. **Utf8LoggingExtensions.cs**: Copy the reference implementation to project's `Services/` directory - provides UTF8Writer, UTF8LoggerProvider, UTF8Logger, and helper methods

## Examples

### Example 1: Basic Logger Setup
```
User: Help me add logging to my RocsMiddleware service

Claude: I'll set up the standard UTF-8 file logging pattern:
- Add --log-dir command-line option
- Copy Utf8LoggingExtensions.cs to Services/
- Initialize logger with automatic date-based filename
- Add console output before logger initialization for debugging

[Provides implementation using the Logger Initialization pattern from reference material below]
```

### Example 2: Directory Path Handling
```
User: Why isn't my log file being created when I specify --log-dir?

Claude: Let me check the directory path handling. The logger should:
- Detect if path is a directory (no extension or ends with separator)
- Use directory name as base filename
- Add date string and .log extension automatically

Common issue: Old Utf8LoggingExtensions.cs without directory detection logic.
Solution: Copy the updated version from skills folder.

[Provides directory detection implementation from reference material below]
```

### Example 3: Error Handling Before Logger Init
```
User: My program just prints "Error" with no details

Claude: This happens when an exception occurs before logger initialization. I'll add:
- Console.WriteLine at key points (startup, before logger init, after logger init)
- Null check on _logger in exception handler
- Fallback to console output if logger is null

[Provides error handling pattern from reference material below]
```

---

# Reference Implementation Details

The sections below contain proven working code from RocsMiddleware services that the examples above reference.

**Reference Files in This Folder**:
- `Utf8LoggingExtensions.cs` - Complete UTF-8 logger implementation (copy to Services/)

# Standard Logging Pattern

All RocsMiddleware services use a consistent logging approach:

1. **Command-line option**: `--log-dir` parameter specifies the directory path
2. **Automatic filename generation**: `{ProgramName}_YYYY_MM_DD.log`
3. **UTF-8 encoding**: All log files use UTF-8 encoding
4. **Date rotation**: Log files automatically rotate daily based on the date

## Implementation

### Command-Line Option

```csharp
[Option("log-dir", Required = false, HelpText = "Directory for log files")]
public string? LogDir { get; set; }
```

### Logger Initialization

```csharp
// Initialize logger with optional log directory
var logLevel = options.Debug ? LogLevel.Debug : LogLevel.Information;
_logger = {Namespace}.Services.Utf8LoggingExtensions.CreateUtf8Logger(
    "{ProgramName}",
    logLevel,
    options.LogDir);
```

### Example Usage

```bash
dotnet run -- --log-dir "C:\RI Services\Logs\MyProgram" --other-options
```

This creates: `C:\RI Services\Logs\MyProgram\MyProgram_2025_10_16.log`

## Directory Path Handling

The `UTF8Writer.Init()` method automatically detects directory paths and creates properly named log files:

- If path has no extension and ends with a path separator (or exists as a directory), it's treated as a directory
- The directory name becomes the base name for the log file
- Default `.log` extension is added automatically
- Date string in format `YYYY_MM_DD` is inserted before the extension

### Examples

| Input `--log-dir`                    | Output Log File                                                    |
|--------------------------------------|---------------------------------------------------------------------|
| `C:\Logs\MyProgram`                  | `C:\Logs\MyProgram\MyProgram_2025_10_16.log`                       |
| `C:\Logs\MyProgram\`                 | `C:\Logs\MyProgram\MyProgram_2025_10_16.log`                       |
| `C:\Logs\MyProgram\custom.log`       | `C:\Logs\MyProgram\custom_2025_10_16.log`                          |
| `C:\Logs\MyProgram\custom`           | `C:\Logs\MyProgram\custom_2025_10_16.log` (adds .log extension)   |

## UTF8LoggingExtensions.cs

All services include a `Services/Utf8LoggingExtensions.cs` file that provides:

- `UTF8Writer` class: Low-level UTF-8 file writer with thread-safe locking
- `UTF8LoggerProvider`: Custom logger provider for Microsoft.Extensions.Logging
- `UTF8Logger`: ILogger implementation that writes to UTF-8 files
- `CreateUtf8Logger()`: Helper method to create a configured logger instance
- `ConfigureUtf8Logging()`: Extension method for ILoggingBuilder

## Error Handling

### Before Logger Initialization

Since the logger may fail to initialize, always include console output for early errors:

```csharp
public static async Task Main(string[] args)
{
    try
    {
        Console.WriteLine("{ProgramName} starting...");

        // Parse command line
        CommandLineOptions? options = null;
        Parser.Default.ParseArguments<CommandLineOptions>(args)
            .WithParsed(opts => options = opts)
            .WithNotParsed(errors =>
            {
                Console.WriteLine("Failed to parse command line arguments");
                Environment.Exit(1);
            });

        if (options == null)
        {
            Console.WriteLine("Failed to parse command line options");
            Environment.Exit(1);
            return;
        }

        Console.WriteLine($"Initializing logger with log-dir: {options.LogDir ?? "(null)"}");

        // Initialize logger
        _logger = {Namespace}.Services.Utf8LoggingExtensions.CreateUtf8Logger(
            "{ProgramName}",
            options.Debug ? LogLevel.Debug : LogLevel.Information,
            options.LogDir);

        Console.WriteLine("Logger initialized");

        _logger.LogInformation("{ProgramName} starting");

        // ... rest of program
    }
    catch (Exception ex)
    {
        if (_logger != null)
        {
            _logger.LogError(ex, "{ProgramName} failed: {Message}", ex.Message);
        }
        else
        {
            Console.WriteLine($"{ProgramName} failed: {ex.Message}");
            Console.WriteLine(ex.StackTrace);
        }
        Environment.Exit(1);
    }
}
```

## Log Levels

Standard log levels used across all services:

- `LogLevel.Debug`: Verbose diagnostic information (use `--debug` flag)
- `LogLevel.Information`: General informational messages (default)
- `LogLevel.Warning`: Warning messages for non-critical issues
- `LogLevel.Error`: Error messages for failures

## Real-World Examples

### PriceExtractor
```bash
dotnet run -- --pqdir "R:\Outputs\Parquets\poller" --pg "R:\JsonParams\x3rocs_db.json" --log-dir "C:\RI Services\Logs\PriceExtractor" --full
```

Creates: `C:\RI Services\Logs\PriceExtractor\PriceExtractor_2025_10_16.log`

### PriceDiscountUploader
```bash
dotnet run -- --pg "R:/JsonParams/x3rocs_db.json" --log-dir "R:/Logs/PriceDiscounter" --elastic https://rocs-stage-es.ramsden-international.com/ --debug --sphkey1 425073
```

Creates: `R:/Logs/PriceDiscounter/PriceDiscounter_2025_10_16.log`

## Benefits

1. **Consistent naming**: All services follow the same `{ProgramName}_YYYY_MM_DD.log` pattern
2. **Automatic rotation**: Daily log files without manual intervention
3. **UTF-8 encoding**: Proper support for international characters
4. **Directory-aware**: Smart handling of directory vs. file paths
5. **Optional logging**: Works without `--log-dir` (console only)
6. **Thread-safe**: Multiple threads can log simultaneously

## Common Issues

### No Log File Created

**Symptom**: Program runs but no log file appears in the specified directory.

**Causes**:
1. Old version of `Utf8LoggingExtensions.cs` without directory path handling
2. Logger initialization failing silently

**Solution**:
- Copy `Utf8LoggingExtensions.cs` from this skills folder to your project's `Services/` directory
- Add console debug output before logger initialization (see Error Handling section above)
- Check that the `UTF8Writer.Init()` method includes directory detection logic

### Program Exits with "Error" and No Details

**Symptom**: Program outputs just "Error" with no stack trace or details.

**Causes**:
1. Exception thrown before logger is initialized
2. Exception handler trying to use null logger

**Solution**:
- Add console output at key points (see Error Handling section)
- Wrap exception handler to check if `_logger` is null before using it
- Check log file was actually created and contains error details

## Related Files

- `Utf8LoggingExtensions.cs`: Reference implementation included in this folder - copy to your project's `Services/` directory
- Command-line parsing: Uses `CommandLineParser` library
- All services in RocsMiddleware follow this pattern

## Notes

- Log files are created on-demand when the first log message is written
- If `--log-dir` is not specified, logging goes to console only (if enabled)
- Parent directories are created automatically if they don't exist
- Log files are UTF-8 encoded without BOM
- The logger uses Microsoft.Extensions.Logging interfaces for compatibility

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.