|
10 | 10 | import io.github.easy4j.opencode.exception.OpenCodeHttpException; |
11 | 11 | import lombok.extern.slf4j.Slf4j; |
12 | 12 | import okhttp3.*; |
| 13 | +import okhttp3.extension.logging.HttpLogLevel; |
13 | 14 | import org.slf4j.Logger; |
14 | 15 | import org.slf4j.LoggerFactory; |
15 | 16 |
|
@@ -78,11 +79,13 @@ public OpenCodeHttpClient(OpenCodeHttpClientConfig config, ObjectMapper objectMa |
78 | 79 | this.objectMapper = Objects.isNull(objectMapper) ? new ObjectMapper() |
79 | 80 | .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false): objectMapper; |
80 | 81 | this.httpClient = Objects.isNull(httpClient) ? buildOkHttpClient(config) : httpClient; |
81 | | - log.debug("OpenCode HTTP client initialized: baseUrl={}, connectTimeoutMs={}, readTimeoutMs={}, " |
82 | | - + "callTimeoutMs={}, retryOnConnectionFailure={}, detailedLoggingEnabled={}", |
83 | | - config.getBaseUrl(), config.getConnectTimeoutMillis(), config.getReadTimeoutMillis(), |
84 | | - config.getCallTimeoutMillis(), config.isRetryOnConnectionFailure(), |
85 | | - config.isDetailedLoggingEnabled()); |
| 82 | + if (allows(HttpLogLevel.BASIC)) { |
| 83 | + log.debug("OpenCode HTTP client initialized: baseUrl={}, connectTimeoutMs={}, readTimeoutMs={}, " |
| 84 | + + "callTimeoutMs={}, retryOnConnectionFailure={}, debugLevel={}", |
| 85 | + config.getBaseUrl(), config.getConnectTimeoutMillis(), config.getReadTimeoutMillis(), |
| 86 | + config.getCallTimeoutMillis(), config.isRetryOnConnectionFailure(), |
| 87 | + config.getDebug().getLevel()); |
| 88 | + } |
86 | 89 | } |
87 | 90 |
|
88 | 91 | private static OkHttpClient buildOkHttpClient(OpenCodeHttpClientConfig config) { |
@@ -443,8 +446,10 @@ public CompletableFuture<String> ensureSessionAsync(String sessionKey, OpenCodeR |
443 | 446 | } |
444 | 447 | throw new CompletionException(cause); |
445 | 448 | } |
446 | | - log.debug("findSessionByTitle failed, sessionKey={}, error={}", |
447 | | - sessionKey, error.getMessage()); |
| 449 | + if (allows(HttpLogLevel.BASIC)) { |
| 450 | + log.debug("findSessionByTitle failed, sessionKey={}, error={}", |
| 451 | + sessionKey, error.getMessage()); |
| 452 | + } |
448 | 453 | return Optional.<Session>empty(); |
449 | 454 | } |
450 | 455 | return sessions.stream().filter(session -> Objects.equals(sessionKey, session.getTitle())) |
@@ -1448,7 +1453,9 @@ private void closeRegistration(AutoCloseable registration) { |
1448 | 1453 | try { |
1449 | 1454 | registration.close(); |
1450 | 1455 | } catch (Exception error) { |
1451 | | - log.debug("Failed to unregister HTTP cancellation callback: {}", error.getMessage()); |
| 1456 | + if (allows(HttpLogLevel.BASIC)) { |
| 1457 | + log.debug("Failed to unregister HTTP cancellation callback: {}", error.getMessage()); |
| 1458 | + } |
1452 | 1459 | } |
1453 | 1460 | } |
1454 | 1461 |
|
@@ -1543,20 +1550,25 @@ private boolean isSuccessful() { |
1543 | 1550 |
|
1544 | 1551 | private long beginTrace(Request request) { |
1545 | 1552 | long requestId = REQUEST_SEQUENCE.incrementAndGet(); |
1546 | | - log.debug("HTTP request started: requestId={}, method={}, url={}", |
1547 | | - requestId, request.method(), request.url()); |
1548 | | - if (config.isDetailedLoggingEnabled()) { |
1549 | | - // 详细日志默认关闭;开启后仍对认证头、token 和 key 脱敏,并限制正文长度。 |
1550 | | - log.debug("HTTP request details: requestId={}, headers={}, body={}", requestId, |
1551 | | - redactHeaders(request.headers()), requestBody(request)); |
| 1553 | + if (allows(HttpLogLevel.BASIC)) { |
| 1554 | + log.debug("HTTP request started: requestId={}, method={}, url={}", |
| 1555 | + requestId, request.method(), request.url()); |
| 1556 | + } |
| 1557 | + if (allows(HttpLogLevel.HEADERS)) { |
| 1558 | + log.debug("HTTP request headers: requestId={}, headers={}", requestId, redactHeaders(request.headers())); |
| 1559 | + } |
| 1560 | + if (allows(HttpLogLevel.BODY)) { |
| 1561 | + log.debug("HTTP request body: requestId={}, body={}", requestId, requestBody(request)); |
1552 | 1562 | } |
1553 | 1563 | return requestId; |
1554 | 1564 | } |
1555 | 1565 |
|
1556 | 1566 | private void logResponse(long requestId, Request request, int status, String body, long startedAt) { |
1557 | | - log.debug("HTTP request completed: requestId={}, method={}, url={}, status={}, bodyLength={}, elapsedMs={}", |
1558 | | - requestId, request.method(), request.url(), status, body.length(), elapsedMillis(startedAt)); |
1559 | | - if (config.isDetailedLoggingEnabled()) { |
| 1567 | + if (allows(HttpLogLevel.BASIC)) { |
| 1568 | + log.debug("HTTP request completed: requestId={}, method={}, url={}, status={}, bodyLength={}, elapsedMs={}", |
| 1569 | + requestId, request.method(), request.url(), status, body.length(), elapsedMillis(startedAt)); |
| 1570 | + } |
| 1571 | + if (allows(HttpLogLevel.BODY)) { |
1560 | 1572 | log.debug("HTTP response body: requestId={}, body={}", requestId, truncate(body)); |
1561 | 1573 | } |
1562 | 1574 | } |
@@ -1584,16 +1596,20 @@ private String requestBody(Request request) { |
1584 | 1596 | } |
1585 | 1597 |
|
1586 | 1598 | private String truncate(String value) { |
1587 | | - int limit = Math.max(0, config.getMaxLoggedBodyLength()); |
| 1599 | + int limit = config.getDebug().resolveMaxContentLength(); |
1588 | 1600 | return value.length() <= limit ? value : value.substring(0, limit) + "...<truncated>"; |
1589 | 1601 | } |
1590 | 1602 |
|
| 1603 | + private boolean allows(HttpLogLevel level) { |
| 1604 | + return config.getDebug().allows(level); |
| 1605 | + } |
| 1606 | + |
1591 | 1607 | private Headers redactHeaders(Headers headers) { |
1592 | 1608 | Headers.Builder safe = headers.newBuilder(); |
1593 | 1609 | for (String name : headers.names()) { |
1594 | 1610 | String lowerName = name.toLowerCase(); |
1595 | 1611 | if ("authorization".equals(lowerName) || lowerName.contains("token") || lowerName.contains("key")) { |
1596 | | - safe.set(name, "██"); |
| 1612 | + safe.set(name, "<redacted>"); |
1597 | 1613 | } |
1598 | 1614 | } |
1599 | 1615 | return safe.build(); |
|
0 commit comments