Package: kiekerforpython
READMEDisclaimerThe Kieker language pack for Python is in an early stage. This means any code in
this repository is not functional or usable in any way other than evaluating how
to implement Python instrumentation.InstalationPrerequisites:python >=3.9build package (pip install build)clone this repositorycd ./kieker-lang-pack-pythonrun python3 -m buildpip install dist/kieker-monitoring-for-python-0.0.1.tar.gzInstrumentationInvasive ApproachThis is the most basic and invasive approach. Currently, it also offers the most control over the instrumentation.
Let's assume that you want to log following function every time it is called.example.pydefsome_function():print('Hello World!')example.pyimporttools.constascondefsome_function():print('Hello World!')Now we have everything we need to log the function execution.
At the current stage of development there are three record types with following entries.BeforeOperationEvent: timestamp in ms, traceId, traceOrder, function_name, fully qualified name of caller classAfterOperationEvent: timestamp in ms, traceId, traceOrder, function_name, fully qualified name of caller classAfterOPerationFailedEvent: timestamp in ms, traceId, traceOrder, function_name, fully qualified name of caller class, error nameCreate a record object and pass it to the monitoring controler vianew_monitoring_record(). In our example we useBeforeExecutionRecordandAfterExecutionRecord.example.pyimportconstasconfrommonitoring.record.trace.operation.operationeventimport(BeforeOperationEvent,AfterOperationEvent,AfterOperationFailedEvent,)ctrl=SingleMonitoringController('/path/to/config.ini')defsome_function():trace_reg=con.trace_regtrace=trace_reg.get_trace()if(traceisNone):trace=trace_reg.register_trace()monitoring_controller.new_monitoring_record(trace)trace_id=trace.trace_idtimestamp=ctrl.time_source_controller.get_time()before_record=BeforeOperationevent(timestamp,trace_id,trace.get_next_order_id(),'some_function','example.some_function')ctrl.new_monitoring_record(before_record)print('Hello World!')timestamp=ctrl.time_source_controller.get_time()after_record=AfterOperationEvent(timestamp,trace_id,trace.get_next_order_id(),'some_function','example.some_function')ctrl.new_monitoring_record(after_record)Semi Invasive ApproachThe above method gives us full control over program instrumentation, but it also requieres a lot of manual work. But this approach alters your own code logic, which might not be a problem for small projects, but for larger code basis it becomes a tedious job to keep an overview. To minimize the grade of source code manipulation you can use anInstrumentdecorator. By anotation a function or method with@Instrumentyou can save a lot of typing. Consider the following example.example.pyfromtools.aspectimportinstrumentfrommonitoring.controllerimportSingleMonitoringControllermonitoring_controller=SingleMonitoringController('/path/to/config.ini')# Always instatiate a controller@instrumentdefsome_function():print('Hello World!')Import HooksWe also provide two import Hooks. They are used in similar manner. All you have to do is to add either PostImportFinder or InstrumentOnImportFinder to the
sys.meta_path in the module which is a an entry point for your python program.
Bellow we show all the necessary API to do that.Post Import Hookfromtools.importhookimportPostImportFinderfrommonitoring.controllerimportSingleMonitoringControllerpattern_object=re.compile('YOUR REGEX')# Some regex to describe which modules should be instrumentedexclude_modules=list()# List with explicit strings of modules which should be excluded from the instrumentationssome_var=SingleMonitoringController('/path/to/config.ini')sys.meta_path.insert(0,PostImportFinder(pattern_object,exclude_modules))Pre Import Hookimportrefromtools.aspectimportdecorate_find_specfromtools.importhookastimportInstrumentOnImportFinderex=list()sys.meta_path.insert(0,InstrumentOnImportFinder(ignore_list=ex,empty=False,debug_on=True))