Page tree
Skip to end of metadata
Go to start of metadata

Overview

FIXEdge can trigger alerts notifications about FIX Session and FIXEdge Transport Adaptors (TA) state changes.

The alerts can be handled on a Business Logic Layer and processed by Business rules and BL Scripting with JavaScript.

The events can be forwarded to the SMTP Transport Adaptor that is intended to convert information from FIX messages to Emails and send them via the SMTP Service.

Notification messages use a custom format representing the Email (C) message

The SMTP TA is configured in the FIXEdge.properties file. The full list of the configuration parameters is here: Configuration.

SMTP Transport Adapter configuration with Gmail SMTP Server

For engaging Gmail SMTP server, one should enable less secure apps & your Google Account in Gmail SMTP settings.

FIXEdge.properties
#------------------------------------------------------------
# Transport Layer Section
#------------------------------------------------------------
 
#Comma separated list of identifiers of Transport Adapters should be loaded.
TransportLayer.TransportAdapters = TransportLayer.SmtpTA
 
#------------------------------------------------------------
# SMTP Adaptor configuration
#------------------------------------------------------------
 
TransportLayer.SmtpTA.Description = SMTP Transport Adaptor
TransportLayer.SmtpTA.DllName  = bin/SMTPAdaptorDll.dll
TransportLayer.SmtpTA.Type = DLL
TransportLayer.SmtpTA.SMTPSessions = SMTPClient
 
# Google SMTP Configuration
TransportLayer.SmtpTA.SMTPSession.SMTPClient.ServerName = smtp.gmail.com
TransportLayer.SmtpTA.SMTPSession.SMTPClient.SecureConnection = SSL
TransportLayer.SmtpTA.SMTPSession.SMTPClient.ServerPort = 465
TransportLayer.SmtpTA.SMTPSession.SMTPClient.Login = sender@gmail.com
TransportLayer.SmtpTA.SMTPSession.SMTPClient.Password = password
TransportLayer.SmtpTA.SMTPSession.SMTPClient.From = sender@gmail.com
TransportLayer.SmtpTA.SMTPSession.SMTPClient.To = receiver@epam.com;
 
TransportLayer.SmtpTA.SMTPSession.SMTPClient.SmartEmailProcessing = true

Format of email 35=C message

Once the state of the session or Adapter is changed, FIXEdge creates an Email (C) message that can be processed with Business Logic configured in BL_Config.xml

The event is logged with the TRACE level:

FixEdge.log
2015-03-26 15:18:12,413 UTC   TRACE   [BL_Layer]  140009470453504  Process incoming message. [8=FIX.4.4 9=189 35=C 49=fake 56=fake 34=1 52=99990909-17:17:17 164=7 94=0 42=20150326-15:17:09 147=[NOTE] FIXEDGE:ICEProxy Established 33=5 58=N 58=1 58=FIXEDGE:ICEProxy 58=Established 58=AttemptToConnect 10=238 ]

The SMTP TA can transform this message to Email.

Mapping for FIXEdge.parameters to Email content:

Email attribute

Comments

FromUsing the value of TransportLayer.SmtpTA.SMTPSession.<Session>.From  property from FIXEdge.properties
ToUsing the value of TransportLayer.SmtpTA.SMTPSession.<Session>.To  property from FIXEdge.properties
CCUsing the value of TransportLayer.SmtpTA.SMTPSession.<Session>.CC property from FIXEdge.properties
BCCUsing the value of TransportLayer.SmtpTA.SMTPSession.<Session>.BCC  property from FIXEdge.properties

SmartEmailProcessing is disabled

The default option.

FIXEdge.properties
TransportLayer.SmtpTA.SMTPSession.SMTPClient.SmartEmailProcessing = false

The SMTP Adapter can process any message on BL and convert it to the Email with the following format:

Item

Email Content

Placeholder explanation

SubjectMessage '<MsgType>' from 'fake' to 'fake'.

