Patent Description:
The presented disclosure relates to the first phase of automatic log messages analysis which is usually known as log parsing. One of the main goals of log parsing is the categorization of individual log lines to groups describing application events of the same type with possibly different event parameters.

Computer systems are becoming an indispensable part of our everyday life. Software systems control traffic lights, railway and flight operations, manage the credit card payments, provides us with personalized information, and are present in almost all branches of industry and services. Simultaneously, the complexity of such systems is continuously increasing, while the requirement for their operability becomes even more important. The maintenance of such systems becomes a critical, yet a very complex task.

Application log files are invaluable and often even indispensable sources of information on the computer system health. Such files typically contain various types of messages informing about current activities performed by a system, encountered warning states and errors. A log file is usually composed of a sequence of log lines. The log line format heavily depends on logging framework type used in the application and its configuration. However, in most cases, a log line contains the following three types of information (called fields), i.e., timestamp, log level (e.g., INFO for statement describing normal behavior, WARN, ERROR for abnormal situations), and a human readable message describing the activity or state. : "<NUM>-<NUM>-<NUM><NUM>:<NUM>:<NUM>,<NUM> +<NUM> INFO [ConfigurationGetTask] Getting configuration from device <NUM>. <NUM>:<NUM>, for user sampleUserName finished in <NUM>", where timestamp "<NUM>-<NUM>-<NUM><NUM>:<NUM>:<NUM>,<NUM> +<NUM>" appears as the first field, "INFO" is the log level, and the actual message "[ConfigurationGetTask] Getting configuration from device <NUM>. <NUM>:<NUM>, for user sampleUserName finished in <NUM>" appears as the last part of the log line. In general, there is no restriction on the content of log line message part, so it is not so uncommon that a single message is composed of multiple lines, what for instance, is a very popular practice for logging exceptions. Here, by a log line we will denote a part of a log file corresponding to a single event in the application, which is composed of a timestamp of the event, an actual log message (possibly containing new line characters) and optionally additional fields describing the event, e.g., severity.

The number of log lines that an application can write in a given period depends on its specific design, configured log details level and the external conditions under which the application is working (e.g., number of end users). The overall complexity of the systems is correlated with the number of diagnostic information in their application logs. Hence, analyzing raw log files can be a very tedious task. Therefore, intelligent log viewer applications try to group related log lines and show them as a single category to the user. All the log lines within such a group should concern the same event type with the same or different parameter values. An event type is represented by all possible log lines that can be obtained from a particular log message template placed in a source code, e.g.: "<NUM>-<NUM>-<NUM><NUM>:<NUM>:<NUM>,<NUM> +<NUM> INFO [ConfigurationGetTask] Getting configuration from device <NUM>. <NUM>:<NUM>, for user sampleUserName finished in <NUM>" and "<NUM>-<NUM>-<NUM><NUM>:<NUM>:<NUM>,<NUM> +<NUM> INFO [ConfigurationGetTask] Getting configuration from device <NUM>. <NUM>:<NUM>, for user sampleUserName finished in <NUM>" represent the same application event type since both the lines come from the same template and the same line in the source code, i.e.: "LOG. info(MessageFormat. format("Getting configuration from device {<NUM>}, for user {<NUM>} finished in {<NUM>}s", device. getlp(), device. getUser(), stopper. getTo-talTime()));".

However, the task (usually referred to as log parsing) of efficiently inferring the correct event templates from a list of log lines using only a log file content is challenging and as such is still the subject of many current research projects, see for example "<NPL>" or "<NPL> et al.

Among others, the following two aspects make it difficult. First, based on a single log line, it is often not possible to tell which of the tokens should be treated as parameters and which should be the part of the template. Although, some heuristic approaches can be used, e.g., it may be assumed that all numbers can be parameters, it is still unclear how to recognize variable parts consisting of only alphabetical characters, (e.g., state names like "RUNNING", "STOPPING", class names, method names, file names, entity identifiers like urls or host names). Second, due to usually large volume of data, simple approaches based on pairwise comparison of all the analyzed log lines and application of a similarity threshold to obtain log line clusters allowing on inference about the possible templates structure are often inefficient, thus their practical usage is very limited.

The document <CIT> describes systems, methods, and computer-readable media that provide for context-sensitive, interactive logs to an administrative user console. A log server can receive at least one logging event from at least one application server based upon activity of at least one entity, identify at least one action associated with the logging event, and create and store a log entry based on the logging event and the associated action. The log server can further format an interactive display page for display at an administrative user console containing the log entry, wherein the interactive display page displays the logging event and the associated action in proximity to the logging event, and wherein the associated action can be selectable by a user at the administrative user console. In response to a selection of the associated action from the administrative user console, the associated action can be initiated.

The document <CIT> relates to creating user-to-software-application-instance-pairings. Each of the pairings is a unique relationship between one of the users and one of the instances of the software applications. Identifiers for the user-to-software-application-instance-pairings are received. There is a separate identifier for each of the user-to-software-application-instance-pairings. One of the log creation facilities is associated with each of the user-to-software-application-instance-pairings. Log files are created at corresponding ones of the log creation facilities in response to detecting errors during execution of the instances of the software applications. The log files are categorized based on error categories. A request for a post error analysis report is received. The request specifies one of the error categories. A subset of the log files is determined based on the specified error category specified in the request. The subset of the log files is displayed. One of the identifiers is displayed for each error described in the post error analysis report.

In the document <CIT>, a method, system, and computer program product for the creation and logging of a taskID is disclosed. A component initiates a task and requests a task identification (TaskID) from a log task manager. The taskID follows this task (which may flow across multiple components or ORBs) until completion. The TaskID is passed in the thread context in local methods and in the message context in remote method invocations. The taskID is then logged with message and trace data from each of the components through which the task flows that generate a trace or message log.

The document <CIT> relates to instrumenting software for enhanced diagnos-ability. In the document <CIT> testing of a software system using instrumentation at a logging module is described.

"The invention is set out in the appended set of claims.

A computer-implemented method for analyzing log files in a distributed computer system according to the independent claim <NUM> is provided. Further, a computer-implemented system for analyzing log files according to a further independent claim is provided. Embodiments are the subject matter of dependent claims in the appended set of claims.

The present disclosure is directed to a method of identifying and grouping log lines corresponding to the same event type indirectly, without the actual analysis of the log lines content. In one example, such an assignment is performed based on the call point, described as a pair consisting of fully qualified class name and line number of the actual logging framework method invocation, as in majority of real word cases a single source code line contains at most one call for logging data. The above-mentioned call point is obtained through bytecode instrumentation of a particular logging framework methods, so as to be able to infer the call point from the application call stack when an actual method responsible for logging data is invoked by application code. The proposed approach is also capable to distinguish log lines that originated from different locations in application source code, even if the created log lines contain identical messages.

As the present disclosure uses the mechanism of bytecode instrumentation, it is applicable to the applications running in environments where such a dynamic modification is supported such as Java Virtual Machine or. NET platform. The mentioned systems provide interfaces enabling the injection of agents into the process of bytecode interpretation done by the virtual machines, which allows on performing suitable instrumentation to record the above-mentioned call point. Using supported logging framework and installation of such a specialized agent are the main application-side requirements for the method to work. There is no need to make any changes in monitored application source code nor in its configuration.

The information on the call point for a particular log line is stored in separate metadata files on the monitored host, therefore the application log files remain unchanged. Restoring the relation between a particular log line and its call point, which also identifies the corresponding event type, can be done efficiently by reading jointly application log file and created helper files.

The drawings described herein are for illustrative purposes only of selected embodiments and not all possible implementations and are not intended to limit the scope of the present disclosure.

The bytecode-based software platforms like Java Virtual Machine or. NET framework provide interfaces to intercept the startup of virtual machines, to inject custom code into the virtual machines and to execute this code under control of the virtual machine. The presented disclosure uses this mechanism to alter the bytecode of logging framework methods. When instrumented methods are invoked, the altered bytecode (sensors) perform operations allowing on getting and analyzing current thread call stack to find the call point of the log framework method in the monitored application (i.e., the point in application code from which a logging framework method has been invoked) and storing the information on assignment of the particular log line to the call point for later analysis. While reference is made throughout this disclosure to the Java software platform, it is readily understood that the claimed techniques are applicable to other software platforms as well. One of the possible ways to identify the call point is by using the pair consisting of fully qualified class name and source code line number. In another variant which will be also discussed, we will additionally use a method signature and an index from compiled code in place of code line number. In general we will use the term call point descriptor for data that can be used to identify the call point (i.e. code location) in an application that performs logging activities.

