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 applications!

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

from logot import Logot, logged

def test_my_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_my_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_my_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_my_app(logot: Logot) -> None:
   app.start()
   logot.wait_for(
      logged.info("App stopped")
      | logged.error("App crashed!")
   )