MsgType - is a type of message handled on Business Logic Layer
Message Body<RAW FIX MessageRAW FIX Message - Contains the original RAW FIX message with SOH delimiters

SmartEmailProcessing_false.msg

SmartEmailProcessing is enabled

The Email is created based on the content of the Email (C) message

The subject is taken from  (147) Subject and a body is composed of (58) Text tag values entries of the repeating group with a size defined in (33) LinesOfText.

FIXEdge.properties
TransportLayer.SmtpTA.SMTPSession.SMTPClient.SmartEmailProcessing = true

Converts messages 35=C to an Email with the following format:

Item

Email Content

Placeholder explanation

Subject

[<Severity>] <SenderCompId>:<TargetCompId><Connection status>


The subject is taken from  (147) Subject of  Email (C) message 

Severitynotification severity type.
Possible values are: NOTE, WARN, ERROR

  • SenderCompId- value of tag (49) SenderCompID 
  • TargetCompId - value of tag (56) TargetCompID 
  • Connection status- new state of the session.
    Possible values are: AttemptToConnect, Established, Terminated correctly, Non-gracefully terminated
Message Body

<Severity>
<Event Code>
<Session Id>
<Connection status>


Original FIX message:
<RAW FIX Message>

The message content is composed with (58) Text tag values entries of the repeating group with a size defined in (33) LinesOfText as part of the Email (C) message  

  • Severity - notification severity type. Entry #0 of the LineOfText group.
    Possible values are: N, W, E
  • Event Code - internal event code. Entry #1 of the LineOfText group.
  • Session Id - the pair of (49) SenderCompID  and (56) TargetCompID with ':' delimiter. Entry #2 of the LineOfText group.
  • Connection status - new state of the session. Entry #3 of the LineOfText group.
    Possible values are: AttemptToConnect, Established, Terminated correctly, Non-gracefully terminated
  • RAW FIX Message - Contains the original RAW FIX message with SOH delimiters

SmartEmailProcessing_true.msg

Simple Email notification Business Logic example

A user can filter session state alerts by checking the value of (147) Subject tag of Email (C) message from a fake:fake session and send the messages to SMTP Adapter.

BL_Config.xml
<!-- Send email on every session status change. Ignore Temp sessions.-->
<Rule Description="Send emails with session state change notifications" >
    <Source>
        <!--Apply to each internal message -->
        <FixSession SenderCompID="fake" TargetCompID="fake" />
    </Source>
    <Condition>
        <!--Apply to  35=C only -->
        <MsgType>
            <Val>C</Val>
        </MsgType>
        <!-- Apply to messages with 147 tag filled with session status  -->
        <MatchField Field="147" Value=".*(AttemptToConnect|Established|Terminated correctly|Non-gracefully terminated)" />
    </Condition>
    <Action>
        <!-- Forward the message to SmtpClient  -->
        <Send>
            <Client Name="SMTPClient"/>
        </Send>
    </Action>
</Rule> 

MatchField condition accepts the list of possible session states here, i.e.: AttemptToConnect, Established, Terminated correctly, Non-gracefully terminated

Example of the Email notification with customized Email content

A user can filter session state alerts by checking the value of (147) Subject tag of Email (C) message from a fake:fake session and change the message content with JavaScript before sending to SMTP Adapter.

The business logic is the following:

BL_Config.xml
<!-- Send email on every session status change. Ignore Temp sessions.-->
<Rule Description="Send emails with session state change notifications">
    <Source>
        <!--Apply to each internal message -->
        <FixSession SenderCompID=".*" TargetCompID=".*" />
    </Source>
    <Condition>
        <Script Language="JavaScript" FileName="../FIXEdge1/conf/isStateNotification.js"/>
    </Condition>
    <Action>
        <Script Language="JavaScript" FileName="../FIXEdge1/conf/prepareEmail.js"/>
        <Send>
            <Client Name="SMTPClient"/>
        </Send>
    </Action>
</Rule>

