Class Logger

java.lang.Object
com.amalgamasimulation.utils.logging.Logger

public class Logger extends Object
Writes log messages to log files.

All log files that belong to the same logging session are located in the same output folder.
A log file is a tab-separated CSV file with the ".log" extension.
One instance of the Logger class can be concurrently used by several message sources (such as simulation models running at the same time). All messages of the same type are written to the same log file, so there is only one file per message type.

Example

 
 // 1
 public record ExperimentDescriptor(@LogColumnName("Name") String name, 
                                    @LogColumnName("Seed") int seed) {}
 // 2
 @LogName("Deliveries")
 public record DeliveryMessage(@LogColumnName("Product") String product, 
                               @LogColumnName("Amount") double amount) {}
 @LogName("StockOnHand")
 public record SOHMessage(@LogColumnName("SOH") double totalStockOnHand, 
                          @LogColumnName("date") String date) {}
 // 3
 Logger logger = new Logger();
 // 4
 logger.openSession("d://logs");
 // 5.1
 logger.log(new DeliveryMessage("Wood", 100), new ExperimentDescriptor("A", 1));
 // 5.2
 logger.log(new SOHMessage(500, "2022-05-23"));
 // 5.3
 logger.log(new SOHMessage(700, "2022-05-24"));
 // 6
 logger.closeSession();
 
 

Example description

1
This record defines the structure of the 'event source key'. Event from several sources can be written to the same log file, so 'event source' helps to understand where each event comes from. The LogColumnName annotations are used to define the column names in the log file. Column names are printed as the first line of each log file.

2
These two records define the structure of the logged data and set the names of their log files (via the LogName annotations). The LogColumnName annotations are used to define the column names in the log files.

3
A new instance of the 'Logger' class is created. At this point, no logging session is started yet, so any attempt to write a log message will be silently ignored.

4
A new logging session is started. All files in the supplied folder are deleted. The logger is ready to accept log messages.

5.1
Several log messages are logged via the 'logger' object.
Upon the first message, a new log file (named "Deliveries.log", as defined in the LogName annotation of the 'DeliveryMessage' record) is created; a header string and the passed message are written to it. The header string and each message in this log file contain 4 columns: 2 from the 'ExperimentDescriptor' and 2 from the 'DeliveryMessage'.

5.2
When the second message is logged, a new log file (named "StockOnHand.log") is created, a header string and a message is written to this file. There are two columns in the log file (defined in the 'SOHMessage' record).

5.2
The 3rd message is written to the already created "StockOnHand.log" file.
More messages can be written here before the logging session is closed.

6
The logging session is closed. Any messages that have been accepted by the logger instance are flushed to disk, and the output log files are closed. Any attempt to write a message beyond this point will be silently ignored.
However, it is possible to start a new logging session (i.e., go to step 4).

Creating a logging session
A newly created Logger instance has no active logging session, so logging is initially disabled.
To start a new logging session, use the openSession(String) method. This method:

  • closes the current logging session (if any);
  • prepares the passed logging folder by removing all old *.log files in it;
  • creates a new logging session and enables logging in this Logger instance.
When a Logger instance has an active logging session, all logging messages that are passed to its log(Record, Record) or log(Record) methods are written to the respective log files.

Closing a logging session
When a Logger instance has no active logging session, all logging messages that are passed to the log(Record, Record) or log(Record) methods are ignored without any warning or error.
To close the current logging session (if any), call the closeSession() method.

Writing log messages
Use the log(Record, Record) or log(Record) methods to write a log message. The message is written to its log file only if the Logger instance has an active session.

