1010import pytest
1111
1212import azure .cosmos .cosmos_client as cosmos_client
13- from azure .cosmos . container import ContainerProxy
13+ from azure .cosmos import PartitionKey , ContainerProxy
1414import test_config
1515from _fault_injection_transport import FaultInjectionTransport
1616from test_fault_injection_transport import TestFaultInjectionTransport
@@ -35,6 +35,12 @@ def reset(self):
3535 def emit (self , record ):
3636 self .messages .append (record )
3737
38+ class FilterStatusCode (logging .Filter ):
39+ def filter (self , record ):
40+ if hasattr (record , 'status_code' ) and record .status_code >= 400 :
41+ return True
42+ return False
43+
3844CONFIG = test_config .TestConfig
3945L1 = "Location1"
4046L2 = "Location2"
@@ -83,8 +89,15 @@ def setUpClass(cls):
8389 "tests." )
8490 cls .mock_handler_default = MockHandler ()
8591 cls .mock_handler_diagnostic = MockHandler ()
92+ cls .mock_handler_filtered_diagnostic = MockHandler ()
93+
94+ # Add filter to the filtered diagnostics handler
95+
96+ cls .mock_handler_filtered_diagnostic .addFilter (FilterStatusCode ())
8697 cls .logger_default = create_logger ("testloggerdefault" , cls .mock_handler_default )
8798 cls .logger_diagnostic = create_logger ("testloggerdiagnostic" , cls .mock_handler_diagnostic )
99+ cls .logger_filtered_diagnostic = create_logger ("testloggerfiltereddiagnostic" ,
100+ cls .mock_handler_filtered_diagnostic )
88101 cls .client_default = cosmos_client .CosmosClient (cls .host , cls .masterKey ,
89102 consistency_level = "Session" ,
90103 connection_policy = cls .connectionPolicy ,
@@ -94,6 +107,11 @@ def setUpClass(cls):
94107 connection_policy = cls .connectionPolicy ,
95108 logger = cls .logger_diagnostic ,
96109 enable_diagnostics_logging = True )
110+ cls .client_filtered_diagnostic = cosmos_client .CosmosClient (cls .host , cls .masterKey ,
111+ consistency_level = "Session" ,
112+ connection_policy = cls .connectionPolicy ,
113+ logger = cls .logger_filtered_diagnostic ,
114+ enable_diagnostics_logging = True )
97115
98116 def test_default_http_logging_policy (self ):
99117 # Test if we can log into from creating a database
@@ -118,22 +136,26 @@ def test_cosmos_http_logging_policy(self):
118136 database_id = "database_test-" + str (uuid .uuid4 ())
119137 self .client_diagnostic .create_database (id = database_id )
120138 assert all (m .levelname == 'INFO' for m in self .mock_handler_diagnostic .messages )
121- messages_request = self .mock_handler_diagnostic .messages [1 ]
122- messages_response = self .mock_handler_diagnostic .messages [2 ]
123- elapsed_time = messages_request .duration
139+ # Check that we made a databaseaccount read request only once and that we only logged it once
140+ messages_request = self .mock_handler_diagnostic .messages [0 ]
141+ messages_response = self .mock_handler_diagnostic .messages [1 ]
142+ elapsed_time = messages_response .duration
124143 assert "databaseaccount" == messages_request .resource_type
125144 assert messages_request .verb == "GET"
126- assert 200 == messages_request .status_code
145+ assert 200 == messages_response .status_code
127146 assert "Read" == messages_request .operation_type
128147 assert elapsed_time is not None
129148 assert "Response headers" in messages_response .message
149+ # Verify we only have a total of 4 logged messages: 2 from databaseaccount read and 2 from create database
150+ assert len (self .mock_handler_diagnostic .messages ) == 4
130151 # Test if we can log into from creating a database
131- messages_request = self .mock_handler_diagnostic .messages [4 ]
132- messages_response = self .mock_handler_diagnostic .messages [5 ]
133- elapsed_time = messages_request .duration
152+ # The request to create database should follow the databaseaccount read request immediately
153+ messages_request = self .mock_handler_diagnostic .messages [2 ]
154+ messages_response = self .mock_handler_diagnostic .messages [3 ]
155+ elapsed_time = messages_response .duration
134156 assert "dbs" == messages_request .resource_type
135157 assert messages_request .verb == "POST"
136- assert 201 == messages_request .status_code
158+ assert 201 == messages_response .status_code
137159 assert messages_request .operation_type == "Create"
138160 assert elapsed_time is not None
139161 assert "Response headers" in messages_response .message
@@ -145,14 +167,14 @@ def test_cosmos_http_logging_policy(self):
145167 except :
146168 pass
147169 assert all (m .levelname == 'INFO' for m in self .mock_handler_diagnostic .messages )
148- messages_request = self .mock_handler_diagnostic .messages [1 ]
149- messages_response = self .mock_handler_diagnostic .messages [2 ]
150- elapsed_time = messages_request .duration
170+ messages_request = self .mock_handler_diagnostic .messages [0 ]
171+ messages_response = self .mock_handler_diagnostic .messages [1 ]
172+ elapsed_time = messages_response .duration
151173 assert "dbs" == messages_request .resource_type
152174 assert messages_request .operation_type == "Create"
153175 assert 'Request headers:' in messages_request .msg
154176 assert 'A body is sent with the request' in messages_request .msg
155- assert messages_request .status_code == 409
177+ assert messages_response .status_code == 409
156178 assert elapsed_time is not None
157179 assert "Response headers" in messages_response .msg
158180
@@ -161,6 +183,49 @@ def test_cosmos_http_logging_policy(self):
161183
162184 self .mock_handler_diagnostic .reset ()
163185
186+ def test_filtered_diagnostics_logging_policy (self ):
187+ # Test if we can log errors with the filtered diagnostics logger
188+ database_id = "database_test-" + str (uuid .uuid4 ())
189+ container_id = "container_test-" + str (uuid .uuid4 ())
190+ self .client_filtered_diagnostic .create_database (id = database_id )
191+ database = self .client_filtered_diagnostic .get_database_client (database_id )
192+ database .create_container (id = container_id , partition_key = PartitionKey (path = "/pk" ))
193+
194+ # Try to read an item that doesn't exist
195+ try :
196+ container = database .get_container_client (container_id )
197+ container .read_item (item = "nonexistent_item" , partition_key = "nonexistent_pk" )
198+ except :
199+ pass
200+
201+ # Assert that the filtered logger only captured the error
202+ request_log = self .mock_handler_filtered_diagnostic .messages [0 ]
203+ response_log = self .mock_handler_filtered_diagnostic .messages [1 ]
204+ assert response_log .status_code == 404
205+ assert request_log .resource_type == "docs"
206+ assert request_log .operation_type == "Read"
207+ assert len (self .mock_handler_filtered_diagnostic .messages ) == 2
208+
209+ self .mock_handler_filtered_diagnostic .reset ()
210+
211+ # Try to create an item with an invalid partition key
212+ try :
213+ container .create_item (body = {"FakeProperty" : "item1" , "NotPk" : None })
214+ except :
215+ pass
216+
217+ # Assert that the filtered logger captured the error
218+ request_log = self .mock_handler_filtered_diagnostic .messages [0 ]
219+ response_log = self .mock_handler_filtered_diagnostic .messages [1 ]
220+ assert response_log .status_code == 400
221+ assert request_log .resource_type == "docs"
222+ assert request_log .operation_type == "Create"
223+ assert len (self .mock_handler_filtered_diagnostic .messages ) == 2
224+
225+ # Clean up
226+ self .client_filtered_diagnostic .delete_database (database_id )
227+ self .mock_handler_filtered_diagnostic .reset ()
228+
164229 def test_client_settings (self ):
165230 # Test data
166231 all_locations = [L1 , L2 ]
0 commit comments