In order to use a custom implementation of emails, the SMTP Transport Adaptor must have DefaultSmartEmailProcessing or SmartEmailProcessing enabled.

FIXEdge.properties
TransportLayer.SmtpTA.SMTPSession.SMTPClient.SmartEmailProcessing = true
 
# Ot for multiple SMTP sessions configuration
TransportLayer.SmtpTA.SMTPSessions.DefaultSmartEmailProcessing=true

If this property is not defined, the SMTP Transport Adaptor uses the default one, which is false.

For example, outgoing Emails should have the following changes.

  • The subject text adjusted and got remapped priority of the event and one of 3 statuses: Online, Stopped as expected, Down
  • Session id contains a Session Qualifier
  • Date and time of the event
  • Highlighted previous and current statuses
  • Contact information
  • Original event message before modifications.
  • Ignore redundant email notifications. 

This can be achieved by modifying (147) Subject and (58) Text tag values entries of the repeating group with a size defined in (33) LinesOfText, the following mapping would be used

Item

Email Content

Placeholder explanation

Subject

[<Severity>] Session Notice <Session Id>. <Connection status>

examples:

  • [LOW] Session Notice INITIATOR:FIXEDGE. Online
  • [MEDIUM] Session Notice INITIATOR:FIXEDGE:User2. Down


The subject is taken from  (147) Subject of  Email (C) message 

  • Severity- notification severity type. 
    Possible values are: LOW, MEDIUM, HIGH
  • Session Id - the combination of (49) SenderCompID(56) TargetCompID and Session Qualifier with ':' delimiter.
  • Connection status - new state of the session. 
    Possible values are: Online, Stopped as expected, Down
  • RAW FIX Message - Contains the original RAW FIX message with SOH delimiters
Message Body

PRIORITY: <Severity>, <Severity level>

DATE and TIME: <Datetime in UTC format>

CONNECTION NAME: <Connection Name>

CURRENT CONNECTION STATUS:  <Current Status>

PREVIOUS CONNECTION STATUS: <Previous Status>

FIXEDGE NOTIFICATION EVENT MESSAGE: <Original FIXEdge Notification message>


<Message Contact Details>


Original FIX message:

<Raw FIX Message>

  • Severity- notification severity type. 
    Possible values are: LOW, MEDIUM, HIGH
  • Severity level- the numeric value of the severity level and impact according to ITSM recommendations 
    Possible values are: 3, 2, 1
  • Datetime in UTC format - a value of DateTime in UTC of the event if format YYYYMMDD-hh:mm:ss

  • Connection Name - value of session's id value of tag 56 TargetCompID, ":" and tag 49 SenderCompId

  • Current Status - The current (new) status of the session. 

  • Previous Status - The previous status of the session.  

  • Original FIXEdge Notification message - the original internal FIXEdge event message with pipe '|' symbol as delimiter

  • Message Contact Details - Contact information of EPAM B2BITS support team.

  • Raw FIX Message - The resulted modified Email (C) message sent to the SMTP adapter. It's appended at the end automatically

JavaScript isStateNotification.js for filtering messages:

isStateNotification.js
// The script check if it is an important session state notification that should be routed to SMTP TA.
result = false; // by default the message should be ignored.
 
function isImportantEvent(current, prev){
    if (prev == 'Established' && current == 'Non-gracefully terminated')
        // Switching state from established to Non-gracefully terminated is redundant
        // Non-gracefully terminated -> AttemptToConnect state change will be used as identification of session disconnection
        return false;                          
    else
        return true;
}
 
