Library Coordination¶
Application and Module with Custom Flavors¶
When the application installs its own truck configuration, any module configurations registered by libraries will be preserved. This allows:
Applications to control global settings like trace levels.
Libraries to maintain their own debug output formatting.
Both to coexist without configuration conflicts.
(Example courtesy of Anthropic claude-3-7-sonnet.)
An example application which uses a library module for some analytics:
# ruff: noqa: F821
import os
import sys
# Ensure that our demonstration package is available.
sys.path.insert( 0, os.path.dirname( __file__ ) )
import ictruck
# Application installs truck with both trace levels and active flavors.
# While active flavors could be global, targeting a particular package
# generally makes more sense.
#
# Installation needs to happen before module registers itself.
ictruck.install(
trace_levels = 2,
active_flavors = { 'analytics': [ 'info', 'error', 'perf' ] } )
from analytics import calculate_metrics, detect_anomalies # noqa: E402
def main( ):
ictr( 0 )( "Application running." )
normal_data = [ 10, 12, 11, 13, 10, 14, 12, 11, 10, 13 ]
ictr( 0 )( "Calculating metrics..." )
metrics = calculate_metrics( normal_data )
ictr( 1 )( metrics ) # Greater depth for more detail.
anomaly_data = [ 10, 12, 11, 13, 10, 40, 12, 11, 10, 13 ]
ictr( 0 )( "Detecting anomalies..." )
anomalies = detect_anomalies( anomaly_data )
if anomalies:
summary = f"Found {len( anomalies )} anomalies."
ictr( 1 )( summary )
for position, value, z_score in anomalies:
ictr( 2 )( position, value, z_score )
ictr( 0 )( "Calculating metrics on empty dataset..." )
calculate_metrics( [ ] )
ictr( 0 )( "Application finished" )
if __name__ == "__main__": main( )
And the library module for analytics:
# ruff: noqa: F821
from typing_extensions import Any
from ictruck import register_module, FlavorConfiguration
# Register module with custom flavors.
register_module(
flavors = {
'info': FlavorConfiguration( prefix_emitter = "ANALYTICS INFO| " ),
'error': FlavorConfiguration( prefix_emitter = "ANALYTICS ERROR| " ),
'perf': FlavorConfiguration( prefix_emitter = "ANALYTICS PERF| " ) } )
def calculate_metrics( dataset: list[ int ] ) -> dict[ str, Any ]:
''' Calculates statistical metrics from dataset. '''
ictr( 'info' )( "Calculating metrics..." )
if not dataset:
ictr( 'error' )( "Empty dataset provided." )
return { }
try:
count = len( dataset )
total = sum( dataset )
average = total / count
minimum = min( dataset )
maximum = max( dataset )
variance = sum( ( x - average ) ** 2 for x in dataset ) / count
std_dev = variance ** 0.5
except Exception as exc:
ictr( 'error' )( exc )
return { }
metrics: dict[ str, Any ] = {
'count': count,
'total': total,
'average': average,
'minimum': minimum,
'maximum': maximum,
'variance': variance,
'std_dev': std_dev,
}
ictr( 'info' )( "Metrics calculation complete." )
ictr( 'perf' )( count )
return metrics
def detect_anomalies(
dataset: list[ int ], threshold = 2.0
) -> list[ tuple[ int, int, float ] ]:
''' Detects anomalies in dataset using standard deviation. '''
ictr( 'info' )( f"Detecting anomalies with threshold {threshold}." )
if not dataset:
ictr( 'error' )( "Empty dataset provided." )
return [ ]
metrics = calculate_metrics( dataset )
if not metrics: return [ ]
anomalies: list[ tuple[ int, int, float ] ] = [ ]
for i, value in enumerate( dataset ):
z_score = abs( value - metrics[ 'average' ] ) / metrics[ 'std_dev' ]
if z_score > threshold:
anomalies.append( ( i, value, z_score ) )
ictr( 'perf' )( len( anomalies ) )
return anomalies
Running this will result in:
TRACE0| 'Application running.'
TRACE0| 'Calculating metrics...'
ANALYTICS INFO| 'Calculating metrics...'
ANALYTICS INFO| 'Metrics calculation complete.'
ANALYTICS PERF| count: 10
TRACE1| metrics: {'average': 11.6,
'count': 10,
'maximum': 14,
'minimum': 10,
'std_dev': 1.3564659966250536,
'total': 116,
'variance': 1.8399999999999999}
TRACE0| 'Detecting anomalies...'
ANALYTICS INFO| f"Detecting anomalies with threshold {threshold}.": 'Detecting anomalies with threshold 2.0.'
ANALYTICS INFO| 'Calculating metrics...'
ANALYTICS INFO| 'Metrics calculation complete.'
ANALYTICS PERF| count: 10
ANALYTICS PERF| len( anomalies ): 1
TRACE1| summary: 'Found 1 anomalies.'
TRACE2| position: 5, value: 40, z_score: 2.975954728492207
TRACE0| 'Calculating metrics on empty dataset...'
ANALYTICS INFO| 'Calculating metrics...'
ANALYTICS ERROR| 'Empty dataset provided.'
TRACE0| 'Application finished'