Skip to content

Commit e95aa92

Browse files
ldanilekConvex, Inc.
authored andcommitted
[ENG-6401] [components] attach path to console logs from sub-queries and sub-mutations (#30679)
when running a mutation or query as a subfunction, the logs should get accumulated with the parent function but they should have the subfunction's path attached. I considered a few ways of doing this ( #30593 and #30576 ) but found the one in this PR to work well: enhance the `LogLine` enum so it has a recursive `LogLine::SubFunction` variant. Some places, like node_executor and LogEvent, only deal with the non-recursive variant of `LogLine`, now called `LogLineStructured`, but most can have a full tree of log lines. Sometimes we need to serialize the tree structure: in protobuf for funrun & usher, and in ConvexValue for `_session_requests`. Meanwhile sometimes we need to flatten the tree into an array: when we need to call `to_pretty_string()` for `RedactedLogLines`, and when we output `LogEvent`s. GitOrigin-RevId: 7274b546885003b4be35072082d12773e3c48c5c
1 parent c13443a commit e95aa92

File tree

20 files changed

+553
-268
lines changed

20 files changed

+553
-268
lines changed

crates/application/src/cron_jobs/mod.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -388,8 +388,10 @@ impl<RT: Runtime> CronJobExecutor<RT> {
388388
let mut new_log_lines = Vec::new();
389389
let mut is_truncated = false;
390390
let mut size = 0;
391-
for rich_log in log_lines.into_iter() {
392-
let log = rich_log.to_pretty_string();
391+
for log in log_lines
392+
.into_iter()
393+
.flat_map(|log| log.to_pretty_strings())
394+
{
393395
let line_len = log.len();
394396
if size + line_len <= CRON_LOG_MAX_LOG_LINE_LENGTH {
395397
new_log_lines.push(log);

crates/application/src/function_log.rs

Lines changed: 69 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -162,44 +162,64 @@ impl FunctionExecution {
162162
}
163163
}
164164

165-
fn event_source(&self) -> FunctionEventSource {
166-
let udf_id = self.params.identifier_str();
165+
fn event_source(
166+
&self,
167+
sub_function_path: Option<&CanonicalizedComponentFunctionPath>,
168+
) -> FunctionEventSource {
167169
let cached = if self.udf_type == UdfType::Query {
168170
Some(self.cached_result)
169171
} else {
170172
None
171173
};
172-
let component_path = match &self.params {
173-
UdfParams::Function { identifier, .. } => identifier.component.clone(),
174-
// TODO(ENG-7612): Support HTTP actions in components.
175-
UdfParams::Http { .. } => ComponentPath::root(),
174+
let (component_path, udf_path) = match sub_function_path {
175+
Some(path) => (path.component.clone(), path.udf_path.to_string()),
176+
None => {
177+
let udf_id = self.params.identifier_str();
178+
let component_path = match &self.params {
179+
UdfParams::Function { identifier, .. } => identifier.component.clone(),
180+
// TODO(ENG-7612): Support HTTP actions in components.
181+
UdfParams::Http { .. } => ComponentPath::root(),
182+
};
183+
(component_path, udf_id)
184+
},
176185
};
177186

178187
FunctionEventSource {
179188
component_path,
180-
udf_path: udf_id,
189+
udf_path,
181190
udf_type: self.udf_type,
182191
module_environment: self.environment,
183192
cached,
184193
context: self.context.clone(),
185194
}
186195
}
187196

197+
fn console_log_events_for_log_line(
198+
&self,
199+
log_line: &LogLine,
200+
sub_function_path: Option<&CanonicalizedComponentFunctionPath>,
201+
) -> Vec<LogEvent> {
202+
match log_line {
203+
LogLine::Structured(log_line) => {
204+
vec![LogEvent {
205+
timestamp: log_line.timestamp,
206+
event: StructuredLogEvent::Console {
207+
source: self.event_source(sub_function_path),
208+
log_line: log_line.clone(),
209+
},
210+
}]
211+
},
212+
LogLine::SubFunction { path, log_lines } => log_lines
213+
.into_iter()
214+
.flat_map(|log_line| self.console_log_events_for_log_line(log_line, Some(path)))
215+
.collect(),
216+
}
217+
}
218+
188219
fn console_log_events(&self) -> Vec<LogEvent> {
189220
self.log_lines
190221
.iter()
191-
.map(|line| {
192-
let timestamp = match &line {
193-
LogLine::Structured { timestamp, .. } => *timestamp,
194-
};
195-
LogEvent {
196-
timestamp,
197-
event: StructuredLogEvent::Console {
198-
source: self.event_source(),
199-
log_line: line.clone(),
200-
},
201-
}
202-
})
222+
.flat_map(|line| self.console_log_events_for_log_line(line, None))
203223
.collect()
204224
}
205225

@@ -209,7 +229,7 @@ impl FunctionExecution {
209229
let mut events = vec![LogEvent {
210230
timestamp: self.unix_timestamp,
211231
event: StructuredLogEvent::FunctionExecution {
212-
source: self.event_source(),
232+
source: self.event_source(None),
213233
error: self.params.err().cloned(),
214234
execution_time,
215235
usage_stats: log_streaming::AggregatedFunctionUsageStats {
@@ -230,7 +250,7 @@ impl FunctionExecution {
230250
event: StructuredLogEvent::Exception {
231251
error: err.clone(),
232252
user_identifier: self.identity.user_identifier().cloned(),
233-
source: self.event_source(),
253+
source: self.event_source(None),
234254
udf_server_version: self.udf_server_version.clone(),
235255
},
236256
});
@@ -256,21 +276,37 @@ impl HeapSize for FunctionExecutionProgress {
256276
}
257277

258278
impl FunctionExecutionProgress {
259-
fn console_log_events(self) -> Vec<LogEvent> {
260-
self.log_lines
261-
.into_iter()
262-
.map(|line: LogLine| {
263-
let timestamp = match &line {
264-
LogLine::Structured { timestamp, .. } => *timestamp,
279+
fn console_log_events_for_log_line(
280+
&self,
281+
log_line: &LogLine,
282+
sub_function_path: Option<&CanonicalizedComponentFunctionPath>,
283+
) -> Vec<LogEvent> {
284+
match log_line {
285+
LogLine::Structured(log_line) => {
286+
let mut event_source = self.event_source.clone();
287+
if let Some(sub_function_path) = sub_function_path {
288+
event_source.component_path = sub_function_path.component.clone();
289+
event_source.udf_path = sub_function_path.udf_path.to_string();
265290
};
266-
LogEvent {
267-
timestamp,
291+
vec![LogEvent {
292+
timestamp: log_line.timestamp,
268293
event: StructuredLogEvent::Console {
269-
source: self.event_source.clone(),
270-
log_line: line,
294+
source: event_source,
295+
log_line: log_line.clone(),
271296
},
272-
}
273-
})
297+
}]
298+
},
299+
LogLine::SubFunction { path, log_lines } => log_lines
300+
.into_iter()
301+
.flat_map(|log_line| self.console_log_events_for_log_line(log_line, Some(path)))
302+
.collect(),
303+
}
304+
}
305+
306+
fn console_log_events(self) -> Vec<LogEvent> {
307+
self.log_lines
308+
.iter()
309+
.flat_map(|line| self.console_log_events_for_log_line(line, None))
274310
.collect()
275311
}
276312
}

crates/application/src/redaction.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ impl RedactedLogLines {
4545
} else {
4646
log_lines
4747
.into_iter()
48-
.map(|l| l.to_pretty_string())
48+
.flat_map(|l| l.to_pretty_strings())
4949
.collect()
5050
})
5151
}

0 commit comments

Comments
 (0)