(Detailed Design) Aleph2 logging overview - IKANOW/Aleph2 GitHub Wiki
Overview
Logging allows users to send messages to the storage, search, columnar, and temporal service for debugging/metrics collections. Messages are sent to a unique logging bucket created for each bucket (similar to test buckets) unless using the external service logger (which logs to its own unique bucket).
The typical way to view log messages is allowing them to output to the search_index_service (Elasticsearch) and viewing them in Kibana. The Infinite V2 Record Viewer widget has built in support for looking at logging messages by clicking using the logging toggle button.
Adding the LoggingService to your project
Adding it to a technology
Logging can be added to a technology (such as a harvester/analytic) by accessing the logger through the IHarvestContext or IAnalyticsContext. As contexts are already bucket specific you can just call
IBucketLogger logger = context.getLogger(Optional.empty());
Adding it to a service
Logging can be added to a service by retrieving the ILoggingService from the IServiceContext. Once you have the configured ILoggingService you can get a user/system/external IBucketLogger via ILoggingService.
ILoggingService logging_service = service_context.getService(ILoggingService.class, Optional.empty()).get(); IBucketLogger logger = logging_service.getLogger(Optional.of(bucket));
#Using the BucketLogger IBucketLogger has many functions to log messages, it has 3 main modes:
- Normal - IBucketLogger.log(Level, IBasicMessageBeanSupplier) - this method and the helpers that build an IBasicMessageBeanSupplier just pass the message through a filter and output it if it matches. This is the normal way to use the logger
- Merge - IBucketLogger.log(Level, IBasicMessageBeanSupplier, merge_key, ...) - these methods allow merging log messages, they will be mapped to the same merge function via the merge_key you pass in and you can perform various aggregations on the log messages. Examples of when you want to use these would be for summing up processing time in functions by outputting log messages every step and summing a time_taken_ms variable in the details, you can also apply rules on when to emit merged messages, e.g. when that time_taken_ms sum exceeds 5000.
- Inefficient - IBucketLogger.inefficientLog(Level, BasicMessageBean) - this method is inefficient because you are required to build the BasicMessageBean object even if this message is going to be filtered out and not emitted. It should be used sparingly.
#Configuration If you need to configure the logging service, see the reference on this page: https://github.com/IKANOW/Aleph2/wiki/Aleph2:-configuration-reference
#Examples
-
Normal Usage
//...in some method that passed in a context and bucket e.g. IHarvestTechnologyModule.onXXX final IBucketLogger user_logger = context.getLogger(Optional.of(bucket)); user_logger.log(Level.ERROR, false, ()->"Error getting some value :" + some_value, ()->this.class.getSimpleName());
-
Merge Usage
//...in some method that passed in a context and bucket e.g. IHarvestTechnologyModule.onXXX final IBucketLogger user_logger = context.getLogger(Optional.of(bucket)); final IBasicMessageBeanSupplier message = new BasicMessageBeanSupplier(false, ()->this.class.getSimpleName(), ()->"onUpdatedSource", ()->null, ()->"some output message", ()->ImmutableMap.of("proc_time_ms", 2.34)); //merge messages with "job1_merge_key" //merged messages sum up the field "proc_time_ms" and output the sum into "proc_time_ms_sum" //once proc_time_ms_sum exceeds 5000, emit a message //before message is emitted, format it with the output message: Error: processing time exceeded 5000ms ("+b.details().get("proc_time_ms_sum")+" ms) user_logger.log(Level.ERROR, message, "job1_merge_key", Arrays.asList(LoggingRules.logOutsideThreshold("proc_time_ms_sum", Optional.empty(),Optional.of(5000.0))), Optional.of((b)->{return BeanTemplateUtils.clone(b).with(BasicMessageBean::message,"Error: processing time exceeded 5000ms ("+b.details().get("proc_time_ms_sum")+" ms)").done();}), LoggingMergeFunctions.sumField("proc_time_ms","proc_time_ms_sum"));
-
Inefficient Usage
//...in some method that passed in a context and bucket e.g. IHarvestTechnologyModule.onXXX
final IBucketLogger user_logger = context.getLogger(Optional.of(bucket));
user_logger.inefficientLog(Level.ERROR, ErrorUtils.buildErrorMessage(this.class.getSimpleName(),"onUpdatedSource","Error getting some value: " + some_value));