Skip to content
This repository was archived by the owner on Jan 23, 2024. It is now read-only.

Commit 9fbff21

Browse files
b-danielsemrekultursay
authored andcommitted
Fix location information for logpoint output.
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=130294233
1 parent ac04fbb commit 9fbff21

File tree

2 files changed

+71
-35
lines changed

2 files changed

+71
-35
lines changed

src/googleclouddebugger/__init__.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,7 @@ def _StartDebugger():
5454
_breakpoints_manager = breakpoints_manager.BreakpointsManager(_hub_client)
5555

5656
# Set up loggers for logpoints.
57-
capture_collector.log_info_message = logging.info
58-
capture_collector.log_warning_message = logging.warning
59-
capture_collector.log_error_message = logging.error
57+
capture_collector.SetLogger(logging.getLogger())
6058

6159
capture_collector.CaptureCollector.pretty_printers.append(
6260
appengine_pretty_printers.PrettyPrinter)

src/googleclouddebugger/capture_collector.py

Lines changed: 70 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import copy
2020
import datetime
2121
import inspect
22+
import logging
2223
import os
2324
import re
2425
import sys
@@ -49,6 +50,70 @@
4950
INVALID_EXPRESSION_INDEX = '<N/A>'
5051

5152

53+
def NormalizePath(path):
54+
"""Removes any Python system path prefix from the given path.
55+
56+
Python keeps almost all paths absolute. This is not what we actually
57+
want to return. This loops through system paths (directories in which
58+
Python will load modules). If "path" is relative to one of them, the
59+
directory prefix is removed.
60+
61+
Args:
62+
path: absolute path to normalize (relative paths will not be altered)
63+
64+
Returns:
65+
Relative path if "path" is within one of the sys.path directories or
66+
the input otherwise.
67+
"""
68+
path = os.path.normpath(path)
69+
70+
for sys_path in sys.path:
71+
if not sys_path:
72+
continue
73+
74+
# Append '/' at the end of the path if it's not there already.
75+
sys_path = os.path.join(sys_path, '')
76+
77+
if path.startswith(sys_path):
78+
return path[len(sys_path):]
79+
80+
return path
81+
82+
83+
class LineNoFilter(logging.Filter):
84+
"""Enables overriding the path and line number in a logging record.
85+
86+
The "extra" parameter in logging cannot override existing fields in log
87+
record, so we can't use it to directly set pathname and lineno. Instead,
88+
we add this filter to the default logger, and it looks for "cdbg_pathname"
89+
and "cdbg_lineno", moving them to the pathname and lineno fields accordingly.
90+
"""
91+
92+
def filter(self, record):
93+
# This method gets invoked for user-generated logging, so verify that this
94+
# particular invocation came from our logging code.
95+
if record.pathname != inspect.currentframe().f_code.co_filename:
96+
return True
97+
if hasattr(record, 'cdbg_pathname'):
98+
record.pathname = record.cdbg_pathname
99+
del record.cdbg_pathname
100+
if hasattr(record, 'cdbg_lineno'):
101+
record.lineno = record.cdbg_lineno
102+
del record.cdbg_lineno
103+
return True
104+
105+
106+
def SetLogger(logger):
107+
"""Sets the logger object to use for all 'LOG' breakpoint actions."""
108+
global log_info_message
109+
global log_warning_message
110+
global log_error_message
111+
log_info_message = logger.info
112+
log_warning_message = logger.warning
113+
log_error_message = logger.error
114+
logger.addFilter(LineNoFilter())
115+
116+
52117
class CaptureCollector(object):
53118
"""Captures application state snapshot.
54119
@@ -145,7 +210,7 @@ def Collect(self, top_frame):
145210
breakpoint_frames.append({
146211
'function': code.co_name,
147212
'location': {
148-
'path': CaptureCollector._NormalizePath(code.co_filename),
213+
'path': NormalizePath(code.co_filename),
149214
'line': frame.f_lineno},
150215
'arguments': frame_arguments,
151216
'locals': frame_locals})
@@ -403,36 +468,6 @@ def _CaptureRequestLogId(self):
403468
self.breakpoint['labels'][
404469
labels.Breakpoint.REQUEST_LOG_ID] = request_log_id
405470

406-
@staticmethod
407-
def _NormalizePath(path):
408-
"""Converts an absolute path to a relative one.
409-
410-
Python keeps almost all paths absolute. This is not what we actually
411-
want to return. This loops through system paths (directories in which
412-
Python will load modules). If "path" is relative to one of them, the
413-
directory prefix is removed.
414-
415-
Args:
416-
path: absolute path to normalize (relative paths will not be altered)
417-
418-
Returns:
419-
Relative path if "path" is within one of the sys.path directories or
420-
the input otherwise.
421-
"""
422-
path = os.path.normpath(path)
423-
424-
for sys_path in sys.path:
425-
if not sys_path:
426-
continue
427-
428-
# Append '/' at the end of the path if it's not there already.
429-
sys_path = os.path.join(sys_path, '')
430-
431-
if path.startswith(sys_path):
432-
return path[len(sys_path):]
433-
434-
return path
435-
436471

437472
class LogCollector(object):
438473
"""Captures minimal application snapshot and logs it to application log.
@@ -489,7 +524,10 @@ def Log(self, frame):
489524
self._definition.get('logMessageFormat', ''),
490525
self._EvaluateExpressions(frame))
491526

492-
self._log_message('LOGPOINT: ' + message)
527+
self._log_message('LOGPOINT: ' + message, extra={
528+
'cdbg_pathname': NormalizePath(frame.f_code.co_filename),
529+
'cdbg_lineno': frame.f_lineno
530+
})
493531
return None
494532

495533
def _EvaluateExpressions(self, frame):

0 commit comments

Comments
 (0)