@@ -103,7 +103,8 @@ def _estimate_log_size(self, log: LogData, depth: int = 3) -> int:
103
103
Estimates the size in bytes of a log by calculating the size of its body and its attributes
104
104
and adding a buffer amount to account for other log metadata information.
105
105
Will process complex log structures up to the specified depth limit.
106
- If the depth limit of the log structure is exceeded, returns the truncated calculation
106
+ Includes cycle detection to prevent processing the same complex log content (Maps, Arrays)
107
+ more than once. If the depth limit of the log structure is exceeded, returns the truncated calculation
107
108
to everything up to that point.
108
109
109
110
Args:
@@ -114,9 +115,13 @@ def _estimate_log_size(self, log: LogData, depth: int = 3) -> int:
114
115
int: The estimated size of the log object in bytes
115
116
"""
116
117
117
- # Use a queue to prevent excessive recursive calls.
118
- # We calculate based on the size of the log record body and attributes for the log.
119
- queue : List [tuple [AnyValue , int ]] = [(log .log_record .body , 0 ), (log .log_record .attributes , - 1 )]
118
+ # Queue is a list of (log_content, depth) where:
119
+ # log_content is the current piece of log data being processed
120
+ # depth tracks how many levels deep we've traversed to reach this data
121
+ queue = [(log .log_record .body , 0 ), (log .log_record .attributes , - 1 )]
122
+
123
+ # Track visited objects to avoid calculating the same complex log content more than once
124
+ visited = set ()
120
125
121
126
size : int = self ._BASE_LOG_BUFFER_BYTE_SIZE
122
127
@@ -130,6 +135,9 @@ def _estimate_log_size(self, log: LogData, depth: int = 3) -> int:
130
135
131
136
next_val , current_depth = data
132
137
138
+ if not next_val :
139
+ continue
140
+
133
141
if isinstance (next_val , (str , bytes )):
134
142
size += len (next_val )
135
143
continue
@@ -142,7 +150,14 @@ def _estimate_log_size(self, log: LogData, depth: int = 3) -> int:
142
150
size += len (str (next_val ))
143
151
continue
144
152
153
+ # next_val must be Sequence["AnyValue"] or Mapping[str, "AnyValue"],
145
154
if current_depth <= depth :
155
+ # Guaranteed to be unique, see: https://www.w3schools.com/python/ref_func_id.asp
156
+ obj_id = id (next_val )
157
+ if obj_id in visited :
158
+ continue
159
+ visited .add (obj_id )
160
+
146
161
if isinstance (next_val , Sequence ):
147
162
for content in next_val :
148
163
new_queue .append ((cast (AnyValue , content ), current_depth + 1 ))
0 commit comments