Author:
Kliment Zakharov
  • Constructor Details

    • Logger

      public Logger()
  • Method Details

    • startNewLoggingSession

      @Deprecated(forRemoval=true) public void startNewLoggingSession(String logFolderFullPath)
      Deprecated, for removal: This API element is subject to removal in a future version.
      Starts a new logging session and enables logging.

      All "*.log" files in the provided log folder are deleted.

      If an active logging session already exists, then it is closed, and another logging session is started.

      Parameters:
      logFolderFullPath - path to the folder where the new logging session will place its log files (any already existing *.log files will be deleted)
      See Also:
    • openSession

      public void openSession(String logFolderFullPath)
      Starts a new logging session and enables logging.

      All "*.log" files in the provided log folder are deleted.

      If an active logging session already exists, then it is closed, and another logging session is started.

      Parameters:
      logFolderFullPath - path to the folder where the new logging session will place its log files (any already existing *.log files will be deleted)
      See Also:
    • closeLoggingSession

      @Deprecated(forRemoval=true) public void closeLoggingSession()
      Deprecated, for removal: This API element is subject to removal in a future version.
      Use closeSession() instead
      Finishes the current logging session (if any), closes all opened log files, and disables logging. All log information is flushed to disk.

      After the logging session has been closed, any subsequent calls to log(Record, Record) or log(Record) will be ignored until a new logging session is started.

      As the application exits, any active (not closed) logging session is closed automatically.

      See Also:
    • closeSession

      public void closeSession()
      Finishes the current logging session (if any), closes all opened log files, and disables logging. All log information is flushed to disk.

      After the logging session has been closed, any subsequent calls to log(Record, Record) or log(Record) will be ignored until a new logging session is started.

      As the application exits, any active (not closed) logging session is closed automatically.

      See Also:
    • getLogFolderFullPath

      public String getLogFolderFullPath()
      Returns the full path to the folder that contains log files of the current logging session. Returns null if there is no active logging session.

      Note that even if a logging session is started and this method returns a non-null result, the log folder itself may have not yet been created on disk: if the folder is missing, then it is automatically created when the first message is written to a log file.

    • log

      @Deprecated public <E extends Record> void log(E event, String scenarioFileName, String scenarioName, int randomSeed)
      Deprecated.
      Use log(Record, Record) instead.
      Writes a log message to a log file.

      Calls log(Record, Record) and uses (scenarioFileName, scenarioName, randomSeed) as the event source key.

      Parameters:
      scenarioFileName - Scenario file name. Part of the "event source key".
      scenarioName - Scenario descriptive name. Part of the "event source key".
      randomSeed - Simulation random seed. Part of the "event source key".
    • log

      public <B extends Record, K extends Record> void log(B eventBody, K eventSourceKey)
      Writes a log message to a log file.

      Event body type is a public Java Record annotated with LogName that consists of fields annotated with LogColumnName.
      Here is an example:

       @LogName("Deliveries")
       public record DeliveryLogRecord(	
          @LogColumnName("Delivery Id")        String id, 
          @LogColumnName("Source Location Id") String sourceLocId, 
          @LogColumnName("Dest Location Id")   String destLocId
       ) {}
       
       
      Messages of the same body type belong to the same topic and are placed to the same log file.

      To distinguish the results from several message sources (like, for example, several scenario comparison experiments running concurrently), an "event source key" is also written to the log file, beside (to the left of) the log message body contents.
      Event source key type is a public Java Record that consists of fields annotated with LogColumnName. Here is an example:

      
       public record ExperimentDescriptor(	
          @LogColumnName("Scenario file name") String scenarioFileName, 
          @LogColumnName("Scenario name") String scenarioName, 
          @LogColumnName("Seed") int randomSeed
       ) {}
       
       

      In a logger set up to use such DeliveryLogRecord and ExperimentDescriptor, messages will be placed in a log file named 'Deliveries.log' (as defined by the LogName annotation of the DeliveryLogRecord). The file will have three "event source key" columns ("Scenario file name", "Scenario name", and "Seed") and three columns with event body data ("Delivery Id", "Source Location Id", and "Dest Location Id").
      There will be a header line with column names. Column order in the log file is the same as in its defining Java Records; event source key column go before event body columns.

      Thread-safety
      It is safe to call this method concurrently from several threads: file writing operations are properly synchronized.
      It is also safe to call this method any time, whether a logging session is created or not. A method call is silently ignored if there is no active logging session.

      Type Parameters:
      B - Event body type. Must be a public Java record annotated with the LogName annotation, with every field having the LogColumnName annotation.
      K - Event source key type. Must be a public Java record with every field having the LogColumnName annotation.
      Parameters:
      eventBody - event body to be logged
      eventSourceKey - event source key to be logged
    • log

      public <B extends Record> void log(B eventBody)
      Writes a log message to a log file.
      Event source key is not supplied and is not written to a log file.
      Type Parameters:
      B - Event body type. Must be a public Java record annotated with the LogName annotation, with every field having the LogColumnName annotation.
      Parameters:
      eventBody - event body to be logged
      See Also: