Incident Reporting

Overview

The collector API allows you to place data into the collector data stream to be uploaded to AppFirst for viewing as Incident Reports. You can create alerts on this data, view the list of uploaded strings, etc. This Incident Reporting API works by placing items in a system message queue called /afcollectorapi which the collector reads from. You can give the incident reports a severity level, of Info, Warning, or Critical.

Incident reports are similar to logs, with the exception that they are not written to files. The strings are written directly in the collector data stream. This creates less overhead and allows for efficient information exchange. It is important to note that incident reporting is not intended to replace logs. Rather these reports are intended to convey information about specific software situations. Incident reports become a tool to communicate specific software situations in an operational context.

Each incident report includes a message string and severity level. There are 3 levels of severity: Information, Warning and Critical. Counters for each type of incident report are managed by AppFirst backend processing. The total number of incidents reported and the number of critical incidents are graphed by the Correlate application. For example, if 24 information reports and 2 critical reports were included in a given minute, Correlate would graph 26 total incidents and 2 critical incidents.

The collector API is delivered in source. You are free to use the code as is or make changes as necessary.

The API is delivered in various forms:

  • On Linux for C/C++ including a Makefile that creates a shared lib
  • On Linux & Windows for Python which consists of a log handler
  • On Linux for Java which takes the form of a log handler
  • On WIndows for C/C++ including a VS project file to create a DLL
  • On WIndows for .Net as a log handler

The source code can be downloaded from github.com/appfirst.

Note that there is a limit of 200 messages per collector upload period. The upload period defaults to 20 secs. Each incident report can be 1024 characters max and on Windows it is required to use wide characters.

We’ve already made APIs to do most of this work for you in C and Python. You can download them below.

The C APIs are just a library you can call to log incident reports to the collector. For Python, we created a logging handler that works seamlessly with the python logging module. So, if you already use the python logging module, it’s only a few lines of code to get all your log messages into our data stream as incident reports.

Python

Description

The Python API works through a Python logging handler. The AFCollectorAPI implements a standard Python logging handler class and places the incident report output in the collector data stream.

The incident reporting API supports 3 severity levels. The 5 Python logging severity levels are mapped as follows:

  • Python debug – AFCollectorAPI Info
  • Python info – AFCollectorAPI Info
  • Python warning – AFCollectorAPI Warning
  • Python critical – AFCollectorAPI Critical
  • Python error – AFCollectorAPI Critical

Example Usage

You need to have the collector running for this to work. If you do, a few minutes after running this example, you should be able to go to Browse for this process and click “Select Resources,” click Critical Incident Reports, and you can see them on the graph.

import logging
from AFCollectorAPI import CollectorAPIHandle
capi = CollectorAPIHandler()
formatter = logging.Formatter("%(name)s - %(levelname)s - %(message)s")
capi.setFormatter(formatter)
logger = logging.getLogger("test")
logger.setLevel(logging.DEBUG)
logger.addHandler(capi)

# logging examples
logger.debug("This is a debug msg it is mapped to info")
logger.info("This is an info msg it is mapped to info")
logger.warning("This is a warning msg it is mapped to warning")
logger.critical("This is a critical msg it is mapped to critical")
logger.error("This is an error msg it is mapped to critical")

C (Windows and Linux)

Windows

af_msg_init

Initializes the AppFirst Client API for incident reporting. It initializes internal data structures and establises a connection to the AppFirst collector. This is necessary before calling af_write msg.

Syntax

  • int af_msg_init();

Parameters

  • None

Return

  • 1 if initialization was successful. Otherwise, it returns 0.
af_msg_exit

Disconnects the application from the AppFirst collector and cleans up any internal data.

Syntax

  • int af_msg_exit();

Parameters

  • None

Return

  • None
af_msg_write

Writes an incident report message to the AppFirst collector. This function is designed for use with af_init_msg and af_exit_msg as such, the same connection established at the time of af_init_msg would be used when af_write_msg is called.

Syntax

  • int af_msg_write(__in severity, __in wchar_t *msg, __in DWORD msg_len);

Parameters

  • int severity (Severity level)
