Skip to content

EventLoomer .NET SDK Usage Guide

This guide explains how to use the EventLoomer .NET SDK in your applications. The .NET SDK is our first officially supported SDK, providing seamless integration with .NET's ILogger infrastructure and direct client access for manual logging. More language-specific SDKs are planned.

While the SDK provides convenience, especially for .NET applications, logs can also be sent directly to our simple HTTP API from any language or platform.

Supported Platforms

The EventLoomer .NET SDK supports:

  • .NET 6.0 and later
  • ASP.NET Core applications
  • Console applications
  • Worker services
  • Blazor applications (both Server and WebAssembly)

Installation

Install the EventLoomer .NET SDK using NuGet:

bash
dotnet add package EventLoomer.SDK

Configuration

Basic Configuration (Program.cs / Startup.cs)

Configure EventLoomer services using AddEventLoomer:

csharp
// Example using builder pattern in Program.cs
builder.Services.AddEventLoomer(options =>
{
    // Required: Base URL of your EventLoomer API instance
    options.BaseUrl = builder.Configuration["EventLoomer:BaseUrl"] ?? "https://api.eventloomer.com";

    // Required: Your Team's API Key (find in Team Settings)
    options.ApiKey = builder.Configuration["EventLoomer:ApiKey"] ?? throw new InvalidOperationException("ApiKey missing");

    // Required for ILogger Integration (Application Logs): Your Project's ID
    options.ProjectId = builder.Configuration["EventLoomer:ProjectId"] ?? throw new InvalidOperationException("ProjectId missing for logging");

    // Optional: Set the environment (e.g., "Production", "Staging", "Development"). Defaults to "Development".
    options.Environment = builder.Configuration["EventLoomer:Environment"] ?? "Development";

    // Optional: If true, API call errors won't throw exceptions (check response instead). Defaults to false.
    options.FailSilently = true;

    // Optional: Enable/disable sending logs via ILogger. Defaults to true.
    options.LoggingEnabled = true;
});

Advanced Logger Configuration

You can fine-tune the ILogger behavior:

csharp
builder.Services.AddEventLoomer(
    options => // Standard options from above
    {
        options.BaseUrl = builder.Configuration["EventLoomer:BaseUrl"];
        options.ApiKey = builder.Configuration["EventLoomer:ApiKey"];
        options.ProjectId = builder.Configuration["EventLoomer:ProjectId"];
        options.Environment = builder.Configuration["EventLoomer:Environment"];
        options.LoggingEnabled = true;
    },
    loggerConfig =>
    {
        // Configure ILogger specific options
        loggerConfig.MinimumLogLevel = LogLevel.Information; // Default: Information
        loggerConfig.IncludeScopes = true;                 // Default: true
        loggerConfig.IncludeExceptionStackTrace = true;    // Default: true
        loggerConfig.UseBatching = true;                   // Default: true (recommended for performance)
        loggerConfig.BatchSize = 50;                       // Default: 100
        loggerConfig.BatchTimeout = TimeSpan.FromSeconds(1); // Default: 2 seconds
        loggerConfig.Environment = options.Environment;      // Inherits from main options by default
        // loggerConfig.CorrelationKey = "your-global-correlation-key"; // Optional global correlation key
    });

Usage

The SDK offers two primary ways to send logs:

  1. Automatic Logging via ILogger: Integrates directly with the standard .NET logging framework (Microsoft.Extensions.Logging). Logs sent this way appear as Application Logs in EventLoomer, associated with the configured ProjectId.
  2. Manual Logging via IEventLoomerClient: Provides direct methods to send logs. You can send logs associated with specific Events/Steps (appearing as Event Logs) or send logs associated with a Project (appearing as Application Logs).

1. Automatic Logging with ILogger (Application Logs)

This is the recommended approach for general application logging within .NET applications. Once configured via AddEventLoomer, simply inject ILogger<T> and use standard logging methods. These logs will be automatically sent to EventLoomer and associated with the ProjectId specified in the options.

csharp
using Microsoft.Extensions.Logging;

