Understanding Audit Log Providers
An audit log provider implements methods to log and query data changes:Quick Setup
interface AuditLog {
id: string;
resource: string;
action: string;
data?: any;
previousData?: any;
author?: {
id: string;
name: string;
};
timestamp: Date;
meta?: Record<string, any>;
}
const auditLogs: AuditLog[] = [];
export const auditLogService = {
create: async (log: Omit<AuditLog, "id" | "timestamp">) => {
const newLog: AuditLog = {
...log,
id: Date.now().toString(),
timestamp: new Date(),
};
auditLogs.push(newLog);
return newLog;
},
get: async (filters: Partial<AuditLog>) => {
return auditLogs.filter((log) => {
if (filters.resource && log.resource !== filters.resource) return false;
if (filters.action && log.action !== filters.action) return false;
if (filters.author && log.author?.id !== filters.author.id) return false;
return true;
});
},
getAll: () => auditLogs,
};
import { AuditLogProvider } from "@refinedev/core";
export const auditLogProvider: AuditLogProvider = {
create: async (params) => {
const { resource, action, data, author, meta } = params;
await fetch("http://localhost:3001/audit-logs", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
resource,
action,
data,
author,
meta,
timestamp: new Date(),
}),
});
},
get: async (params) => {
const { resource, action, author, meta } = params;
const queryParams = new URLSearchParams();
if (resource) queryParams.append("resource", resource);
if (action) queryParams.append("action", action);
if (author?.id) queryParams.append("authorId", author.id);
const response = await fetch(
`http://localhost:3001/audit-logs?${queryParams}`
);
return response.json();
},
update: async (params) => {
const { id, name } = params;
await fetch(`http://localhost:3001/audit-logs/${id}`, {
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name }),
});
return { id, name };
},
};
Automatic Logging
With an audit log provider configured, Refine automatically logs all CRUD operations:Create Operations
Update Operations
Delete Operations
Viewing Audit Logs
useLog Hook
Query audit logs in your components:Resource-Specific Logs
User Activity
Custom Logging
useLogList Hook
Manually log custom events:Login/Logout Tracking
Advanced Features
Diff Tracking
Track what changed in updates:Sensitive Data Masking
Batch Operations
Retention Policies
Visualization
Activity Timeline
Activity Chart
Compliance Features
GDPR Data Export
Data Deletion
Best Practices
- Log meaningful actions - Focus on important operations
- Include context - Store relevant metadata
- Mask sensitive data - Don’t log passwords or PII
- Set retention policies - Comply with regulations
- Index properly - Optimize database queries
- Monitor storage - Audit logs can grow large
- Implement access control - Protect audit log access
- Use async logging - Don’t block operations
- Test thoroughly - Ensure logs are reliable
- Document your schema - Make logs searchable
Security Considerations
Tamper-Proof Logs
Access Control
Troubleshooting
Logs Not Being Created
- Verify audit log provider is configured
- Check network requests for errors
- Ensure backend endpoint is working
- Check for JavaScript errors
Performance Issues
- Implement batching for high-volume operations
- Use async logging (don’t await)
- Add database indexes
- Consider using a dedicated logging service
Storage Growth
- Implement retention policies
- Archive old logs
- Compress stored data
- Use time-series databases
Next Steps
- Learn about Authentication
- Explore Data Providers
- Discover Access Control