How to Configure and Leverage CoSky's Audit Logging Feature
CoSky's audit logging automatically records REST API requests to Redis and exposes them via a paginated HTTP endpoint for real-time dashboard monitoring.
CoSky provides a built-in audit logging mechanism that tracks every write-type request processed by the REST API. As implemented in the ahoo-wang/cosky repository, this feature stores logs in Redis under a system-wide key and surfaces them through a dedicated endpoint consumed by the dashboard UI. The implementation requires minimal configuration while providing comprehensive visibility into system operations.
Understanding CoSky's Audit Logging Architecture
CoSky's audit logging system consists of several coordinated components that capture, persist, and serve audit records.
Core Components
-
SecurityProperties: Holds the configuration flagauditLog.action(defaultWRITE) incosky-rest-api/src/main/kotlin/me/ahoo/cosky/rest/security/SecurityProperties.kt. When the request action matches the configuredAction, the interceptor generates an audit record. -
AuditLogHandlerInterceptor: A Spring WebFluxWebFilterimplemented incosky-rest-api/src/main/kotlin/me/ahoo/cosky/rest/security/audit/AuditLogHandlerInterceptor.kt. It runs after request processing to extract the operator, IP, path, HTTP method, status, and error message, then forwards the data toAuditLogService. -
AuditLogService: Persists audit entries to Redis usingReactiveStringRedisTemplateincosky-rest-api/src/main/kotlin/me/ahoo/cosky/rest/security/audit/AuditLogService.kt. It stores records in the list keyNamespaced.SYSTEM + ":audit:log"(e.g.,cosky:system:audit:log) and providesaddLog,queryLog, andtotaloperations. -
AuditLogController: Exposes the REST endpointGET /v1/audit-log(prefix defined inRequestPathPrefix.AUDIT_LOG_PREFIX) incosky-rest-api/src/main/kotlin/me/ahoo/cosky/rest/security/audit/AuditLogController.kt, returning paginatedQueryLogResponseobjects. -
Dashboard UI: The React component
AuditLogPage.tsxindashboard/src/pages/audit/AuditLogPage.tsxcalls the generated client to fetch logs and displays them in a paginated table.
Configuring Audit Logging in CoSky
Enable and customize audit logging through Spring Boot configuration properties.
Application Configuration
Add the cosky.security.audit-log.action property to your application.yaml:
cosky:
security:
audit-log:
# Allowed values: WRITE (default) | READ | ALL
action: WRITE
Action Types
WRITE: Records only write operations (POST, PUT, DELETE, PATCH). This is the default behavior.READ: Records only read operations (GET requests).ALL: Records every request regardless of HTTP method.
Redis Storage Configuration
Audit logs persist in the same Redis instance used by other CoSky modules. No additional configuration is required beyond standard Redis connection settings (cosky.redis.*). The system stores entries under the key pattern cosky:system:audit:log.
How CoSky Audit Logging Works
The audit logging pipeline executes automatically once enabled, requiring no manual intervention for standard REST operations.
Step 1: Request Interception
After the controller chain finishes processing an incoming request, AuditLogHandlerInterceptor.filter executes. The interceptor checks the configured auditLog.action against the current request method to determine if logging is required.
Step 2: Data Extraction
For qualifying requests, the interceptor extracts:
- Operator: From the JWT principal or authentication path (
/v1/authenticate/{username}) - Client IP: The remote address of the request
- Request Path: The accessed URI
- HTTP Method: The action type
- Response Status: The HTTP status code
- Error Message: Any error details if the request failed
Step 3: Redis Persistence
The interceptor builds an AuditLog instance and calls auditService.addLog(auditLog). The AuditLogService.addLog method serializes the record with Jackson and pushes it to the Redis list using leftPush to the key cosky:system:audit:log.
Step 4: Log Retrieval
The dashboard UI or external clients call GET /v1/audit-log?offset=0&limit=10. The AuditLogController aggregates the total count via auditService.total and retrieves paginated results via auditService.queryLog, returning a QueryLogResponse.
Querying and Consuming Audit Logs
Access audit data through multiple interfaces depending on your integration requirements.
Via REST API
Query logs directly using the paginated endpoint:
curl "http://localhost:8080/v1/audit-log?offset=0&limit=20" \
-H "Authorization: Bearer ${JWT_TOKEN}"
The endpoint returns a JSON QueryLogResponse containing the total count and log entries.
Via Generated TypeScript Client
For TypeScript applications, use the generated client in dashboard/src/generated/AuditLogApiClient.ts:
import { auditLogApiClient } from '@/generated/AuditLogApiClient';
async function fetchAuditLogs(page: number, size: number) {
const response = await auditLogApiClient.queryLog(page, size);
console.log('Total logs:', response.total);
return response.list;
}
// Fetch first 20 entries
fetchAuditLogs(0, 20);
Dashboard Integration
The built-in dashboard renders logs using the React component AuditLogPage.tsx. The component utilizes useQuery to fetch data via auditLogApiClient.queryLog and displays results in a paginated table with navigation controls.
Programmatic Audit Log Examples
Extend or customize audit logging using the service layer directly.
Adding Custom Audit Entries in Kotlin
Inject AuditLogService to manually log operations:
import me.ahoo.cosky.rest.security.audit.AuditLog
import me.ahoo.cosky.rest.security.audit.AuditLogService
import reactor.core.publisher.Mono
fun logCustomOperation(auditService: AuditLogService): Mono<Long> {
val log = AuditLog(
operator = "system",
ip = "127.0.0.1",
requestPath = "/custom/operation",
action = "POST",
status = 200,
msg = "Custom operation executed",
opTime = System.currentTimeMillis()
)
return auditService.addLog(log)
}
React Component Implementation
Implement custom audit log viewers using the generated types:
import React, { useState } from 'react';
import { useQuery } from 'react-query';
import { auditLogApiClient } from '../../generated';
import { QueryLogResponse, AuditLog } from '../../generated/types';
export const CustomAuditViewer: React.FC = () => {
const [page, setPage] = useState(0);
const pageSize = 10;
const { data } = useQuery<QueryLogResponse>(
['auditLog', page],
() => auditLogApiClient.queryLog(page, pageSize)
);
return (
<table>
<thead>
<tr>
<th>Operator</th>
<th>IP</th>
<th>Path</th>
<th>Status</th>
</tr>
</thead>
<tbody>
{data?.list.map((log: AuditLog) => (
<tr key={log.opTime}>
<td>{log.operator}</td>
<td>{log.ip}</td>
<td>{log.requestPath}</td>
<td>{log.status}</td>
</tr>
))}
</tbody>
</table>
);
};
Summary
- Configuration: Set
cosky.security.audit-log.actiontoWRITE,READ, orALLinapplication.yamlto control which requests generate audit records. - Storage: Audit logs persist in Redis under the key
cosky:system:audit:logusingAuditLogServicewith automatic serialization. - Capture:
AuditLogHandlerInterceptorautomatically intercepts requests and extracts operator, IP, path, method, status, and error details. - Access: Query logs via the
GET /v1/audit-logendpoint, the generated TypeScript client, or the built-in dashboard UI. - Customization: Use
AuditLogService.addLog()to programmatically insert custom audit entries from Kotlin code.
Frequently Asked Questions
Where are CoSky audit logs stored?
CoSky stores audit logs in Redis as a list under the system-wide key cosky:system:audit:log. The AuditLogService class in cosky-rest-api/src/main/kotlin/me/ahoo/cosky/rest/security/audit/AuditLogService.kt handles persistence using ReactiveStringRedisTemplate, pushing serialized JSON entries via leftPush operations.
How do I enable audit logging for read operations in CoSky?
Set the property cosky.security.audit-log.action to READ or ALL in your application.yaml. The default value is WRITE, which only captures POST, PUT, DELETE, and PATCH requests. Changing this configuration in SecurityProperties.kt instructs AuditLogHandlerInterceptor to also log GET requests or all HTTP methods respectively.
What is the default action type for CoSky audit logging?
The default action type is WRITE, configured in SecurityProperties.kt. This means only mutating HTTP methods (POST, PUT, DELETE, PATCH) generate audit records by default. This setting minimizes log volume while capturing the most critical state-changing operations.
How can I query CoSky audit logs programmatically?
Use the GET /v1/audit-log endpoint exposed by AuditLogController.kt with offset and limit query parameters for pagination. For type-safe access, import the generated AuditLogApiClient.ts from dashboard/src/generated/, which provides the queryLog(page, size) method returning a QueryLogResponse containing the total count and list of AuditLog entries.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →