main
1import logging
2from typing import Any, Dict, cast
3
4import pytest
5
6from openai._utils import SensitiveHeadersFilter
7
8
9@pytest.fixture
10def logger_with_filter() -> logging.Logger:
11 logger = logging.getLogger("test_logger")
12 logger.setLevel(logging.DEBUG)
13 logger.addFilter(SensitiveHeadersFilter())
14 return logger
15
16
17def test_keys_redacted(logger_with_filter: logging.Logger, caplog: pytest.LogCaptureFixture) -> None:
18 with caplog.at_level(logging.DEBUG):
19 logger_with_filter.debug(
20 "Request options: %s",
21 {
22 "method": "post",
23 "url": "chat/completions",
24 "headers": {"api-key": "12345", "Authorization": "Bearer token"},
25 },
26 )
27
28 log_record = cast(Dict[str, Any], caplog.records[0].args)
29 assert log_record["method"] == "post"
30 assert log_record["url"] == "chat/completions"
31 assert log_record["headers"]["api-key"] == "<redacted>"
32 assert log_record["headers"]["Authorization"] == "<redacted>"
33 assert (
34 caplog.messages[0]
35 == "Request options: {'method': 'post', 'url': 'chat/completions', 'headers': {'api-key': '<redacted>', 'Authorization': '<redacted>'}}"
36 )
37
38
39def test_keys_redacted_case_insensitive(logger_with_filter: logging.Logger, caplog: pytest.LogCaptureFixture) -> None:
40 with caplog.at_level(logging.DEBUG):
41 logger_with_filter.debug(
42 "Request options: %s",
43 {
44 "method": "post",
45 "url": "chat/completions",
46 "headers": {"Api-key": "12345", "authorization": "Bearer token"},
47 },
48 )
49
50 log_record = cast(Dict[str, Any], caplog.records[0].args)
51 assert log_record["method"] == "post"
52 assert log_record["url"] == "chat/completions"
53 assert log_record["headers"]["Api-key"] == "<redacted>"
54 assert log_record["headers"]["authorization"] == "<redacted>"
55 assert (
56 caplog.messages[0]
57 == "Request options: {'method': 'post', 'url': 'chat/completions', 'headers': {'Api-key': '<redacted>', 'authorization': '<redacted>'}}"
58 )
59
60
61def test_no_headers(logger_with_filter: logging.Logger, caplog: pytest.LogCaptureFixture) -> None:
62 with caplog.at_level(logging.DEBUG):
63 logger_with_filter.debug(
64 "Request options: %s",
65 {"method": "post", "url": "chat/completions"},
66 )
67
68 log_record = cast(Dict[str, Any], caplog.records[0].args)
69 assert log_record["method"] == "post"
70 assert log_record["url"] == "chat/completions"
71 assert "api-key" not in log_record
72 assert "Authorization" not in log_record
73 assert caplog.messages[0] == "Request options: {'method': 'post', 'url': 'chat/completions'}"
74
75
76def test_headers_without_sensitive_info(logger_with_filter: logging.Logger, caplog: pytest.LogCaptureFixture) -> None:
77 with caplog.at_level(logging.DEBUG):
78 logger_with_filter.debug(
79 "Request options: %s",
80 {
81 "method": "post",
82 "url": "chat/completions",
83 "headers": {"custom": "value"},
84 },
85 )
86
87 log_record = cast(Dict[str, Any], caplog.records[0].args)
88 assert log_record["method"] == "post"
89 assert log_record["url"] == "chat/completions"
90 assert log_record["headers"] == {"custom": "value"}
91 assert (
92 caplog.messages[0]
93 == "Request options: {'method': 'post', 'url': 'chat/completions', 'headers': {'custom': 'value'}}"
94 )
95
96
97def test_standard_debug_msg(logger_with_filter: logging.Logger, caplog: pytest.LogCaptureFixture) -> None:
98 with caplog.at_level(logging.DEBUG):
99 logger_with_filter.debug("Sending HTTP Request: %s %s", "POST", "chat/completions")
100 assert caplog.messages[0] == "Sending HTTP Request: POST chat/completions"