//The message type should be Email (35=C).
if (getStringField(35) == "C")
    {
    // Get default subject from tag 147.
    status = getStringField(147);
     
    // Regex for session events only: [STATUS] SenderCompId:TargetCompId NEW_STATE
    var regexp = /.*\s+(\S+):(\S+)\s+(.*)/g;
    match = regexp.exec(status);
     
    if (match != null) {
        //target = match[1];
        //sender = match[2];
        // Email content is located in the group 33
        hndl = getGroup(33);
        numberOfLines = getNumField(33); // Get number of entries in the group from LinesOfText(33) field
     
        if (isGroupValid(hndl) && numberOfLines >= 4 && numberOfLines <= 5) { // Session state events have 4 and 5 entries.
            currentStatus = getStringField(hndl, 3, 58);
            if (numberOfLines == 5) { // Events with previous state has 5 lines
                previousStatus = getStringField(hndl, 4, 58);
                result = isImportantEvent(currentStatus, previousStatus);
            } else {
                result = true; // all messages with initial state are important.
            }
        } // end if hdnl
    } // end if match
}
result;

The JavaScript describing the mapping prepareEmail.js above:

prepareEmail.js
// The script customizes the session state notification emails.
// https://btobits.com/fixopaedia/fixdic44/index.html?message_Email_C.html
// Email custom format
  
// Functions for severity
function getSeverityText(code) {
  // Convert letter from severity to human readable text
  switch (code) {
    case "N": return "LOW";
    case "W": return "MEDIUM";
    case "E": return "HIGH";
    default: return "UNKNOWN";
  }// end switch
}
  
function getSeverityNumber(code) {
  // Convert letter from severity to severity code
  switch (code) {
    case "N": return "3"; //A minor incident with low impact
    case "W": return "2"; // A major incident with significant impact
    case "E": return "1"; //A critical incident with very high impact
    default: return "UNKNOWN";
  }// end switch
}
  
// convert FIXEdge status to a new format: Online, Online, Stopped as expected, Down
function getStatusForSubject(currentStatus) {
  // Convert letter from severity to severity code
  switch (currentStatus) {
    case "AttemptToConnect":
    case "Non-gracefully terminated":  
        return "Down";
    case "Established":
        return "Online";
    case "Terminated correctly":
        return "Stopped as expected";
    default: return currentStatus;
  }// end switch
}
  
// Fix original message serialization
var original_message = serializeMessage("|");
 
// Get default subject from tag 147
status = getStringField(147);
  
// Regex for session events only: [STATUS] SenderCompId:TargetCompId NEW_STATE
var regexp = /.*\s+(\S+):(\S+)\s+(.*)/g;
match = regexp.exec(status);
  
if (match != null) {
  target = match[1];
  sender = match[2];
  qualifier = getStringField(50);
  sessionId = target + ":" + sender;
   
  if (qualifier != null) // update session id if the session has qualifier.
     sessionId = sessionId + ":" + qualifier;
  
  // Email content is located in the group 33
  hndl = getGroup(33);
  numberOfLines = getNumField(33); // Get number of entries in the group from LinesOfText(33) field
  
  if (isGroupValid(hndl) && numberOfLines >= 4 && numberOfLines <= 5) { // Session state events have 4 and 5 entries.
    // convert severity to human readable text and the numeric value
    // according to ITSM recommendations about severity levels and impact
    severity = getStringField(hndl, 0, 58);
    priority = "PRIORITY: \t\t\t\t" + getSeverityText(severity) + ", " + getSeverityNumber(severity);
     
    dateTimeUtc = "DATE and TIME: \t\t\t" + getCurrentDateStr(DATETIMEUtc); // A new line with timestamp of the event.
    connectionName = "CONNECTION NAME: \t\t\t" + sessionId; // sender:target:qualifier
    currentStatus = getStringField(hndl, 3, 58);
    currentStatusLine = "CURRENT CONNECTION STATUS: \t" + currentStatus;
    if (numberOfLines == 5) {
      previousConnectionStatus = "PREVIOUS CONNECTION STATUS: \t" + getStringField(hndl, 4, 58);
    } else {
      previousConnectionStatus = "PREVIOUS CONNECTION STATUS: \t" + "Initial"; // unknown previous status is Initial.
    }
     
    fixEdgeNotificationMsg = "FIXEDGE NOTIFICATION EVENT MESSAGE: " + original_message;
    contactDetails = "\n\nIf you need assistance on this notice please contact the FIXEdge Support Team emailing SupportFIXAntenna@epam.com or please call tel:+44-20-369-58-166";
  
    // Subject generation
    subject = "[" + getSeverityText(severity) + "] Session Notice " + sessionId + ". " + getStatusForSubject(currentStatus);
    setStringField(147, subject);
  
    // Set number of total lines starting from 1
    setNumField(33, 7);
  
    // Setting the values of text based on the n number of lines from group handle 33 in repeating group tag 58 staring from 0
    setStringField(hndl, 0, 58, priority);
    setStringField(hndl, 1, 58, dateTimeUtc);
    setStringField(hndl, 2, 58, connectionName);
    setStringField(hndl, 3, 58, currentStatusLine);
    setStringField(hndl, 4, 58, previousConnectionStatus);
    setStringField(hndl, 5, 58, fixEdgeNotificationMsg);
    setStringField(hndl, 6, 58, contactDetails);
 
  } // end if hdnl
} // end if match
 
