Probe Step
The probe
step allows you to execute a callback function for each element in the traversal, primarily for side effects like logging, metrics collection, or debugging, without altering the elements themselves or the flow of the traversal.
In this diagram:
- Input Elements: The walker starts with elements A, B, C.
- The
.probe(callback)
step processes each element. - Side Effect: As each element (A, B, C) passes through, the provided callback function is executed. This is shown triggering actions like logging or updating metrics.
- Output Elements (Unchanged): The elements A, B, C continue to the next step in the traversal, completely unaffected by the
probe
operation.
Syntax
walker.probe(|element, context| {
// inspection logic
})
Parameters
inspector
: A function that takes:- A reference to the current element (vertex or edge)
- The element's context
- Performs some side effect like logging or debugging
Return Value
Returns the same traversal unchanged, allowing you to continue chaining steps.
Examples
Inspecting Vertices
This example shows how to use the probe
step to inspect and count vertices during traversal:
// Use probe to inspect vertices during traversal without affecting the flow
println!("Examining each person vertex:");
let mut person_count = 0;
graph
.walk()
.vertices(Vertex::person()) // Type-safe vertex lookup by label
.probe(|vertex, _| {
// Inspect vertex properties using type-safe projection
if let Some(person) = vertex.project::<Person<_>>() {
person_count += 1;
println!(" Found person: {} (age {})", person.name(), person.age());
}
})
.count();
println!(" Total people found: {}", person_count);
Inspecting Edges
This example demonstrates using the probe
step to examine relationships between vertices:
// Use probe to inspect relationships between vertices
println!("\nExamining Bryn's outgoing relationships:");
graph
.walk()
.vertices(Vertex::person_by_username("bryn123"))
.edges(EdgeSearch::scan().outgoing())
.probe(|edge, _| {
// Get the target vertex to display relationship context
let target = graph.vertex(edge.head()).unwrap();
// Display relationship information
match edge.weight() {
crate::standard_model::Edge::Created => {
if let Some(project) = target.project::<Project<_>>() {
println!(" Bryn created project: {}", project.name());
}
}
crate::standard_model::Edge::Follows => {
if let Some(person) = target.project::<Person<_>>() {
println!(" Bryn follows: {}", person.name());
}
}
crate::standard_model::Edge::Liked { timestamp } => {
if let Some(project) = target.project::<Project<_>>() {
println!(" Bryn liked project {} on {}", project.name(), timestamp);
}
}
crate::standard_model::Edge::Commented { timestamp } => {
if let Some(project) = target.project::<Project<_>>() {
println!(
" Bryn commented on project {} on {}",
project.name(),
timestamp
);
}
}
}
})
.count();
Best Practices
- Insert probe steps at key points in complex traversals to verify correct behavior
- Use descriptive logging within probes to make debugging output meaningful
- Add counters or statistics collection to understand traversal performance
- Keep probe functions simple and side-effect only; don't try to affect the traversal flow
Common Use Cases
- Debugging: Inserting temporary probe steps to understand traversal behavior
- Logging: Recording traversal information during development or in production
- Metrics collection: Gathering statistics about traversal performance and results
- Inspection: Examining element properties at specific points in the traversal