Wrapture bindings, originally used for unit testing, can also serve as a powerful tracing mechanism. A binding observes method calls and emits events, which are then processed by a "sink" instead of a test tape. This allows for real-time narration of a running program.The article illustrates this with an OrderService, including a Gateway, Ledger, and Notifier, where card payments can be declined. Three bindings are applied to key methods: OrderService.place, Gateway.charge, and Ledger.record. A simple Printer sink is used to display these events.The output shows detailed call information, including arguments, return values, and exceptions, with indentation indicating call nesting. Crucially, sensitive data like card numbers can be redacted using wrapture.redact() capture policies at the binding level.When no sink is registered, bindings incur minimal overhead, running at about half a microsecond per call. To manage large traces, filtering can be applied at the sink or binding level.Sink-level filtering, like wrapture.Depth(1, wrapture.Printer()), limits output to top-level calls, providing a concise overview. Binding-level filtering using when= takes a predicate to prevent event construction for specific calls, making it very efficient.However, when= only skips the specified event; nested calls still record. To suppress an entire call tree, tree=True can be added to the binding, ensuring "nothing from here down" is traced.Bindings also track filtered_calls, allowing users to understand which operations were suppressed. This setup enables programs to self-describe their actions with real-time data, with minimal code changes and customizable sinks for various monitoring needs.
wrapture.redact()capture policies at the binding level.When no sink is registered, bindings incur minimal overhead, running at about half a microsecond per call. To manage large traces, filtering can be applied at the sink or binding level.Sink-level filtering, likewrapture.Depth(1, wrapture.Printer()), limits output to top-level calls, providing a concise overview. Binding-level filtering usingwhen=takes a predicate to prevent event construction for specific calls, making it very efficient.However,when=only skips the specified event; nested calls still record. To suppress an entire call tree,tree=Truecan be added to the binding, ensuring "nothing from here down" is traced.Bindings also trackfiltered_calls, allowing users to understand which operations were suppressed. This setup enables programs to self-describe their actions with real-time data, with minimal code changes and customizable sinks for various monitoring needs.