//print("Updated Message: "+ serializeMessage("|"));

Email examples

Custom Notification. Session is Down.msg

Custom Notification. Session is Online.msg

Statuses description

  • Established - The FIX session is online and is sending heartbeats.
  • AttemptToConnect - The FIX session is down.
    In the case of the initiator session: the session is about to try to connect.
    In the case of the acceptor session: the session is listening to connections.
  • Non-gracefully terminated - The session is dropped unexpectedly.
    The possible reasons can be disconnections not as per the configured schedules. For example: IntradayLogoutTolerance = false, RecreateOnLogout = true, TerminateOnLogout = true.
  • Terminated correctly - The session is dropped and it is expected.
    For example, FIXEdge is configured to terminate session after receiving logout:  IntradayLogoutTolerance = false, RecreateOnLogout = false, TerminateOnLogout = true.
    Or the session is stopped by the schedule.
  • Reconnecting The initiator is trying to connect to the counterparty after the disconnection.

Status changes

State changes

Event description

(147) Email Subject

NULL → Established 

Transport adapter with name <AdaptorName> has been initialized.[NOTE] <AdaptorName> Established

NULL → AttemptToConnect

Initial → AttemptToConnect

The FIX Session <(49) SenderCompID>:<(56) TargetCompID has been initialized and is ready to perform the following scheduled actions:

  • accept a connection in case of acceptor
  • connect to the target destination in case of the initiator

The action is expected → so severity is INFO.

If events don't have the previous state they would have the NULL state instead of the Initial state.

[NOTE] <(49) SenderCompID>:<(56) TargetCompID AttemptToConnect
AttemptToConnect → Established

The FIX Session <(49) SenderCompID>:<(56) TargetCompID has been established.

The action is expected → so severity is INFO.

[NOTE] <(49) SenderCompID>:<(56) TargetCompIDEstablished
Established → Non-gracefully terminated

The FIX Session <(49) SenderCompID>:<(56) TargetCompID has been disconnected.

Possible reasons:

  • received a Logout (5) message
  • the counterparty closed the socket
  • network disorder

The disconnection is not expected at this time according to the configuration  →  so the severity is WARN.

[WARN] <(49) SenderCompID>:<(56) TargetCompID Non-gracefully terminated

Non-gracefully terminated → AttemptToConnect

The FIX Session <(49) SenderCompID>:<(56) TargetCompID has been recovered and is ready to perform the following scheduled actions:

  • accept a connection in case of acceptor
  • connect to the target destination in case of the initiator

The action is expected → so severity is INFO.

[NOTE] <(49) SenderCompID>:<(56) TargetCompID AttemptToConnect
Established → Terminated correctly

The FIX Session <(49) SenderCompID>:<(56) TargetCompID has been disconnected as expected after receiving a Logout (5) message.

The disconnection is expected at this time according to the configuration →  so the severity is NOTE.

[NOTE] <(49) SenderCompID>:<(56) TargetCompIDTerminated correctly

