An OkHttp interceptor which logs HTTP request and response data
npx @tessl/cli install tessl/maven-com-squareup-okhttp3--logging-interceptor@4.12.00
# OkHttp Logging Interceptor
1
2
An OkHttp interceptor which logs HTTP request and response data with configurable logging levels and custom logger support. Provides comprehensive HTTP traffic monitoring for development and debugging.
3
4
## Package Information
5
6
- **Package Name**: logging-interceptor
7
- **Package Type**: Maven
8
- **Language**: Kotlin (with Java interop)
9
- **Installation**: `implementation("com.squareup.okhttp3:logging-interceptor:4.12.0")`
10
11
## Core Imports
12
13
```kotlin
14
import okhttp3.logging.HttpLoggingInterceptor
15
import okhttp3.logging.LoggingEventListener
16
```
17
18
Java:
19
```java
20
import okhttp3.logging.HttpLoggingInterceptor;
21
import okhttp3.logging.LoggingEventListener;
22
```
23
24
## Basic Usage
25
26
```kotlin
27
import okhttp3.OkHttpClient
28
import okhttp3.logging.HttpLoggingInterceptor
29
30
// Basic logging interceptor
31
val logging = HttpLoggingInterceptor()
32
logging.level = HttpLoggingInterceptor.Level.BODY
33
34
val client = OkHttpClient.Builder()
35
.addInterceptor(logging)
36
.build()
37
38
// Custom logger with header redaction
39
val customLogger = HttpLoggingInterceptor { message ->
40
println("HTTP: $message")
41
}
42
customLogger.level = HttpLoggingInterceptor.Level.HEADERS
43
customLogger.redactHeader("Authorization")
44
customLogger.redactHeader("Cookie")
45
46
val secureClient = OkHttpClient.Builder()
47
.addInterceptor(customLogger)
48
.build()
49
```
50
51
Java equivalent:
52
```java
53
import okhttp3.OkHttpClient;
54
import okhttp3.logging.HttpLoggingInterceptor;
55
56
// Basic logging interceptor
57
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
58
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
59
60
OkHttpClient client = new OkHttpClient.Builder()
61
.addInterceptor(logging)
62
.build();
63
64
// Custom logger with header redaction
65
HttpLoggingInterceptor customLogger = new HttpLoggingInterceptor(message -> {
66
System.out.println("HTTP: " + message);
67
});
68
customLogger.setLevel(HttpLoggingInterceptor.Level.HEADERS);
69
customLogger.redactHeader("Authorization");
70
customLogger.redactHeader("Cookie");
71
72
OkHttpClient secureClient = new OkHttpClient.Builder()
73
.addInterceptor(customLogger)
74
.build();
75
```
76
77
## Architecture
78
79
The library consists of two main components:
80
81
- **HttpLoggingInterceptor**: The primary interceptor that logs HTTP request/response data at configurable detail levels
82
- **LoggingEventListener**: An EventListener that provides detailed timing and connection-level event logging
83
- **Logger Interface**: Pluggable logging interface allowing custom output destinations
84
- **Level Configuration**: Four logging levels from silent to full body logging with header redaction
85
86
## Capabilities
87
88
### HTTP Request/Response Logging
89
90
Core interceptor functionality for logging HTTP traffic with configurable detail levels and header security.
91
92
```kotlin { .api }
93
class HttpLoggingInterceptor @JvmOverloads constructor(
94
private val logger: Logger = Logger.DEFAULT
95
) : Interceptor {
96
97
@set:JvmName("level")
98
@Volatile var level: Level
99
100
fun redactHeader(name: String): Unit
101
fun setLevel(level: Level): HttpLoggingInterceptor
102
103
@JvmName("-deprecated_level")
104
@Deprecated(
105
message = "moved to var",
106
replaceWith = ReplaceWith(expression = "level"),
107
level = DeprecationLevel.ERROR
108
)
109
fun getLevel(): Level
110
111
@Throws(IOException::class)
112
override fun intercept(chain: Interceptor.Chain): Response
113
}
114
```
115
116
**Logging Levels:**
117
118
```kotlin { .api }
119
enum class Level {
120
/** No logs. */
121
NONE,
122
123
/** Logs request and response lines only. */
124
BASIC,
125
126
/** Logs request and response lines and their respective headers. */
127
HEADERS,
128
129
/** Logs request and response lines, headers, and bodies (if present). */
130
BODY
131
}
132
```
133
134
**Usage Examples:**
135
136
```kotlin
137
// Different logging levels
138
val interceptor = HttpLoggingInterceptor()
139
140
// No logging
141
interceptor.level = HttpLoggingInterceptor.Level.NONE
142
143
// Basic: --> POST /api/users http/1.1 (45-byte body)
144
// <-- 201 Created (123ms, 78-byte body)
145
interceptor.level = HttpLoggingInterceptor.Level.BASIC
146
147
// Headers: includes all request/response headers
148
interceptor.level = HttpLoggingInterceptor.Level.HEADERS
149
150
// Body: includes request/response bodies (be careful with sensitive data)
151
interceptor.level = HttpLoggingInterceptor.Level.BODY
152
153
// Header redaction for security
154
interceptor.redactHeader("Authorization")
155
interceptor.redactHeader("Set-Cookie")
156
157
// Fluent API (useful for Java)
158
val configuredInterceptor = HttpLoggingInterceptor()
159
.setLevel(HttpLoggingInterceptor.Level.HEADERS)
160
```
161
162
### Custom Logger Implementation
163
164
Interface for directing log output to custom destinations like files, logging frameworks, or analytics systems.
165
166
```kotlin { .api }
167
fun interface Logger {
168
fun log(message: String): Unit
169
170
companion object {
171
/** A Logger that outputs to platform-appropriate default location. */
172
@JvmField
173
val DEFAULT: Logger
174
}
175
}
176
```
177
178
**Usage Examples:**
179
180
```kotlin
181
// File logging
182
val fileLogger = HttpLoggingInterceptor { message ->
183
File("http.log").appendText("$message\n")
184
}
185
186
// Integration with logging frameworks
187
val timberLogger = HttpLoggingInterceptor { message ->
188
Timber.tag("OkHttp").d(message)
189
}
190
191
// Structured logging
192
val structuredLogger = HttpLoggingInterceptor { message ->
193
logger.info("http_traffic") {
194
"message" to message
195
"timestamp" to Instant.now()
196
}
197
}
198
199
// Conditional logging
200
val debugLogger = HttpLoggingInterceptor { message ->
201
if (BuildConfig.DEBUG) {
202
println("HTTP: $message")
203
}
204
}
205
```
206
207
### Event-Level HTTP Logging
208
209
Detailed connection and call lifecycle event logging for advanced debugging and performance monitoring.
210
211
```kotlin { .api }
212
class LoggingEventListener private constructor(
213
private val logger: HttpLoggingInterceptor.Logger
214
) : EventListener() {
215
// Private constructor - use Factory to create instances
216
217
// Connection lifecycle events
218
override fun callStart(call: Call): Unit
219
override fun callEnd(call: Call): Unit
220
override fun callFailed(call: Call, ioe: IOException): Unit
221
override fun canceled(call: Call): Unit
222
223
// DNS and proxy events
224
override fun proxySelectStart(call: Call, url: HttpUrl): Unit
225
override fun proxySelectEnd(call: Call, url: HttpUrl, proxies: List<Proxy>): Unit
226
override fun dnsStart(call: Call, domainName: String): Unit
227
override fun dnsEnd(call: Call, domainName: String, inetAddressList: List<InetAddress>): Unit
228
229
// Connection events
230
override fun connectStart(call: Call, inetSocketAddress: InetSocketAddress, proxy: Proxy): Unit
231
override fun connectEnd(call: Call, inetSocketAddress: InetSocketAddress, proxy: Proxy, protocol: Protocol?): Unit
232
override fun connectFailed(call: Call, inetSocketAddress: InetSocketAddress, proxy: Proxy, protocol: Protocol?, ioe: IOException): Unit
233
override fun secureConnectStart(call: Call): Unit
234
override fun secureConnectEnd(call: Call, handshake: Handshake?): Unit
235
236
// Connection pool events
237
override fun connectionAcquired(call: Call, connection: Connection): Unit
238
override fun connectionReleased(call: Call, connection: Connection): Unit
239
240
// Request events
241
override fun requestHeadersStart(call: Call): Unit
242
override fun requestHeadersEnd(call: Call, request: Request): Unit
243
override fun requestBodyStart(call: Call): Unit
244
override fun requestBodyEnd(call: Call, byteCount: Long): Unit
245
override fun requestFailed(call: Call, ioe: IOException): Unit
246
247
// Response events
248
override fun responseHeadersStart(call: Call): Unit
249
override fun responseHeadersEnd(call: Call, response: Response): Unit
250
override fun responseBodyStart(call: Call): Unit
251
override fun responseBodyEnd(call: Call, byteCount: Long): Unit
252
override fun responseFailed(call: Call, ioe: IOException): Unit
253
254
// Cache events
255
override fun satisfactionFailure(call: Call, response: Response): Unit
256
override fun cacheHit(call: Call, response: Response): Unit
257
override fun cacheMiss(call: Call): Unit
258
override fun cacheConditionalHit(call: Call, cachedResponse: Response): Unit
259
}
260
```
261
262
**Factory for Event Listener Creation:**
263
264
```kotlin { .api }
265
open class Factory @JvmOverloads constructor(
266
private val logger: HttpLoggingInterceptor.Logger = HttpLoggingInterceptor.Logger.DEFAULT
267
) : EventListener.Factory {
268
override fun create(call: Call): EventListener
269
}
270
```
271
272
**Usage Examples:**
273
274
```kotlin
275
// Basic event logging
276
val eventLogger = LoggingEventListener.Factory()
277
val client = OkHttpClient.Builder()
278
.eventListenerFactory(eventLogger)
279
.build()
280
281
// Custom event logger
282
val customEventLogger = LoggingEventListener.Factory { message ->
283
println("Event: $message")
284
}
285
286
// Combined interceptor and event logging
287
val interceptor = HttpLoggingInterceptor()
288
interceptor.level = HttpLoggingInterceptor.Level.BASIC
289
290
val eventListener = LoggingEventListener.Factory()
291
292
val client = OkHttpClient.Builder()
293
.addInterceptor(interceptor)
294
.eventListenerFactory(eventListener)
295
.build()
296
297
// Performance monitoring
298
val performanceLogger = LoggingEventListener.Factory { message ->
299
if (message.contains("ms")) {
300
// Log timing events to analytics
301
analytics.track("http_timing", message)
302
}
303
}
304
```
305
306
## Types
307
308
```kotlin { .api }
309
// From OkHttp core (referenced types)
310
interface Interceptor {
311
@Throws(IOException::class)
312
fun intercept(chain: Chain): Response
313
314
interface Chain {
315
fun request(): Request
316
@Throws(IOException::class)
317
fun proceed(request: Request): Response
318
fun connection(): Connection?
319
}
320
}
321
322
abstract class EventListener {
323
interface Factory {
324
fun create(call: Call): EventListener
325
}
326
}
327
328
// Standard Java/Kotlin types used
329
import java.io.IOException
330
import java.net.InetAddress
331
import java.net.InetSocketAddress
332
import java.net.Proxy
333
import okhttp3.Call
334
import okhttp3.Connection
335
import okhttp3.Handshake
336
import okhttp3.HttpUrl
337
import okhttp3.Protocol
338
import okhttp3.Request
339
import okhttp3.Response
340
```
341
342
## Security Considerations
343
344
**Header Redaction:**
345
- Always redact sensitive headers like `Authorization`, `Cookie`, `Set-Cookie`
346
- Use `redactHeader()` method to prevent credential leakage
347
- Headers are redacted with `"██"` in logs
348
349
**Body Logging Security:**
350
- `Level.BODY` exposes full request/response content
351
- Only use in development/debugging environments
352
- Consider data privacy and compliance requirements
353
- Request bodies containing binary data are omitted automatically
354
355
**Production Usage:**
356
- Use `Level.NONE` or `Level.BASIC` in production
357
- Implement custom Logger to control log destination
358
- Be aware that logs may contain sensitive URLs and headers
359
360
```kotlin
361
// Secure production configuration
362
val productionLogger = HttpLoggingInterceptor { message ->
363
// Only log to secure, encrypted storage
364
secureLogger.info(message)
365
}
366
productionLogger.level = HttpLoggingInterceptor.Level.BASIC
367
productionLogger.redactHeader("Authorization")
368
productionLogger.redactHeader("Cookie")
369
productionLogger.redactHeader("Set-Cookie")
370
productionLogger.redactHeader("X-API-Key")
371
```