Exemplary embodiment of a log analysis system for grouping related log lines is presented in <FIG>. User <NUM>, often called operator, accesses log data produced by application <NUM> running on a monitored host <NUM> via log viewer <NUM>, which provides diagnostic web interface. In order not to introduce additional performance overhead on monitored application <NUM>, log viewer <NUM> with related components is running on a separate monitoring host <NUM>. Application <NUM> is a process running on monitored host that supports code instrumentation, typically this can be a computer program running on some virtual machine such as Java Virtual Machine (JVM) or. NET platform. From now, if not stated explicitly, it is assumed that the monitored application is a Java process running on JVM although this disclosure is not limited thereto.

During application <NUM> startup, the log agent <NUM> as depicted in <FIG>, analyzes classes to be loaded by JVM using native loader <NUM> and performs instrumentation <NUM> of certain logging framework methods <NUM> by placing <NUM> two different types of sensors. Load-time instrumentation presented in <FIG> is one example of possible instrumentation types that can be used for placing sensors. Another possibility is to use run-time instrumentation, for example as discussed in U. Patent No. <NUM>,<NUM>,<NUM> entitled "Method and system for automated analysis of the performance of remote method invocations in multi-tier applications using bytecode instrumentation".

The first sensor type is a call point inferring sensor <NUM>, which is placed in methods <NUM> of a particular logging framework that are invoked by application code to log messages. Alternatively, the call point inferring sensor may be placed in one or more internal methods of a logging framework to which log methods that are directly invoked by the application delegate. Potential locations for call point inferring sensors include internal methods which are directly called by logging methods and internal methods that are called indirectly, via one or more intermediate internal methods. For example, the first sensor type may be instrumented in put(. ) method of ch. AsyncAppender-Base class of one of popular Java logging framework Logback, which may appear on call stack as a result of using org. info("Sample message") method in monitored application to log data. The sensor <NUM> infers the call point descriptor based on obtained call stack in current thread and stores the assignment between log entry and call point descriptor in memory. The second sensor type, the call point saving sensor <NUM>, is placed into the bytecode of one or more methods of the logging framework that are invoked during the writing of log entries to files <NUM>, e.g., in methods subAppend(. ), writeBytes(. OutputStreamAppender class of Logback framework. The idea behind splitting the functionality into two types of sensors comes from the fact that the final format of log line written to log file, which depends on the particular logging framework and its configuration, may not be determined in the methods that are invoked during the post of log entries, but rather in different logging framework methods executed right before actual writing operation. Therefore, the sequence of bytes defining the log line could not be easily accessible for call point inferring sensor <NUM>, but it should be for call point saving sensor <NUM>.

While a logging framework method that is responsible for writing an application state to log file is executed, but before the actual operation of writing the data to a file <NUM> (due to injection of sensors illustrated in <FIG>) additional activities are performed. First, call point inferring sensor <NUM> is activated to get and analyze current stack trace to find the call point descriptor. Next <NUM>, call point saving sensor <NUM> using suitable log agent code writes metadata <NUM> allowing an assignment <NUM> the call point descriptor <NUM> to the log line <NUM> that is about to be stored.

Various approaches can be used to persist the log line - call point descriptor assignment <NUM>. One of the simplest strategies is to create log file metadata <NUM>, where the log line entries <NUM> are composed of the whole log line <NUM> and a call point descriptor <NUM> as presented in <FIG>. However, such a strategy uses a lot of disk space to store full duplication of log data. Another approach, in which log data is not duplicated, involves including call point descriptors in application log file <NUM> itself, thereby modifying the original log line format <NUM>. In this case, the additional metadata files are not needed. However, such a modification may not be acceptable by application users, who, for instance, may have already configured various external or internal (being part of the application) tools for processing the log files expecting the originally configured log line format.

Another approach, which does not have any of the above-mentioned disadvantages is presented in <FIG>. Here, the log file metadata <NUM> is organized as two index files <NUM>, <NUM>. One of the index files, called the call point index <NUM>, stores call point entries <NUM> consisting of a call point identifier <NUM> and the call point descriptor <NUM>. The second index file, called log line mapping index <NUM>, contains log line mapping entries <NUM> defined as pairs of the following records: log line descriptor <NUM> and call point identifier <NUM>. Call point identifier <NUM> is a simple reference to call point index, whereas log line descriptor <NUM> contains information which enables matching of the entry with a particular log line <NUM>. The main purpose of decoupling call point storage from log line descriptor storage is reducing the disk space needed to save the information on the relation between a log line <NUM> and its call point descriptor <NUM>. Call point <NUM> and log line mapping <NUM> indexes can be implemented as simple structured text or binary files. Using only one index file with entries consisting of log line descriptor and call point descriptor can be an alternative, which is slightly simpler than two-index approach, but requires more disk space.

Next, the detailed description of tasks performed by call point saving sensor <NUM> is provided, assuming that two-index approach as presented in <FIG> is chosen.

First, call point saving sensor <NUM> using suitable log agent <NUM> code writes data about the call point descriptor <NUM> to call point index <NUM>. Only entries that currently do not exist in the call point index <NUM> are appended to it. Next, call point saving sensor <NUM> writes log line mapping entries <NUM> to log line mapping index <NUM>, one for each application log line <NUM>. Log line mapping entry <NUM> besides call point identifier <NUM> contains log line descriptor <NUM>, which should contain information allowing to match the entry with a particular log line <NUM>. Different strategies can be used to ensure the above-mentioned correspondence, which also determines the steps that have to be performed by log collector <NUM> to recreate the relation based on collected data, i.e.: log file <NUM>, call point index <NUM> and log line mapping index <NUM>. Some possible approaches are described below.

Note that regardless of the chosen approach, if the first log line mapping entry <NUM> in the index <NUM> is about to be written, it may be helpful to include with the entry any additional information on the position of the application log line <NUM> in the log file <NUM> to which the entry relates to.

When log viewer <NUM> receives a request <NUM> from a user <NUM> to present data from a log file for a specified period, it attempts to receive <NUM> that data from log repository <NUM>. If there is no suitable data in the repository, log viewer <NUM> sends request <NUM> directly to log collector <NUM>. Log collector <NUM> forwards the request <NUM> to suitable host agent <NUM>, which is responsible for gathering log file metadata <NUM> and raw log file <NUM> and sending them back to log collector <NUM>. Next, log collector <NUM> correlates and stores <NUM> received data in log repository <NUM>. Depending on the mode specified by the user, either raw log lines or grouped ones are shown. To display grouped log lines, log viewer <NUM> requests group definitions <NUM> from log data analyzer <NUM>. To fulfill the request, log data analyzer <NUM> fetches <NUM> necessary input data, i.e., log lines <NUM> and corresponding call point descriptors <NUM> from log repository <NUM>.

<FIG> depicts actions that are performed by placed sensors <NUM>, <NUM> and log agent <NUM> code when an instrumented method of a logging framework that includes a call point inferring sensor has been executed <NUM>. First, the JVM is requested for the call stack of the current thread <NUM>. Next, the call stack is traversed to find a frame (f) with an application method that called one of the logging framework methods designed to log data <NUM>. One of the possible approaches here is to enumerate the names of all the logging framework methods that are typically directly called by application code to log data, find one of such methods on the call stack and choose the previous stack frame (i.e., the one that was put on the stack earlier). Another alternative is to find the first frame (f) that does not come from the application logging framework itself, e.g., by checking class and package names and comparing them with respective names that are used in the particular logging framework. Once the frame (f) is found, the call point descriptor (cp) is computed <NUM>, which can be denoted, for example, as a pair consisting of fully qualified class name and source code line number.

Logging frameworks (e.g., Logback) typically support two types of strategies for writing data to log files:.

In order to be able to handle both the cases relevant mapping between the log event and its call point descriptor is stored in a map in memory (callPointMap) <NUM>. This map is used to exchange data between call point inferring sensor and call point saving sensor and is therefore accessible for both sensors. Once the log event is about to be written to a file <NUM>, the following operations are performed. The call point descriptor (cp) of the event is retrieved from the callPointMap <NUM>. Next, the call point index <NUM> is analyzed <NUM> to find respective identifier (cp_id) for the call point descriptor (cp) <NUM>. If there is no entry for (cp), then the call point descriptor is added to the index and its identifier (cp_id) is assigned <NUM>. Afterwards, log line descriptor (ld) is constructed <NUM>, as mentioned previously it may contain various information which impact the complexity and reliability of the log data parsing and analysis procedure. For example, the descriptor can consist of log line timestamp, hash signature computed using any hashing function such as MurmurHash3 of the log line <NUM> and log line size, which may be used in determining log line boundaries. Next, an entry consisting of log line descriptor (ld) and respective call point identifier (cp_id) is stored in log line mapping index <NUM> and the process ends with step <NUM>.

Splitting a log file into collections of log lines, which in general can span across multiples lines, as was discussed above, might not be a trivial task. <FIG> provides a flow chart of a process that can be realized by log collector <NUM> to extract log lines from a log file using information from metadata and store the relation between log line and call point descriptor in log repository <NUM>. Here it is important that the order of entries in log line mapping index is the same as the order in which log lines are written and log line descriptor contains information on log line size in bytes. After the raw log file and corresponding indexes are fetched <NUM>, each entry in log line mapping index is analyzed in a loop <NUM>. First, log line descriptor (ld) in a current entry from log line mapping index is analyzed <NUM> to obtain the log line size (ls) <NUM>. Next (Is) bytes from log file is read and the data is interpreted as a log line (l) <NUM>. Based on call point identifier (cp_id) included in log line descriptor (ld), corresponding call point descriptor (cp) for the log line (l) is retrieved from call point index <NUM> and the relation between log line and its call point descriptor is stored in log repository <NUM>. Once all the entries in log line mapping index are analyzed the process ends with step <NUM>. If metadata has been organized in such a way that there is no simple indicator on log line boundaries, log collector must do some additional processing, e.g., it can look for time and date fields which usually indicates a beginning of a new log line. Alternatively, additional information on the structure of the log line may be read by one of the sensors, which for example may contain the configured timestamp format, log field separators, field types and their position in the log line. Such information may be then used to simplify computation of log line boundaries. It also can be used to provide more advance filtering and processing capabilities in log viewer <NUM>. Information about a log line <NUM> which may optionally include any combination of the log line properties like timestamp, size, above-mentioned structure data or information on the position of the log line <NUM> in the log file <NUM> forms metadata of the log line. Such metadata can be optionally included in a log line descriptor <NUM>.

Referring now to <FIG>, which describes steps performed by log analyzer <NUM> to fulfill the request <NUM> for providing an assignment of log lines to groups. After the collections of lines to analyze is fetched <NUM>, each log line (l) is examined in the following loop <NUM>. First, log line is removed from input collection <NUM>. Next, call point descriptor (cp) of the log line (l) is retrieved from log repository <NUM>. The log line to call point descriptor assignment was created in log repository <NUM> by log collector <NUM>, see <FIG>, element <NUM>. If there exists a group (g) for the call point descriptor <NUM>, then the line (l) is assigned to that group <NUM>, otherwise a new group is created <NUM>, and next the assignment to that group is made <NUM>. The process ends with step <NUM>, if all the log lines are analyzed.

It is worth mentioning that an application can be compiled without information about line numbers. Although it is not very common practice, possible modifications of the disclosure will be discussed that may be beneficial in such situations. Such alternative approaches may use other identification data that is also available in compiled code, like an opcode index or a command index to report and identify the position of detected logging code invocations. For example, one of possible approaches applicable, e.g., to applications running under JVM, is to use bytecode index instead of source code line number and additionally a method signature. The bytecode index is defined as the index (integer number) in code array containing the execution point for given stack frame. The method signature contains information allowing on identification of the method and its code array in a particular class. Such a signature typically includes the method name and information about its arguments. The term method signature can also refer to class constructors and initializers. Referring now to <FIG>, which provide example Java code with invocations of logging framework methods, <FIG>, placed in lines <NUM> and <NUM>. In <FIG>, code arrays for the class as returned by javap (The Java Class File Disassembler) tool are presented. In particular the first logger. ) method invocation corresponds to the bytecode index of <NUM> in testMethod() code array and the second invocation corresponds to the bytecode index of <NUM> in the same code array. Therefore, the values <NUM> and <NUM> are used in place of source line numbers <NUM> and <NUM>, which are not available in runtime. Note that in the described invention it is sufficient to distinguish different logging calls in a method, initializer, or constructor and such a distinction is provided by bytecode index. One small limitation of the approach concerns logging code placed in instance initializer blocks. Since the blocks are copied to each constructor in a class, invocations of logging methods placed in the blocks will be reported in separate groups created for each of the constructors.

