Skip to content

Commit 1a8eaf0

Browse files
author
yuguo.dtpe
committed
feature(debugger): add debug info
1 parent 221c173 commit 1a8eaf0

File tree

9 files changed

+503
-17
lines changed

9 files changed

+503
-17
lines changed

SDK_Integration_zh.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
- [自定义退避策略](#自定义退避策略)
2929
- [异常处理](#异常处理)
3030
- [Debug机制](#debug机制)
31+
- [开启Debug模式](#开启debug模式)
32+
- [设置Debug级别](#设置debug级别)
3133
- [指定日志Logger](#指定日志logger)
3234

3335
# 集成SDK
@@ -293,6 +295,7 @@ except ApiException as e:
293295
## 配置Http(s)代理
294296

295297
```python
298+
import volcenginesdkcore,volcenginesdkecs
296299
configuration = volcenginesdkcore.Configuration()
297300
configuration.ak = "Your AK"
298301
configuration.sk = "Your SK"
@@ -563,6 +566,8 @@ except Exception as e:
563566

564567
为便于客户在处理请求时进行问题排查和调试,SDK 支持日志功能,并提供多种日志级别设置。客户可根据实际需求配置日志级别,获取详细的请求与响应信息,以提升排障效率和系统可 observability(可观测性)。
565568

569+
## 开启Debug模式
570+
566571
> **默认**
567572
> * `debug` - `False`
568573
@@ -576,6 +581,39 @@ configuration.debug = True # 开启debug模式
576581
volcenginesdkcore.Configuration.set_default(configuration)
577582
```
578583

584+
## 设置debug级别
585+
默认情况下开启debug日志后,会输出所有的debug日志;为了按需输出日志,可以调用`configuration.log_level`进行以下设置:
586+
587+
```python
588+
import volcenginesdkcore
589+
from volcenginesdkcore.observability.debugger import LogLevel
590+
configuration = volcenginesdkcore.Configuration()
591+
configuration.ak = "Your AK"
592+
configuration.sk = "Your SK"
593+
configuration.debug = True # 开启debug模式
594+
configuration.log_level = LogLevel.LOG_DEBUG_WITH_CONFIG.mask | LogLevel.LOG_DEBUG_WITH_REQUEST.mask | LogLevel.LOG_DEBUG_WITH_RESPONSE.mask
595+
volcenginesdkcore.Configuration.set_default(configuration)
596+
597+
```
598+
599+
**支持的日志级别**
600+
601+
602+
| 枚举项 | 父级日志(同时打印父级日志) | 打印的内容 |
603+
| -------------------------------- |-----|--------------------------------------|
604+
| `LOG_DEBUG_WITH_REQUEST` || 请求行与基础请求信息:`HTTP方法``URL(含查询参数)``请求头` |
605+
| `LOG_DEBUG_WITH_REQUEST_BODY` | `LOG_DEBUG_WITH_REQUEST` | `请求体` |
606+
| `LOG_DEBUG_WITH_REQUEST_ID` | `LOG_DEBUG_WITH_REQUEST` | `RequestId` |
607+
| `LOG_DEBUG_WITH_RESPONSE` | `LOG_DEBUG_WITH_REQUEST` | `响应状态码` `响应头` |
608+
| `LOG_DEBUG_WITH_RESPONSE_BODY` | `LOG_DEBUG_WITH_RESPONSE` | `响应体` |
609+
| `LOG_DEBUG_WITH_SIGNING` | `LOG_DEBUG_WITH_REQUEST` | `签名过程` |
610+
| `LOG_DEBUG_WITH_ENDPOINT` | `LOG_DEBUG_WITH_REQUEST` | ` Endpoint 选择过程` |
611+
| `LOG_DEBUG_WITH_REQUEST_RETRIES` | `LOG_DEBUG_WITH_REQUEST` | `重试信息` |
612+
| `LOG_DEBUG_WITH_CONFIG` | `LOG_DEBUG_WITH_REQUEST` | `关键配置信息` |
613+
| `LOG_DEBUG_ALL` || `包含上面所有信息` |
614+
615+
616+
579617
# 指定日志Logger
580618

581619
> **默认**

volcenginesdkcore/api_client.py

Lines changed: 73 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
from __future__ import absolute_import
44

55
import datetime
6-
import logging
76
from multiprocessing.pool import ThreadPool
87
from time import sleep
98

@@ -17,9 +16,7 @@
1716
from volcenginesdkcore.interceptor import DeserializedResponseInterceptor
1817
from volcenginesdkcore.interceptor import InterceptorChain, InterceptorContext
1918
from volcenginesdkcore.interceptor import Request, Response
20-
21-
logger = logging.getLogger(__name__)
22-
19+
from volcenginesdkcore.observability.debugger import sdk_core_logger, LogLevel
2320

2421
class ApiClient(object):
2522
"""Generic API client for Swagger client library builds.
@@ -126,6 +123,8 @@ def __call_api(
126123

127124
interceptor_context = self.interceptor_chain.execute_request(interceptor_context)
128125

126+
self._log_config(interceptor_context.get_request())
127+
129128
retry_count = 0
130129
response_data = None
131130
retry_err = None
@@ -145,7 +144,7 @@ def __call_api(
145144
_request_timeout=interceptor_context.request.request_timeout)
146145
self.last_response = response_data
147146
except Exception as e:
148-
logger.warning("request error: {}".format(e))
147+
sdk_core_logger.warning("request error: {}".format(e))
149148
retry_err = e
150149
if retry_count >= num_max_retries:
151150
raise e
@@ -171,7 +170,7 @@ def request_retry(self, response_data, retry_count, retry_err, retryer):
171170
delay = retryer.get_backoff_delay(retry_count)
172171
sleep(delay / 1000)
173172
if self.configuration.debug:
174-
logger.debug(
173+
sdk_core_logger.debug_config(
175174
"retry backoff strategy:%s, retry condition: %s, max retry count:%d, current retry count: %d, retry delay(ms):%f",
176175
type(retryer.backoff_strategy).__name__, type(retryer.retry_condition).__name__,
177176
retryer.num_max_retries, retry_count + 1, delay)
@@ -331,6 +330,74 @@ def select_header_content_type(self, content_types):
331330
else:
332331
return content_types[0]
333332

333+
def _log_config(self, request):
334+
335+
if not sdk_core_logger.is_enabled_for_loglevel(LogLevel.LOG_DEBUG_WITH_CONFIG):
336+
return
337+
338+
sb = []
339+
340+
sb.append("SDK Version : ")
341+
sb.append(self.user_agent + "\n")
342+
343+
# 连接池配置
344+
sb.append("[Connection Pool]" + "\n")
345+
sb.append(" Number of pools : ")
346+
sb.append(str(self.configuration.num_pools) + "\n")
347+
sb.append(" Connection pool maxsize : ")
348+
sb.append(str(self.configuration.connection_pool_maxsize) + "\n")
349+
350+
# SSL设置
351+
sb.append("[Scheme]" + "\n")
352+
sb.append(" Scheme : ")
353+
sb.append(str(request.scheme) + "\n")
354+
355+
# 代理设置(隐藏部分信息避免敏感泄露)
356+
sb.append("[Proxy]" + "\n");
357+
sb.append(" HTTP Proxy : ")
358+
sb.append(str(self.configuration.http_proxy) + "\n")
359+
sb.append(" HTTPS Proxy : ")
360+
sb.append(str(self.configuration.https_proxy) + "\n")
361+
362+
# 超时设置
363+
sb.append("[Timeout]" + "\n");
364+
sb.append(" Connect Timeout(ms) : ")
365+
sb.append(str(self.configuration.connect_timeout) + "\n")
366+
sb.append(" Read Timeout(ms) : ")
367+
sb.append(str(self.configuration.read_timeout) + "\n")
368+
369+
# 重试设置
370+
sb.append("[Retry]" + "\n");
371+
sb.append(" Auto Retry : ")
372+
sb.append(str(request.auto_retry) + "\n")
373+
if request.auto_retry and request.retryer is not None:
374+
sb.append(" Max Retries : ")
375+
sb.append(str(request.retryer.num_max_retries) + "\n")
376+
sb.append(" Min Delay (ms) : ")
377+
sb.append(str(request.retryer.backoff_strategy.min_retry_delay_ms) + "\n")
378+
sb.append(" Max Delay (ms) : ")
379+
sb.append(str(request.retryer.backoff_strategy.max_retry_delay_ms) + "\n")
380+
sb.append(" Retry Condition : ")
381+
sb.append(type(request.retryer.retry_condition).__name__ if request.retryer.retry_condition is not None else "None" + "\n")
382+
sb.append(" Backoff Strategy : ")
383+
sb.append(type(request.retryer.backoff_strategy).__name__ if request.retryer.backoff_strategy is not None else "None" + "\n")
384+
sb.append(" Retry ErrorCodes : ")
385+
sb.append(str(request.retryer.retry_condition.retry_error_codes) + "\n")
386+
387+
# EndpointResolver设置
388+
sb.append("[Endpoint Resolver]" + "\n")
389+
sb.append(" Region : ")
390+
sb.append(str(request.region) + "\n")
391+
sb.append(" Endpoint : ")
392+
sb.append(str(request.host) + "\n")
393+
sb.append(" Use DualStack : ")
394+
sb.append(str(request.use_dual_stack) + "\n")
395+
sb.append(" Bootstrap Region : ")
396+
sb.append(str(request.custom_bootstrap_region) + "\n")
397+
sb.append(" Resolver Class : ")
398+
sb.append(type(request.endpoint_provider).__name__ if request.endpoint_provider is not None else "None" + "\n")
399+
400+
sdk_core_logger.debug_config("".join(sb))
334401

335402
def metadata(self):
336403
return self._metadata

volcenginesdkcore/configuration.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from six.moves import http_client as httplib
1313

1414
from volcenginesdkcore.endpoint import DefaultEndpointProvider
15+
from volcenginesdkcore.observability.debugger import sdk_core_logger
1516
from volcenginesdkcore.retryer.retryer import DEFAULT_RETRYER
1617

1718

@@ -87,7 +88,7 @@ def __init__(self):
8788

8889
# Logging Settings
8990
self.logger = {}
90-
self.logger["package_logger"] = logging.getLogger("volcenginesdkcore")
91+
self.logger["package_logger"] = sdk_core_logger
9192
self.logger["urllib3_logger"] = logging.getLogger("urllib3")
9293
# Log format
9394
self.logger_format = '%(asctime)s %(levelname)s %(message)s'
@@ -208,14 +209,14 @@ def debug(self, value):
208209
for _, logger in six.iteritems(self.logger):
209210
logger.setLevel(logging.DEBUG)
210211
# turn on httplib debug
211-
httplib.HTTPConnection.debuglevel = 1
212+
#httplib.HTTPConnection.debuglevel = 1
212213
else:
213214
# if debug status is False, turn off debug logging,
214215
# setting log level to default `logging.WARNING`
215216
for _, logger in six.iteritems(self.logger):
216217
logger.setLevel(logging.WARNING)
217218
# turn off httplib debug
218-
httplib.HTTPConnection.debuglevel = 0
219+
#httplib.HTTPConnection.debuglevel = 0
219220

220221
@property
221222
def logger_format(self):
@@ -239,6 +240,9 @@ def logger_format(self, value):
239240
"""
240241
self.__logger_format = value
241242
self.logger_formatter = logging.Formatter(self.__logger_format)
243+
for _, lg in six.iteritems(self.logger):
244+
for h in lg.handlers:
245+
h.setFormatter(self.logger_formatter)
242246

243247
def get_api_key_with_prefix(self, identifier):
244248
"""Gets API key (with prefix if set).
@@ -334,3 +338,11 @@ def max_retry_delay_ms(self, value):
334338
@property
335339
def retryer(self):
336340
return self.__retryer
341+
342+
@property
343+
def log_level(self):
344+
return sdk_core_logger.get_log_level()
345+
346+
@log_level.setter
347+
def log_level(self, value):
348+
sdk_core_logger.set_log_level(value)

volcenginesdkcore/endpoint/providers/default_provider.py

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import warnings
44

55
from volcenginesdkcore.endpoint.endpoint_provider import EndpointProvider, ResolvedEndpoint
6+
from volcenginesdkcore.observability.debugger import sdk_core_logger
67

78
open_prefix = 'open'
89
endpoint_suffix = '.volcengineapi.com'
@@ -29,14 +30,36 @@ def __standardize_domain_service_code(self):
2930
return self.service.lower().replace('_', '-')
3031

3132
def get_endpoint_for(self, region, suffix=endpoint_suffix):
33+
sdk_core_logger.debug_endpoint(
34+
"get_endpoint_for start: service=%s, region=%s, suffix=%s",
35+
self.service, region, suffix
36+
)
3237
if self.is_global:
3338
if self.global_endpoint:
39+
sdk_core_logger.debug_endpoint(
40+
"use global endpoint: service=%s, endpoint=%s",
41+
self.service, self.global_endpoint
42+
)
3443
return self.global_endpoint
35-
return self.__standardize_domain_service_code + suffix
44+
45+
endpoint = self.__standardize_domain_service_code + suffix
46+
sdk_core_logger.debug_endpoint(
47+
"build global endpoint from service code: %s", endpoint
48+
)
49+
return endpoint
3650
if region in self.region_endpoint_map:
37-
return self.region_endpoint_map[region]
51+
endpoint = self.region_endpoint_map[region]
52+
sdk_core_logger.debug_endpoint(
53+
"use region endpoint from map: service=%s, region=%s, endpoint=%s",
54+
self.service, region, endpoint
55+
)
56+
return endpoint
3857

39-
return self.__standardize_domain_service_code + '.' + region + suffix
58+
endpoint = self.__standardize_domain_service_code + '.' + region + suffix
59+
sdk_core_logger.debug_endpoint(
60+
"build region endpoint by default rule: %s", endpoint
61+
)
62+
return endpoint
4063

4164

4265
default_endpoint = {
@@ -477,9 +500,21 @@ def __init__(self, custom_endpoints=None):
477500
self.custom_endpoints = custom_endpoints or {}
478501

479502
def get_default_endpoint(self, service, region, suffix=endpoint_suffix):
503+
sdk_core_logger.debug_endpoint(
504+
"get_default_endpoint: service=%s, region=%s, suffix=%s",
505+
service, region, suffix
506+
)
480507
if service in default_endpoint:
481508
e = default_endpoint[service]
482-
return e.get_endpoint_for(region, suffix)
509+
endpoint = e.get_endpoint_for(region, suffix)
510+
sdk_core_logger.debug_endpoint(
511+
"resolved default endpoint: service=%s, endpoint=%s",
512+
service, endpoint
513+
)
514+
return endpoint
515+
sdk_core_logger.debug_endpoint(
516+
"service not found in default_endpoint, use fallback=%s", fallback_endpoint
517+
)
483518
return fallback_endpoint
484519

485520
def __in_bootstrap_region_list(self, region, custom_bootstrap_region):
@@ -519,20 +554,36 @@ def __has_enabled_dualstack(use_dual_stack):
519554
return use_dual_stack
520555

521556
def endpoint_for(self, service, region, custom_bootstrap_region=None, use_dual_stack=None, **kwargs):
557+
sdk_core_logger.debug_endpoint(
558+
"endpoint_for called: service=%s, region=%s, custom_bootstrap_region=%s, use_dual_stack=%s",
559+
service, region, custom_bootstrap_region, use_dual_stack
560+
)
522561
if service in self.custom_endpoints:
523562
conf = self.custom_endpoints[service]
524563
host = conf.get_endpoint_for(region)
564+
sdk_core_logger.debug_endpoint(
565+
"use custom endpoint: service=%s, region=%s, host=%s",
566+
service, region, host
567+
)
525568
return ResolvedEndpoint(host)
526569

527570
if custom_bootstrap_region is None:
528571
custom_bootstrap_region = {}
529572

530573
if not self.__in_bootstrap_region_list(region, custom_bootstrap_region):
574+
sdk_core_logger.debug_endpoint(
575+
"region=%s not in bootstrap list, fallback=%s",
576+
region, fallback_endpoint
577+
)
531578
return ResolvedEndpoint(fallback_endpoint)
532579

533580
suffix = dualstack_endpoint_suffix if self.__has_enabled_dualstack(use_dual_stack) else endpoint_suffix
534581
host = self.get_default_endpoint(service=service, region=region, suffix=suffix)
535582

583+
sdk_core_logger.debug_endpoint(
584+
"final resolved endpoint: service=%s, region=%s, host=%s",
585+
service, region, host
586+
)
536587
return ResolvedEndpoint(host)
537588

538589

@@ -541,4 +592,8 @@ def __init__(self, host):
541592
self.host = host
542593

543594
def endpoint_for(self, service, region, **kwargs):
595+
sdk_core_logger.debug_endpoint(
596+
"HostEndpointProvider.endpoint_for: service=%s, region=%s, host=%s",
597+
service, region, self.host
598+
)
544599
return ResolvedEndpoint(self.host)

volcenginesdkcore/observability/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)