Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Commit

Permalink
Add additional request information to structured logs.
Browse files Browse the repository at this point in the history
  • Loading branch information
clokep committed Mar 19, 2021
1 parent 28275b3 commit dab36c2
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 3 deletions.
24 changes: 23 additions & 1 deletion synapse/http/site.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,28 @@ def get_method(self) -> str:
return self.method.decode("ascii")
return method

def get_authenticated_entity(self) -> Optional[str]:
# Convert the requester into a string that we can log
if isinstance(self.requester, str):
return self.requester
elif isinstance(self.requester, Requester):
authenticated_entity = self.requester.authenticated_entity

# If this is a request where the target user doesn't match the user who
# authenticated (e.g. and admin is puppetting a user) then we log both.
if self.requester.user.to_string() != authenticated_entity:
return "{},{}".format(
authenticated_entity,
self.requester.user.to_string(),
)
return authenticated_entity
elif self.requester is not None:
# This shouldn't happen, but we log it so we don't lose information
# and can see that we're doing something wrong.
return repr(self.requester) # type: ignore[unreachable]

return None

def render(self, resrc):
# this is called once a Resource has been found to serve the request; in our
# case the Resource in question will normally be a JsonResource.
Expand Down Expand Up @@ -312,7 +334,7 @@ def _finished_processing(self):
' %sB %s "%s %s %s" "%s" [%d dbevts]',
self.getClientIP(),
self.site.site_tag,
authenticated_entity,
self.get_authenticated_entity(),
processing_time,
response_send_time,
usage.ru_utime,
Expand Down
16 changes: 16 additions & 0 deletions synapse/logging/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,22 @@ def filter(self, record: logging.LogRecord) -> Literal[True]:
# compatibility this is stored as the "request" on the record.
record.request = str(context) # type: ignore

# Add some data from the HTTP request.
request = context.request
if request is None:
return True

# Avoid a circular import.
from synapse.http import get_request_user_agent

record.ip_address = request.getClientIP() # type: ignore
record.site_tag = request.site.site_tag # type: ignore
record.authenticated_entity = request.get_authenticated_entity() # type: ignore
record.method = request.get_method() # type: ignore
record.url = request.get_redacted_uri() # type: ignore
record.protocol = request.clientproto.decode("ascii", errors="replace") # type: ignore
record.user_agent = get_request_user_agent(request) # type: ignore

return True


Expand Down
17 changes: 15 additions & 2 deletions tests/logging/test_terse_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
# 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.

import json
import logging
from io import BytesIO, StringIO
Expand Down Expand Up @@ -163,13 +162,27 @@ def test_with_request_context(self):

log = self.get_log_line()

# The terse logger should give us these keys.
# The terse logger includes additional request information, if possible.
expected_log_keys = [
"log",
"level",
"namespace",
"request",
"ip_address",
"site_tag",
"authenticated_entity",
"method",
"url",
"protocol",
"user_agent",
]
self.assertCountEqual(log.keys(), expected_log_keys)
self.assertEqual(log["log"], "Hello there, wally!")
self.assertTrue(log["request"].startswith("POST-"))
self.assertEqual(log["ip_address"], "127.0.0.1")
self.assertEqual(log["site_tag"], "test-site")
self.assertIsNone(log["authenticated_entity"])
self.assertEqual(log["method"], "POST")
self.assertEqual(log["url"], "/_matrix/client/versions")
self.assertEqual(log["protocol"], "1.1")
self.assertEqual(log["user_agent"], "")

0 comments on commit dab36c2

Please sign in to comment.