public class UserService
{
    private readonly ILogger<UserService> _logger;

    public UserService(ILogger<UserService> logger)
    {
        _logger = logger;
    }

    public async Task RegisterUser(string email, string userId)
    {
        // Scopes add contextual data to all logs within the 'using' block
        using (_logger.BeginScope(new Dictionary<string, object>
        {
            ["UserId"] = userId,
            ["Operation"] = "UserRegistration"
        }))
        {
            try
            {
                _logger.LogInformation("Attempting to register user {Email}", email);

                // ... registration logic ...
                if (await UserExists(email))
                {
                     // LogWarning includes the scope data automatically
                    _logger.LogWarning("User {Email} already exists.", email);
                    return;
                }

                // ... create user ...

                _logger.LogInformation("User {Email} registered successfully with ID {UserId}", email, userId);
            }
            catch (Exception ex)
            {
                // LogError automatically includes exception details and scope data
                _logger.LogError(ex, "Failed to register user {Email}", email);
                throw;
            }
        }
    }

    private async Task<bool> UserExists(string email) { /* ... check database ... */ return false; }
}

2. Manual Logging with IEventLoomerClient

Inject IEventLoomerClient for more direct control or when logging specific business events/steps.

a) Sending Event/Step Logs (External Logs):

Use methods like InfoAsync, ErrorAsync, etc., or the general SendLogAsync. These require a uniqueIdentifier corresponding to an Event or Step you've defined in EventLoomer. These appear as Event Logs in the UI.

csharp
using EventLoomer.SDK;
using EventLoomer.SDK.Models; // For EventLogLevel

public class PaymentService
{
    private readonly IEventLoomerClient _eventLoomerClient;

    public PaymentService(IEventLoomerClient eventLoomerClient)
    {
        _eventLoomerClient = eventLoomerClient;
    }

    public async Task ProcessPayment(PaymentRequest request)
    {
        string paymentEventId = "payment-processed"; // Unique ID defined in EventLoomer UI
        string chargeStepId = "charge-attempted";    // Unique ID defined in EventLoomer UI

        await _eventLoomerClient.InfoAsync(paymentEventId, $"Processing payment {request.PaymentId}", request.CorrelationId, request.Environment);

        try
        {
            // ... attempt charge ...
            bool success = await _chargeProvider.Charge(request.Amount);

            var payload = new { RequestId = request.PaymentId, Success = success, Amount = request.Amount };
            await _eventLoomerClient.InfoAsync(chargeStepId, JsonSerializer.Serialize(payload), EventLogLevel.Information, request.CorrelationId, request.Environment);

            if(!success) {
                 await _eventLoomerClient.ErrorAsync(paymentEventId, "Payment failed", request.CorrelationId, request.Environment);
            }
        }
        catch (Exception ex)
        {
            await _eventLoomerClient.ErrorAsync(paymentEventId, $"Exception during payment: {ex.Message}", request.CorrelationId, request.Environment);
            throw;
        }
    }
}

b) Sending Application Logs Manually:

Use SendApplicationLogAsync if you need to manually send a log that should be associated with your ProjectId (like ILogger does). This is less common than using ILogger directly.

csharp
// Example: Logging a background task status manually as an Application Log
await _eventLoomerClient.SendApplicationLogAsync(
    projectId: "your-project-id", // Or retrieve from options
    categoryName: "BackgroundTasks.Cleanup",
    eventId: 1001,
    eventName: "CleanupTaskCompleted",
    message: $"Cleanup task finished. Removed {count} items.",
    level: EventLogLevel.Information,
    environment: "Production"
);

Log Levels

Use the appropriate level to indicate severity:

  • Trace/Debug: Verbose developer information.
  • Information: Standard operational messages.
  • Warning: Potential issues or non-critical errors.
  • Error: Functional errors that should be investigated.
  • Critical: Severe errors indicating system instability.

The SDK uses EventLogLevel enum for client methods and maps standard Microsoft.Extensions.Logging.LogLevel for ILogger.

Correlation Tracking

Pass a correlationKey (e.g., a request ID, transaction ID, or GUID) consistently across related log calls (both ILogger scopes and IEventLoomerClient methods) to link them together in the EventLoomer UI's Flow view.

csharp
public async Task HandleRequest(HttpRequest request)
{
    var correlationId = request.Headers["X-Request-ID"].FirstOrDefault() ?? Guid.NewGuid().ToString();

    using (_logger.BeginScope(new Dictionary<string, object> { ["CorrelationId"] = correlationId }))
    {
        _logger.LogInformation("Handling request {Path}", request.Path);
        await _someService.DoWorkAsync(correlationId);
        await _eventLoomerClient.InfoAsync("REQUEST_END", "Request finished", correlationId);
    }
}

Environment Support

Specify the environment (Development, Staging, Production, etc.) to segregate logs.

  • Configuration: Set the default environment in EventLoomerOptions.
  • ILogger: Automatically uses the environment from configuration.
  • IEventLoomerClient: Pass the environment parameter to override the default for specific calls.
csharp
// Set default in Program.cs
options.Environment = "Production";

// Override for a specific manual log
await _eventLoomerClient.WarnAsync(eventId, "Staging specific warning", correlationId, "Staging");

Configuration Validation

You can check if the SDK is configured correctly and can reach the API:

csharp
// Inject IEventLoomerClient client;

// Check status property (updated periodically or after calls)
if (client.ConfigurationStatus != EventLoomerConfigurationStatus.Valid)
{
    Console.WriteLine($"Warning: EventLoomer client status: {client.ConfigurationStatus}");
}

// Perform an explicit validation check (makes an API call)
var validationResponse = await client.ValidateConfigurationAsync();
if (!validationResponse.Success)
{
    Console.WriteLine($"Error validating EventLoomer config: {validationResponse.Error?.Message}");
    // status property will also be updated
} else {
    Console.WriteLine($"EventLoomer config status: {validationResponse.Data}");
}

See EventLoomerConfigurationStatus enum for possible status values.

Error Handling (EventLoomerResponse<T>)

By default (FailSilently = true), SDK methods interacting with the API do not throw exceptions for HTTP or API errors. Instead, they return an EventLoomerResponse<string> (or specific type for ValidateConfigurationAsync). Always check the Success property.

csharp
var response = await _eventLoomerClient.InfoAsync("MY_EVENT", "Important data");

if (response.Success)
{
    Console.WriteLine($"Log sent successfully. ID (if available): {response.Data}");
}
else
{
    // Log failed to send
    Console.WriteLine($"Failed to send log: {response.Error?.Code} - {response.Error?.Message}");
    // Optionally log response.Error.Details
    // Implement fallback logging or retry logic if needed
}

If you set options.FailSilently = false, API call errors will throw exceptions (typically HttpRequestException or potentially a custom EventLoomerException in future versions).

Best Practices

  1. Choose the Right Method: Use ILogger for general application tracing and diagnostics. Use IEventLoomerClient for explicitly logging key business events or steps defined in EventLoomer.
  2. Use Meaningful Identifiers: Use clear uniqueIdentifier values (for SendLogAsync) or categoryName/EventId (for ILogger/SendApplicationLogAsync) that align with your application's domain.
  3. Structured Logging (ILogger): Leverage structured logging (_logger.LogInformation("User {UserId} logged in", userId);) for richer, searchable logs. Use scopes (BeginScope) for contextual data.
  4. Correlation Keys: Consistently apply correlation keys to trace operations across services or asynchronous boundaries.
  5. Log Levels: Use appropriate levels to differentiate between informational messages, warnings, and critical errors.
  6. Exception Handling: Include the Exception object when logging errors (_logger.LogError(ex, ...) or _eventLoomerClient.ErrorAsync(..., ex.ToString())).
  7. Environments: Configure and use the Environment property to separate logs logically.
  8. Check Responses: If not failing silently, check response.Success from IEventLoomerClient calls to handle potential sending errors.
  9. Configuration Validation: Consider using ValidateConfigurationAsync at application startup to ensure the SDK is correctly configured.