-
Notifications
You must be signed in to change notification settings - Fork 9.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Document debug logging. #5671
Merged
+307
−139
Merged
Document debug logging. #5671
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
53 changes: 53 additions & 0 deletions
53
android-test/src/androidTest/java/okhttp/android/test/OkHttpDebugLogcat.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
/* | ||
* Copyright (C) 2019 Square, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package okhttp.android.test | ||
|
||
import android.util.Log | ||
import okhttp3.internal.concurrent.TaskRunner | ||
import okhttp3.internal.http2.Http2 | ||
import java.util.concurrent.CopyOnWriteArraySet | ||
import java.util.logging.Handler | ||
import java.util.logging.Level | ||
import java.util.logging.LogRecord | ||
import java.util.logging.Logger | ||
import kotlin.reflect.KClass | ||
|
||
object OkHttpDebugLogcat { | ||
// Keep references to loggers to prevent their configuration from being GC'd. | ||
private val configuredLoggers = CopyOnWriteArraySet<Logger>() | ||
|
||
fun enableHttp2() = enable(Http2::class) | ||
|
||
fun enableTaskRunner() = enable(TaskRunner::class) | ||
|
||
private fun enable(loggerClass: KClass<*>) { | ||
val logger = Logger.getLogger(loggerClass.java.name) | ||
if (configuredLoggers.add(logger)) { | ||
logger.level = Level.FINE | ||
logger.addHandler(object : Handler() { | ||
override fun publish(record: LogRecord) { | ||
Log.i(loggerClass.simpleName, record.message, record.thrown) | ||
} | ||
|
||
override fun flush() { | ||
} | ||
|
||
override fun close() { | ||
} | ||
}) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
Debug Logging | ||
============= | ||
|
||
OkHttp has internal APIs to enable debug logging. It uses the `java.util.logging` API which can be | ||
tricky to configure. As a shortcut, you can paste [OkHttpDebugLogging.kt]. Then enable debug logging | ||
for whichever features you need: | ||
|
||
``` | ||
OkHttpDebugLogging.enableHttp2() | ||
OkHttpDebugLogging.enableTaskRunner() | ||
``` | ||
|
||
On Android, use [OkHttpDebugLogcat.kt] instead. It connects OkHttp logs to Logcat in Android Studio. | ||
|
||
### HTTP/2 Frame Logging | ||
|
||
This logs inbound (`<<`) and outbound (`>>`) frames for HTTP/2 connections. | ||
|
||
``` | ||
[2020-01-01 00:00:00] >> CONNECTION 505249202a20485454502f322e300d0a0d0a534d0d0a0d0a | ||
[2020-01-01 00:00:00] >> 0x00000000 6 SETTINGS | ||
[2020-01-01 00:00:00] >> 0x00000000 4 WINDOW_UPDATE | ||
[2020-01-01 00:00:00] >> 0x00000003 47 HEADERS END_STREAM|END_HEADERS | ||
[2020-01-01 00:00:00] << 0x00000000 6 SETTINGS | ||
[2020-01-01 00:00:00] << 0x00000000 0 SETTINGS ACK | ||
[2020-01-01 00:00:00] << 0x00000000 4 WINDOW_UPDATE | ||
[2020-01-01 00:00:00] >> 0x00000000 0 SETTINGS ACK | ||
[2020-01-01 00:00:00] << 0x00000003 322 HEADERS END_HEADERS | ||
[2020-01-01 00:00:00] << 0x00000003 288 DATA | ||
[2020-01-01 00:00:00] << 0x00000003 0 DATA END_STREAM | ||
[2020-01-01 00:00:00] << 0x00000000 8 GOAWAY | ||
[2020-01-01 00:00:05] << 0x00000000 8 GOAWAY | ||
``` | ||
|
||
### Task Runner Logging | ||
|
||
This logs task enqueues, starts, and finishes. | ||
|
||
``` | ||
[2020-01-01 00:00:00] Q10000 scheduled after 0 µs: OkHttp ConnectionPool | ||
[2020-01-01 00:00:00] Q10000 starting : OkHttp ConnectionPool | ||
[2020-01-01 00:00:00] Q10000 run again after 300 s : OkHttp ConnectionPool | ||
[2020-01-01 00:00:00] Q10000 finished run in 1 ms: OkHttp ConnectionPool | ||
[2020-01-01 00:00:00] Q10001 scheduled after 0 µs: OkHttp squareup.com applyAndAckSettings | ||
[2020-01-01 00:00:00] Q10001 starting : OkHttp squareup.com applyAndAckSettings | ||
[2020-01-01 00:00:00] Q10003 scheduled after 0 µs: OkHttp squareup.com onSettings | ||
[2020-01-01 00:00:00] Q10003 starting : OkHttp squareup.com onSettings | ||
[2020-01-01 00:00:00] Q10001 finished run in 3 ms: OkHttp squareup.com applyAndAckSettings | ||
[2020-01-01 00:00:00] Q10003 finished run in 528 µs: OkHttp squareup.com onSettings | ||
[2020-01-01 00:00:00] Q10000 scheduled after 0 µs: OkHttp ConnectionPool | ||
[2020-01-01 00:00:00] Q10000 starting : OkHttp ConnectionPool | ||
[2020-01-01 00:00:00] Q10000 run again after 300 s : OkHttp ConnectionPool | ||
[2020-01-01 00:00:00] Q10000 finished run in 739 µs: OkHttp ConnectionPool | ||
``` | ||
|
||
[OkHttpDebugLogging.kt]: https://github.com/square/okhttp/blob/master/okhttp-testing-support/src/main/java/okhttp3/OkHttpDebugLogging.kt | ||
[OkHttpDebugLogcat.kt]: https://github.com/square/okhttp/blob/master/android-test/src/androidTest/java/okhttp/android/test/OkHttpDebugLogcat.kt |
49 changes: 49 additions & 0 deletions
49
okhttp-testing-support/src/main/java/okhttp3/OkHttpDebugLogging.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
/* | ||
* Copyright (C) 2019 Square, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package okhttp3 | ||
|
||
import okhttp3.internal.concurrent.TaskRunner | ||
import okhttp3.internal.http2.Http2 | ||
import java.util.concurrent.CopyOnWriteArraySet | ||
import java.util.logging.ConsoleHandler | ||
import java.util.logging.Level | ||
import java.util.logging.LogRecord | ||
import java.util.logging.Logger | ||
import java.util.logging.SimpleFormatter | ||
import kotlin.reflect.KClass | ||
|
||
object OkHttpDebugLogging { | ||
// Keep references to loggers to prevent their configuration from being GC'd. | ||
private val configuredLoggers = CopyOnWriteArraySet<Logger>() | ||
|
||
fun enableHttp2() = enable(Http2::class) | ||
|
||
fun enableTaskRunner() = enable(TaskRunner::class) | ||
|
||
private fun enable(loggerClass: KClass<*>) { | ||
val logger = Logger.getLogger(loggerClass.java.name) | ||
if (configuredLoggers.add(logger)) { | ||
logger.addHandler(ConsoleHandler().apply { | ||
level = Level.FINE | ||
formatter = object : SimpleFormatter() { | ||
override fun format(record: LogRecord) = | ||
String.format("[%1\$tF %1\$tT] %2\$s %n", record.millis, record.message) | ||
} | ||
}) | ||
logger.level = Level.FINE | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -48,30 +48,34 @@ internal inline fun <T> logElapsed( | |
if (loggingEnabled) { | ||
val elapsedNs = queue.taskRunner.backend.nanoTime() - startNs | ||
if (completedNormally) { | ||
log(task, queue, "finished in ${formatDuration(elapsedNs)}") | ||
log(task, queue, "finished run in ${formatDuration(elapsedNs)}") | ||
} else { | ||
log(task, queue, "failed in ${formatDuration(elapsedNs)}") | ||
log(task, queue, "failed a run in ${formatDuration(elapsedNs)}") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. carefully chosen words to get the right width! |
||
} | ||
} | ||
} | ||
} | ||
|
||
private fun log(task: Task, queue: TaskQueue, message: String) { | ||
TaskRunner.logger.fine("${queue.name} $message: ${task.name}") | ||
TaskRunner.logger.fine("${queue.name} ${String.format("%-22s", message)}: ${task.name}") | ||
} | ||
|
||
/** | ||
* Returns a duration in the nearest whole-number units like "999 µs" or "1 ms". This rounds 0.5 | ||
* Returns a duration in the nearest whole-number units like "999 µs" or " 1 s ". This rounds 0.5 | ||
* units away from 0 and 0.499 towards 0. The smallest unit this returns is "µs"; the largest unit | ||
* it returns is "s". For values in [-499..499] this returns "0 µs". | ||
* it returns is "s". For values in [-499..499] this returns " 0 µs". | ||
* | ||
* The returned string attempts to be column-aligned to 6 characters. For negative and large values | ||
* the returned string may be longer. | ||
*/ | ||
fun formatDuration(ns: Long): String { | ||
return when { | ||
ns <= -999_500_000 -> "${(ns - 500_000_000) / 1_000_000_000} s" | ||
val s = when { | ||
ns <= -999_500_000 -> "${(ns - 500_000_000) / 1_000_000_000} s " | ||
ns <= -999_500 -> "${(ns - 500_000) / 1_000_000} ms" | ||
ns <= 0 -> "${(ns - 500) / 1_000} µs" | ||
ns < 999_500 -> "${(ns + 500) / 1_000} µs" | ||
ns < 999_500_000 -> "${(ns + 500_000) / 1_000_000} ms" | ||
else -> "${(ns + 500_000_000) / 1_000_000_000} s" | ||
else -> "${(ns + 500_000_000) / 1_000_000_000} s " | ||
} | ||
return String.format("%6s", s) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably worth a sentence on Android, example logcat filter etc?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added. Turns out hooking up logcat to java.util.Logging nicely is a bit of a pain if you want to use
FINE
!There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Good idea though!)