Since, assuming we do not use the index for compiled code discussed above, log line grouping performed by log analyzer when line numbers are not available can be based only on class names and method names (or method signatures), obtained groups may contain log entries coming from multiple templates. Another approach that can be taken in such a situation involves analyzing log lines content within each of such group to further split it to smaller clusters in which lines come from the same template. Various methods can be used to perform such a clustering. In particular, this can be done using any of known log parsing algorithms, e.g., <NPL>.

Alternatively, the parsing method described in <CIT> entitled "Method And System For Log Data Analytics Based On SuperMinHash Signatures" can also be used for such purpose. Since the methods responsible for analysis of log line contents are executed individually for each of group obtained from log analyzer, the overall accuracy of such hybrid approach should be superior (or at least the same) comparing to using any of the methods individually for analyzing the whole log file.

Once grouping has been accomplished a header for each individual group can be computed, which (ideally) should look similar the actual log event message template, e.g., "Getting configuration from device *, for user * finished in *". The header can be created, for example, by choosing tokens, which appears in all log messages in a particular group and by putting "*" in place of tokens that vary in the group. Such a header can be shown to the user in log viewer <NUM>. Additionally, the header can be used as a group identifier which is not dependent on possible class, method signature and line number (or bytecode index) changes in newer versions of the same application.

