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.

Probe step diagram showing elements flowing through, side effects, and unchanged output stream

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