A flexible, configurable logging middleware for OpenAPI client and server implementations with support for console, file, and OSLog logging.
- β
Dual Parameter System: Separate
appNameandlogPrefixfor clean file naming and formatted console output - β
Client & Server Support: Works with both
ClientMiddlewareandServerMiddleware - β Configurable Body Logging: Control how much request/response body data to log
- β Multiple Log Handlers: Simultaneous console (stream), JSON file, and OSLog logging
- β OSLog Integration: Native Apple unified logging system support (macOS 11+, iOS 14+)
- β Automatic File Naming: Generates clean filenames from app name and prefix
import OpenAPILoggingMiddleware
// Client logging
let clientMiddleware = LoggingMiddleware(
appName: "NSSpainAPI",
logPrefix: "π APIClient: "
)
// Server logging
let serverMiddleware = await LoggingMiddleware(
appName: "NSSpainAPI",
logPrefix: "π₯οΈ ApiServer: "
)let middleware = LoggingMiddleware(
logger: customLogger, // Optional custom logger
bodyLoggingConfiguration: .upTo(maxBytes: 2_000_000), // Log bodies up to 2MB
appName: "MyApp", // App identifier for files
logPrefix: "π§ Service: " // Console output prefix
)The middleware automatically generates clean, organized log file names:
| appName | logPrefix | File Names |
|---|---|---|
"NSSpainAPI" |
"π APIClient: " |
_NSSpainAPI_APIClient.json, _NSSpainAPI_APIClient.log |
"NSSpainAPI" |
"π₯οΈ ApiServer: " |
_NSSpainAPI_ApiServer.json, _NSSpainAPI_ApiServer.log |
"MyApp" |
"Client: " |
_MyApp_Client.json, _MyApp_Client.log |
nil |
"π APIClient: " |
_APIClient.json, _APIClient.log |
nil |
"" |
_OpenAPILog.json, _OpenAPILog.log |
- With both appName and logPrefix:
_<appName>_<cleanPrefix>.<ext> - With appName only:
_<appName>.<ext> - With logPrefix only:
_<cleanPrefix>.<ext> - Neither provided:
_OpenAPILog.<ext>(default)
Clean names are generated by:
- Trimming whitespace
- Removing spaces from prefix
- Filtering to ASCII letters and numbers (removes emojis)
Uses the logPrefix as-is for visual distinction:
π APIClient: `method` = `GET`
π APIClient: `path` = `/user/me`
π APIClient: `statusCode` = `200`
Structured JSON logs saved to Documents directory:
[
{
"timestamp": "16.10.2025. 14:30:45",
"method": "GET",
"path": "/user/me",
"statusCode": "200",
"responseBody": "{...}"
}
]Native Apple unified logging system integration. Logs appear in:
- Console.app on macOS
- Xcode Console during development
- System log database for persistent storage
Subsystem: com.openapi
Category: logging-middleware
Method 1: Terminal (Recommended for Development)
Open Terminal and run:
# Stream ALL logs from the middleware in real-time
log stream --predicate 'subsystem == "com.openapi"' --level debugThis will show logs as they happen - you'll see each API request/response immediately.
Additional real-time filters:
# Filter by specific prefix (e.g., only APIClient logs)
log stream --predicate 'subsystem == "com.openapi" AND eventMessage CONTAINS "APIClient"' --level debug
# Show only errors in real-time
log stream --predicate 'subsystem == "com.openapi"' --level error
# Filter by specific HTTP method
log stream --predicate 'subsystem == "com.openapi" AND eventMessage CONTAINS "GET"' --level debugMethod 2: Console.app (GUI)
For a visual real-time log viewer:
- Open Console.app (press
β+Space, type "Console", press Enter) - In the left sidebar, select your Mac under "Devices"
- In the search field (top-right), type:
subsystem:com.openapi - Click the "Start" button to begin streaming logs in real-time
- Logs will appear live as your app makes API calls
Tip: Keep Console.app open while running your app to see all logs in real-time with syntax highlighting!
View past logs in Terminal:
# Show logs from the last hour
log show --predicate 'subsystem == "com.openapi"' --last 1h
# Show logs with specific text
log show --predicate 'subsystem == "com.openapi" AND eventMessage CONTAINS "GET"' --last 30m
# Export logs to a file
log show --predicate 'subsystem == "com.openapi"' --last 1d --style json > logs.jsonLog Level Mapping:
| swift-log Level | OSLog Type | Console.app Display |
|---|---|---|
.trace |
.debug |
Debug |
.debug |
.debug |
Debug |
.info |
.info |
Info |
.notice |
.default |
Default |
.warning |
.error |
Error |
.error |
.error |
Error |
.critical |
.fault |
Fault |
Privacy & Performance:
- OSLog is highly optimized for performance
- Logs are stored in a compressed binary format
- Automatic log rotation and retention policies
- System-level privacy controls for sensitive data
The middleware uses a MultiplexLogHandler to direct log output to multiple destinations simultaneously. By default, it's configured with:
StreamLogHandler: Prints formatted logs to the console (stdout).JSONFileLogHandler: Saves structured JSON logs to a file in the app's Documents directory.OSLogHandler: Sends logs to Apple's unified logging system (macOS 11+, iOS 14+).
This architecture makes it easy to:
- Monitor logs in real-time during development (console & OSLog)
- Persist structured logs for analysis (JSON files)
- Integrate with system-level logging tools (Console.app,
logcommand) - Debug production issues using native Apple tools
Control how request/response bodies are logged:
// Never log bodies (for sensitive data)
.never
// Log bodies up to specified size (default: 2MB)
.upTo(maxBytes: 1024 * 1024 * 2)Each log entry includes:
- HTTP method
- Request path
- Base URL and full path
- Request/response headers (JSON format)
- Request/response body (based on policy)
- Operation ID
- Status code and reason
- Error information (if failed)
- Unique identifier per request
Log files are saved to the system Documents directory:
- iOS/macOS:
~/Documents/ - JSON logs:
_<appName>_<prefix>.json
- Stream logs: Output to
stdout(Xcode Console, Terminal)
- System database: Managed by
logddaemon - Location:
/var/db/diagnostics/(system-managed, not user-accessible) - Access: Use
Console.apporlogcommand (see Viewing OSLog Output)
self.loggingMiddleware = LoggingMiddleware(
appName: "NSSpainAPI",
logPrefix: "π APIClient: "
)
self.client = Client(
serverURL: serverURL,
transport: transport,
middlewares: [loggingMiddleware, authMiddleware]
)let loggingMiddleware = await LoggingMiddleware(
appName: "NSSpainAPI",
logPrefix: "π₯οΈ ApiServer: "
)
try handler.registerHandlers(
on: transport,
serverURL: serverURL,
middlewares: [loggingMiddleware]
)The LoggingMiddleware is an actor, ensuring thread-safe operation across concurrent requests.
swift-openapi-runtime- OpenAPI runtime supportswift-log- Logging backendHTTPTypes- HTTP types