Skip to content

Querying Audit Logs

This guide covers all the ways to query and retrieve audit logs in GrydAudit.

Query Options

GrydAudit provides multiple ways to query audit logs:

  1. MediatR Queries - CQRS pattern for application layer
  2. Repository - Direct data access
  3. REST API - HTTP endpoints for external access

MediatR Queries

Get Audit Log by ID

csharp
var query = new GetAuditLogByIdQuery(auditLogId);
var result = await mediator.Send(query);

if (result is not null)
{
    Console.WriteLine($"Action: {result.Action}");
    Console.WriteLine($"Entity: {result.EntityType} ({result.EntityId})");
    Console.WriteLine($"User: {result.UserName}");
}

Get Entity History

Retrieve all audit logs for a specific entity:

csharp
var query = new GetAuditLogsByEntityQuery("Product", productId);
var logs = await mediator.Send(query);

foreach (var log in logs)
{
    Console.WriteLine($"{log.Timestamp}: {log.Action} by {log.UserName}");
}

Get User's Audit Logs

Retrieve all actions performed by a specific user:

csharp
var query = new GetAuditLogsByUserQuery(userId);
var logs = await mediator.Send(query);

Search with Filters

Perform complex searches with multiple filter criteria:

csharp
var query = new SearchAuditLogsQuery(new AuditLogFilter
{
    EntityType = "Product",
    Action = EntityChangeType.Updated,
    FromDate = DateTime.UtcNow.AddDays(-7),
    ToDate = DateTime.UtcNow,
    UserId = specificUserId,
    TenantId = tenantId,
    Skip = 0,
    Take = 50
});

var result = await mediator.Send(query);
Console.WriteLine($"Found {result.TotalCount} records");
foreach (var log in result.Items)
{
    // Process results
}

Repository Direct Access

For scenarios where you need direct data access:

csharp
public class AuditReportService
{
    private readonly IAuditLogRepository _repository;

    public AuditReportService(IAuditLogRepository repository)
    {
        _repository = repository;
    }

    public async Task<IEnumerable<AuditLog>> GetRecentChangesAsync()
    {
        return await _repository.SearchAsync(new AuditLogFilter
        {
            FromDate = DateTime.UtcNow.AddHours(-24),
            Take = 100
        });
    }
}

Repository Methods

MethodDescription
GetByIdAsync(id)Get single audit log by ID
GetByEntityAsync(type, id)Get all logs for an entity
GetByUserAsync(userId)Get all logs for a user
SearchAsync(filter)Search with filter criteria

REST API

Get by ID

http
GET /api/auditlogs/{id}

Response:

json
{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "entityType": "Product",
  "entityId": "a1b2c3d4-...",
  "action": "Updated",
  "timestamp": "2026-02-07T10:30:00Z",
  "userId": "user123",
  "userName": "John Doe",
  "details": [
    {
      "propertyName": "Price",
      "oldValue": "99.99",
      "newValue": "149.99"
    }
  ]
}

Get Entity History

http
GET /api/auditlogs/entity/{entityType}/{entityId}

Example:

http
GET /api/auditlogs/entity/Product/a1b2c3d4-5678-90ab-cdef-123456789012

Get User's Logs

http
GET /api/auditlogs/user/{userId}

Search with Filters

http
GET /api/auditlogs/search?entityType=Product&action=Updated&fromDate=2026-02-01&toDate=2026-02-07&skip=0&take=50

Query Parameters:

ParameterTypeDescription
entityTypestringFilter by entity type name
entityIdGuidFilter by specific entity ID
actionstringFilter by action (Created, Updated, Deleted)
userIdstringFilter by user ID
tenantIdGuidFilter by tenant ID
fromDateDateTimeStart date (UTC)
toDateDateTimeEnd date (UTC)
skipintRecords to skip (pagination)
takeintRecords to take (max 100)

Filter Object

The AuditLogFilter class supports the following properties:

csharp
public class AuditLogFilter
{
    public string? EntityType { get; set; }
    public Guid? EntityId { get; set; }
    public EntityChangeType? Action { get; set; }
    public string? UserId { get; set; }
    public Guid? TenantId { get; set; }
    public DateTime? FromDate { get; set; }
    public DateTime? ToDate { get; set; }
    public int Skip { get; set; } = 0;
    public int Take { get; set; } = 50;
}

Search Results

The SearchAsync method returns an AuditLogSearchResult:

csharp
public class AuditLogSearchResult
{
    public IReadOnlyList<AuditLog> Items { get; set; }
    public int TotalCount { get; set; }
    public int Skip { get; set; }
    public int Take { get; set; }
}

Pagination Example

csharp
var pageSize = 20;
var currentPage = 1;

var result = await mediator.Send(new SearchAuditLogsQuery(new AuditLogFilter
{
    EntityType = "Order",
    Skip = (currentPage - 1) * pageSize,
    Take = pageSize
}));

var totalPages = (int)Math.Ceiling(result.TotalCount / (double)pageSize);
Console.WriteLine($"Page {currentPage} of {totalPages}");

Performance Tips

  1. Use Date Filters: Always specify FromDate and ToDate for large datasets
  2. Limit Results: Use Take to limit the number of returned records
  3. Index EntityType/EntityId: Ensure database indexes on frequently queried columns
  4. Archive Old Logs: Implement retention policies for historical data

Audit Log Details

Each AuditLog contains a collection of AuditLogDetail records showing property changes:

csharp
var log = await mediator.Send(new GetAuditLogByIdQuery(id));

foreach (var detail in log.Details)
{
    Console.WriteLine($"Property: {detail.PropertyName}");
    Console.WriteLine($"  Old: {detail.OldValue}");
    Console.WriteLine($"  New: {detail.NewValue}");
}

Released under the MIT License.