Skip to main content

CI PyPI Python Versions

Absynthe: A (branching) Behavior Synthesizer

Motivation

Absynthe came about in response to the need for test data for analysizing the performance and accuracy of log analysis algorithms. Even though plenty of real life logs are available, e.g. /var/log/ in unix-based laptops, they do not serve the purpose of test data. For that, we need labels, which are difficult to obtain without an understanding the source code of the applications that are generating these logs.

A more interesting situation arises while trying to test log analytic (and anomaly detection) solutions for distributed applications where multiple sources or modules emit their respective log messages in a single log queue or stream. This means that consecutive log lines could have originated from different, unrelated application components. Absynthe provides ground truth models to simulate such situations.

You need Absynthe if you wish to simulate the behavior of any well defined process -- whether it's a computer application or a business process flow.

Overview

Each business process or compuater application is modelled as a control flow graph (or CFG), which typically has one or more roots (i.e. entry) nodes and multiple leaf (i.e. end) nodes.

Tree-like CFG

An example of a simple, tree-like CFG generated using Absynthe is shown below. This is like a tree since nodes are laid out in levels, and nodes at level i have outgoing edges only to nodes at level i + 1.

Each behavior is the sequence of nodes encountered while traversing this CFG from a root to a leaf. Of course, a CFG might contain loops which could be traversed multiple times before arriving at the leaf. Moreover, if there are multiple CFGs, then Absynthe can synthesize interleaved behaviors. This means that a single sequence of nodes might contain nodes from multiple CFGs. We are ultimately interested in this interleaving behavior, which is produced by multiple CFGs.

The above screenshot shows logs generated by Absynthe. Each log line starts with a time stamp, followed by a session ID, CFG ID, and a log message. At present, the log message is simply a random concatenation of the node ID to which the log message corresponds. A single CFG might participate in multiple sessions, where each session is a different traversal of the CFG. Therefore, we maintain both session ID and CFG ID in the log line.

Directed Cyclic CFG

An example of a more complex CFG, a directed cyclic graph, is shown in the figure below. It expands the tree-like graph illustrated above by:

  1. attaching loops on some of the nodes,
  2. constructing skip-level edges, i.e. edges from a node at level i to a node at level ≥(i + 2), and
  3. optionally, upward edges (not shown here), i.e. edges from a node at level i to a node at level ≤(i - 1).

The identifiers of nodes appearing loops are helpfully prefixed with the identifiers of nodes where these loops start and finish. Moreover, loops could be traversed multiple times in a single behavior, as illustrated in the figure below.

Installation

This package requires Python >= 3.10 and depends on scipy.

The latest release is available on PyPI, simply pip install absynthe.

The main branch of this repository always contains the latest source, including any changes merged since the last tagged release. To install from source:

# Change dir to absynthe
cd /path/to/absynthe

# Install absynthe and its dependencies
pip install .

Usage

It is possible to start using Absynthe with two classes:

  1. any concrete implementation of the abstract GraphBuilder class, which generates CFGs, and
  2. any concrete implementation of the abstract Behavior class, which traverses the CFGs generated above and emits log messages.

For instance, consider the basicLogGeneration method in ./examples/01_generateSimpleBehavior.py:

from absynthe.graph_builder import TreeBuilder
from absynthe.behavior import MonospaceInterleaving


def basicLogGeneration(numRoots: int = 2, numLeaves: int = 4,
                       branching: int = 2, numInnerNodes: int = 16,
                       loggerNodeTypes: str = "SimpleLoggerNode"):
    # Capture all the arguments required by GraphBuilder class
    tree_kwargs = {TreeBuilder.KW_NUM_ROOTS: str(numRoots),
                   TreeBuilder.KW_NUM_LEAVES: str(numLeaves),
                   TreeBuilder.KW_BRANCHING_DEGREE: str(branching),
                   TreeBuilder.KW_NUM_INNER_NODES: str(numInnerNodes),
                   TreeBuilder.KW_SUPPORTED_NODE_TYPES: loggerNodeTypes}

    # Instantiate a concrete GraphBuilder. Note that the
    # generateNewGraph() method of this class returns a
    # new, randomly generated graph that (more or less)
    # satisfies all the parameters provided to the
    # constructor, viz. tree_kwargs in the present case.
    simpleTreeBuilder = TreeBuilder(**tree_kwargs)

    # Instantiate a concrete behavior generator. Some
    # behavior generators do not print unique session ID
    # for each run, but it's nice to have those.
    exBehavior = MonospaceInterleaving()

    # Add multiple graphs to this behavior generator. The
    # behaviors that it will synthesize would essentially
    # be interleavings of simultaneous traversals of all
    # these graphs.
    for _ in range(4):
        # Add 4 graphs to the behavior
        exBehavior.addGraph(simpleTreeBuilder.generateNewGraph())

    # Specify how many behaviors are to be synthesized,
    # and get going.
    wSessionID: bool = True
    numTraversalsOfEachGraph: int = 2
    for logLine in exBehavior.synthesize(numTraversalsOfEachGraph, wSessionID):
        print(logLine)
    return

