It is obvious that Logging are used for three very distinct purposes, and in our opinion the concepts are not related and should not be abstracted in the same fashion, as has been the norm in Log4j, JDK logging, Commons Logging and most other similar packages and APIs.
Tracing - Developers often need to trace where the application has been, recording the sequence of execution to see if the logic is correct. This is often a choice when stepping through with a debugger is not possible for whatever reason.
Debugging - Developers like to get additional information out from a running system. This could be information about conditions, events or unexpected results that we want to record and analyse later.
Logging - The requirements of an application sometimes specifies that events or conditions should be recorded for auditing purposes. These are often described as domain events and written to a special log file and/or printed to log printer.
Although similar in nature, the audience are very different in Logging vs Debugging/Tracing and their requirements are not only different, but if not handled properly the debug log is mixed up with the audit logs, which in turn can lead to turning off whole or parts of the domain logging by mistake. We want to avoid this, and instead crystalize the needs for each scenario and audience.
Another drastic difference from previous frameworks is that we don't have an Appender notion. All messages are entities which are stored in a configured entity store. This means that especially the domain log can be more easily be given a user interface suitable for the domain, without complex parsing of message strings
Logging is still not finalized and will need a lot more thought before considered done.
To produce debugging output in your code you just need to add
You will also need to declare a DebugService to be visible to the composite where the debug output is coming from. And the DebugService in turn will use the default UnitOfWork and associated entity store, which must also be configured and visible.
If the TraceAllConcern is added to a composite, and there is a TraceService visible, then all method calls into that composite is traced.
If a subset of the methods want to be traced, you can annotate those methods with @Trace in either the Composite Type interface or the mixin implementation. You will also need to add the TraceConcern to the composite.
@Trace
void removeImportantStuff( ImportantStuff stuff );
ImportantStuff findImportantStuff( String searchKey );
}
The fact that each TraceConcern (and TraceAllConcern) will use the TraceService that is visible, allows you to enable or disable tracing per module, simply by adding or removing a TraceService with Visibility.module in each module you want it, or expose Visibility.layer and turn on/off tracing by layers. The TraceConcern has the TraceService as optional.
The recommended way to enable tracing is to use contexual fragments, a feature that allows you to add concerns, sideeffects and mixins to composites during the bootstrap phase instead of hard-coded into the composite declaration.