Log pattern matching¶

logot makes it easy to match logs that may arrive in an unpredictable order. This is especially useful in threaded or asynchronous code. 💪

Compose your logot.logged calls with special log pattern operators:

from logot import Logot, logged

def test_app(logot: Logot) -> None:
   app.start()
   logot.wait_for(
      # Wait for the app to start...
      logged.info("App started")
      # ...then wait for the app to stop *or* crash!
      >> (
         logged.info("App stopped")
         | logged.error("App crashed!")
      )
   )

Note

Log pattern operators are infinitely composable! Use () brackets when needed to define complex log patterns.

Available operators¶

Sequential logs¶

Use the >> operator to wait for logs that must arrive in a sequential order:

from logot import Logot, logged

def test_app(logot: Logot) -> None:
   app.start()
   logot.wait_for(
      logged.info("App started")
      >> logged.info("App stopped")
   )

Parallel logs¶

Use the & operator to wait for logs that must arrive in any order:

from logot import Logot, logged

def test_app(logot: Logot) -> None:
   app.start()
   other_app.start()
   logot.wait_for(
      logged.info("App started")
      & logged.info("Other app started")
   )

Any logs¶

Use the | operator to wait for any matching log pattern:

from logot import Logot, logged

def test_app(logot: Logot) -> None:
   app.start()
   logot.wait_for(
      logged.info("App stopped")
      | logged.error("App crashed!")
   )