The techniques described herein may be implemented by one or more computer programs executed by one or more processors. The computer programs include processor-executable instructions that are stored on a non-transitory tangible computer readable medium. The computer programs may also include stored data. Non-limiting examples of the non-transitory tangible computer readable medium are nonvolatile memory, magnetic storage, and optical storage.

Certain aspects of the described techniques include process steps and instructions described herein in the form of an algorithm. It should be noted that the described process steps and instructions could be embodied in software, firmware or hardware, and when embodied in software, could be downloaded to reside on and be operated from different platforms used by real time network operating systems.

The present disclosure also relates to an apparatus for performing the operations herein. This apparatus may be specially constructed for the required purposes, or it may comprise a computer selectively activated or reconfigured by a computer program stored on a computer readable medium that can be accessed by the computer. Such a computer program may be stored in a tangible computer readable storage medium, such as, but is not limited to, any type of disk including floppy disks, optical disks, CD-ROMs, magnetic-optical disks, read-only memories (ROMs), random access memories (RAMs), EPROMs, EEPROMs, magnetic or optical cards, application specific integrated circuits (ASICs), or any type of media suitable for storing electronic instructions, and each coupled to a computer system bus. Furthermore, the computers referred to in the specification may include a single processor or may be architectures employing multiple processor designs for increased computing capability.