Value Meaning
af_severity_info
0×00000001
Informational message
af_severity_warn
0×00000002
Warning conditions
af_severity_crit
0×00000003
Critical conditions. This message is treated separately in Browse.
  • wchar_t *msg (Actual message that describes the condition)
  • DWORD msg_len (Message length in wide characters. The maximum length it can send each time is 1024.)

Return

  • If the function suceeds, it returns the number of characters actually written. If the function fails, it returns zero.
af_msg_send

Sends an incident report message to the AppFirst collector. This function is used independently from other msg functions. It does not require any initialization or cleanup calls. It creates the connection, sends the message, and cleans up the connection. Thus, this function incurs more overhead than af_write_msg but it does not need any setup. It has the same syntax, parameters and return value as af_msf_write.

Linux

postAFCollectorMessage

Posts a message to AppFirst collector agent.

Syntax

  • AFCollectorReturnCode postAFCollectorMessage(__in AFCollectorMsg *msg);

Parameters

  • AFCollectorMsg *msg (Client message struct. The msg parameter specifies severity level and actual message to be sent.). The severity values that AppFirst currently supports are:
Value Meaning
AFCSeverityInformation Informational message.
AFCSeverityWarning Warning conditions.
AFCSeverityCritical Critical conditions. This message is presented separately in Correlate.
  • AFCollectorMSG is defined in “AFCollectorAPI.h” as follows:
typedef struct AFCollectorMsg_t {
    AFCollectorMsgSeverity severity;
    int msg_len;
    char *data;
} AFCollectorMsg;

Return

  • 0 on success; otherwise, it returns one of the errors listed in “Errors” section.

Errors

  • AFCNoMemory – memory request to build the internal message failed.
  • AFCBadParaminput – parameter is invalid.
  • AFCOpenError – connecting to AppFirst failed.
  • AFCPostError – transmitting the user data to AppFirst collector failed.
  • AFCWouldBlock – transmitting the user data to AppFirst collector failed due to the max limit of number of messages.

Java

The collector API uses POSIX message queues (% man 7 mq_overview) as a message passing IPC to pass a message from your Java app to the AppFirst collector. Message queues are used as a common IPC so that various client bindings can be supported, in addition to Java.

Because POSIX message queues are used, the Java client code needs to access native OS functions. We use JNA (http://jna.java.net/) for this. The jna.jar file is used along with AfCollector.class.

There are two distinct approaches to creating incident reports in the Java client. One is a distinct method, the other is a log handler. The developer can either make calls to the distinct method or use the Java log interface. Both approaches create the same result of placing incident report strings in the collector data stream.

With the log handler, all that is required is to instantiate a handler and logging performed with standard Java log I/Fs will cause formatted log strings to be place in the collector data stream.

Build:

% ant

This builds the classes and jars as needed

% ant -buildfile ./build_jar.xml

This creates the AfCollector.jar combining classes from jna.jar & AfCollector.class.

Run a test:

% java -jar bin/AfCollector.jar 2

This creates 2 sample log messages that are placed in the collector data stream.

The main method in the file src/AfCollectorLogHandler.java provides an example for using the log handler.

Java Distinct Method

public enum AFCollectorReturnCode{

AFCSuccess,
AFCNoMemory,
AFCBadParam,
AFCOpenError,
AFCPostError,
AFCWouldBlock,
AFCCloseError;

public enum AFCollectorMsgSeverity{

AFCSeverityInformation,
AFCSeverityWarning,
AFCSeverityCritical;
AFCollectorReturnCode rc;
rc = AfCollector.postAFCollectorMessage(AFCollectorMsgSeverity.AFCSeverityCritical,test_data);

Java Log Handler Example

public static void main(String[] args) {
logger.addHandler(new Handler() {

public void publish(LogRecord logRecord) {
transPost(logRecord.getLevel(), 
   logRecord.getSourceClassName() + ":" + 


   logRecord.getSourceMethodName() + ":" + "<" +    
   logRecord.getMessage() + ">");
}

      public void flush() {
      }

      public void close() {
      }
    });

   logger.warning("Logging Warning");
   logger.info("Logging Info");
 }
}