In order to generate behaviors from a directed cyclic CFG, create a DCG as shown in ./examples/03_generateControlFlowDCG.py and then generate behaviors after adding the DCG to a behavior object as shown in the code snippet above.

Note: When generating a behavior, i.e. when traversing a graph, successors of nodes are chosen based on the probability distributions associated with those nodes. Different nodes rely on different distributions and these nodes are randomly assigned in the graphs that are constructed by generateNewGraph() methods, resulting in graphs with a mix of nodes.

Release Notes

Note: This tool is still in alpha stage, so backward compatibility is not guaranteed between releases. However, inasmuch as users stick to graph builders' generateNewGraph() methods, they will stay away from compatibility problems.

Major changes in v0.1.0

  1. Repo revival and modernization: packaging migrated from setup.py to pyproject.toml (hatchling), dependency management via uv, ruff for linting/formatting, mypy for type checking, pytest for tests, GitHub Actions for CI, and a Trusted Publishing (OIDC) release flow to PyPI -- replacing the old, manual twine upload process.
  2. Dropped support for Python < 3.10. Python 3.10-3.13 are tested in CI.
  3. Merged in previously unreleased work from the develop branch: a new MonospaceSimple behavior class, and the withSessionID flag moved from MonospaceInterleaving's constructor to its synthesize() method (breaking change for any existing callers of MonospaceInterleaving.__init__).
  4. Dropped the unused numpy dependency; scipy is now the only runtime dependency.

Major changes in v0.0.2

  1. Added new graph builders, viz. DAGBuilder and DCGBuilder, which build CFGs with skip-level edges and loops respectively.
  2. Added new node, viz. BinomialNode, which exploits the binomial distribution in order to select its successors at the time of graph traversal.
  3. Added a separate utility class called Utils in absynthe.cfg.utils.py to create a new Node object from any of the concrete implementations of Node at random. All concrete implementations of Node therefore transparently available to graph builders (and everyone else) through this utility.

Coming up in future releases

  1. Sophisticated interleaving behaviors
  2. Logger nodes that emit more life like log messages
  3. Anomalous behaviors

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

absynthe-0.1.0.tar.gz (22.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

absynthe-0.1.0-py3-none-any.whl (23.2 kB view details)

Uploaded Python 3

File details

Details for the file absynthe-0.1.0.tar.gz.

File metadata

  • Download URL: absynthe-0.1.0.tar.gz
  • Upload date:
  • Size: 22.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for absynthe-0.1.0.tar.gz
Algorithm Hash digest
SHA256 1f06d674478a7869937c2018dcfdf51be7974cb5746db0df0582dfe55e2c732c
MD5 3e2cc92be46a85bcc83872a4acc88a8f
BLAKE2b-256 7766df46e96f79ba59ce0aa0eb12fb9dcf107e96e9bfd416aab61dc01c3b6806

See more details on using hashes here.

Provenance

The following attestation bundles were made for absynthe-0.1.0.tar.gz:

Publisher: publish.yml on chaturv3di/absynthe

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file absynthe-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: absynthe-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 23.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for absynthe-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0c79e15b962f7e355b277e04e7c64cdbe28e0d2d5778241663ff87d4e4fbd6ee
MD5 a1577ec5186afb5942fea1cc15f9adc7
BLAKE2b-256 315317a75b07a25f7f80e6ba1bfde0647260f5e17f049826be78559e10bb124f

See more details on using hashes here.

Provenance

The following attestation bundles were made for absynthe-0.1.0-py3-none-any.whl:

Publisher: publish.yml on chaturv3di/absynthe

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 files

0.0.3

2 files

0.0.2

2 files

0.0.1

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page