The algorithms and operations presented herein are not inherently related to any particular computer or other apparatus. Various systems may also be used with programs in accordance with the teachings herein, or it may prove convenient to construct more specialized apparatuses to perform the required method steps. The required structure for a variety of these systems will be apparent to those of skill in the art.

In addition, the present disclosure is not described with reference to any particular programming language. It is appreciated that a variety of programming languages may be used to implement the teachings of the present disclosure as described herein.

Claim 1:
A computer-implemented method for analyzing log files (<NUM>) in a distributed computer system, comprising:
- receiving, by a log analyzer (<NUM>), a plurality of log entries from a log repository (<NUM>), where each log entry describes an event which occurred during execution of an application (<NUM>);
- for each log entry in the plurality of log entries, capturing, by one or more sensors (<NUM>, <NUM>), a given call point descriptor (<NUM>, <NUM>, <NUM>, <NUM>) associated with a given log entry during execution of the application (<NUM>) on a host computing device (<NUM>), where the call point descriptor (<NUM>, <NUM>, <NUM>, <NUM>) identifies a location within the application (<NUM>) from which the given log entry originated and the one or more sensors (<NUM>, <NUM>) is instrumented into the application (<NUM>);
- storing call point descriptors (<NUM>, <NUM>, <NUM>, <NUM>) for each log entry in log file metadata (<NUM>, <NUM>, <NUM>), where the log file metadata (<NUM>, <NUM>, <NUM>) is separate and distinct from a log file (<NUM>) comprising the log entries;
- grouping, by the log analyzer (<NUM>), log entries according to the captured call point descriptors (<NUM>, <NUM>, <NUM>, <NUM>); and
- reporting, by the log analyzer (<NUM>), grouped log entries to a system user (<NUM>), where the log analyzer (<NUM>) is implemented by computer executable instructions executed by a computer processor of a monitoring computer (<NUM>).