Terminated correctly → AttemptToConnect

The FIX Session <(49) SenderCompID>:<(56) TargetCompID has been forced to recreate and is ready to perform the following scheduled actions:

  • accept a connection in case of acceptor
  • connect to the target destination in case of the initiator

The disconnection is not expected at this time according to the configuration →  so the severity is WARN.

[WARN] <(49) SenderCompID>:<(56) TargetCompIDAttemptToConnect

Sending Emails on the certain Logout message content

Sometimes the counterparty sends Logout (5) FIX message instead of confirming Logon (A). FIXEdge can handle this situation and send a notification email about this.

This may be useful when Logout contains the reason (for example the credentials have been expired).

The example below generates an email if the Logout contains a certain value of the SessionStatus (1409) tag.

Handling Logout with DestroySessionEvent routing with JavaScript

FIXEdge raises DestroySessionEvent when it receives  FIX message (35=5, logout) when the session is being closed by the counterparty.

If logout contains SessionStatus (1409) then the FIXEdge can check it and call DestroySessionAction with a Script for example to route the message to the SMTP Transport Adapter where it will be converted to the email.

The below configuration notifies about 1409=5 (Invalid username or password) and 1409=6 (Account locked) Logout reasons from all of the sessions

BL_Config.xml
<?xml version="1.0" encoding="UTF-8"?>
<FIXEdge>
    <BusinessLayer>
        <DestroySessionEvent Description="Sending email in case of getting Logout with tag 1409">
            <Source>
                <FixSession SenderCompID=".*" TargetCompID=".*" />
            </Source>
            <Condition>
                <EqualField Field="1409">
                    <Val>5</Val>
                    <Val>6</Val>
                </EqualField>
            </Condition>
            <DestroySessionAction>
                <Script Language="JavaScript" FileName="../FIXEdge1/conf/sendSMTP.js" />
            </DestroySessionAction>
        </DestroySessionEvent>
        <DefaultRule>
            <Action>
                <DoNothing/>
            </Action>
        </DefaultRule>
    </BusinessLayer>
</FIXEdge>

JavaScript sendSMTP.js just sends FIX message (Logout) to SMTP TA

sendSMTP.js
send("SMTPClient");
  • Email examples: 
    Invalid_username _or_password.msg
  • FIX message example:

    8=FIX.4.4|9=108|35=5|49=EXCHANGE|56=FIXEDGE|34=1|57=T0052FIX1|52=20200818-19:12:22.049|1409=5|58=Invalid username or password|10=128|

Troubleshooting

Running Send action outside of the Javascript from DestroySessionAction is not supported

<DestroySessionEvent> can't route message with the Send instruction outside of the javascript

The examples below lead to the errors.

  1. Sending to the FIX session:

    <DestroySessionAction>
    	<Send>
    		<Client Name="SMTPClient"/>
    	</Send>
    </DestroySessionAction>

    Resulted with error: Incorrect event found: found unknown action 'Send'

  2. Sending to Transport Adapter:

    <DestroySessionAction>
    	<Client Name="SMTPClient"/>
    </DestroySessionAction>

    Resulted with error: Unable to parse business rules: Invalid BL rule: section <Action> has unexpected element <Client>

Solution:

Call the Send function from the javaScript

<DestroySessionAction>
	<Script Language="JavaScript" FileName="../FIXEdge1/conf/sendSMTP.js"/>
</DestroySessionAction>

sendSMTP.js:

sendSMTP.js
send("SMTPClient");

Other notifications

Apart from the  Email (C) message about session state change, FIXEdge also can generate other internal notifications:

  • Logon
  • Logout
  • Sequence Gap
  • Session Reject
  • Session state change
  • Business/Overload protection events
  • Fatal error

These events have a custom message type 35=UFL defined in fixdic40.xml.

The support for internal 35=UFL messages is mandatory, hence the fixidc40.xml dictionary is mandatory for correct FIXEdge functioning.

Related pages