Table of Contents |
---|
Overview
FIXEdge can trigger alerts alert notifications about FIX Session and FIXEdge Transport AdaptorsAdaptor (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 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 the Gmail SMTP server, one should enable less secure apps & your Google Account in Gmail SMTP settings.
Code Block | ||||
---|---|---|---|---|
| ||||
#------------------------------------------------------------ # 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 adapter is changed, FIXEdge creates an Email (C) message that can be processed with Business Logic configured and configured in BL_Config.xml.
The event is logged with the TRACE level:
Code Block | ||
---|---|---|
| ||
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 Emailinto an email.
Mapping for FIXEdge.parameters to Email email content:
Email attribute | Comments |
---|---|
From | Using the value of TransportLayer.SmtpTA.SMTPSession.<Session>.From property from FIXEdge.properties |
To | Using the value of TransportLayer.SmtpTA.SMTPSession.<Session>.To property from FIXEdge.properties |
CC | Using the value of TransportLayer.SmtpTA.SMTPSession.<Session>.CC property from FIXEdge.properties |
BCC | Using the value of TransportLayer.SmtpTA.SMTPSession.<Session>.BCC property from FIXEdge.properties |
SmartEmailProcessing is disabled
The This is the default option.:
Code Block | ||
---|---|---|
| ||
TransportLayer.SmtpTA.SMTPSession.SMTPClient.SmartEmailProcessing = false |
The SMTP Adapter can process any message on the BL and convert it to the Email an email with the following format:
Item | Email Content | Placeholder explanation |
---|---|---|
Subject | Message '<MsgType >' from 'fake' to 'fake'. | MsgType - is a type of message handled on the Business Logic Layer |
Message Body | <RAW FIX Message > | RAW FIX Message - Contains the original RAW FIX message with SOH delimiters |
...
SmartEmailProcessing is enabled
The Email email is created based on the content of the Email (C) message.
The subject is taken from from (147) Subject and a the body is composed of (58) Text tag values value entries of the repeating group, with a size defined in (33) LinesOfText.
Code Block | ||
---|---|---|
| ||
TransportLayer.SmtpTA.SMTPSession.SMTPClient.SmartEmailProcessing = true |
Converts messages 35=C to an Email email with the following format:
Item | Email Content | Placeholder explanation |
---|---|---|
Subject | [< | The subject is taken from from (147) Subject of of an Email (C) message
|
Message Body | < Original FIX message: | The message Message content is composed with (58) Text tag values value entries of the repeating group, with a size defined in (33) LinesOfText as part of the Email (C) message
|
Simple
...
email notification - Business Logic example
A user can filter session state alerts by checking the value of of the (147) Subject tag of of an Email (C) message from a fake:fake
session and send the messages to the SMTP Adapter.
Code Block | ||||
---|---|---|---|---|
| ||||
<!-- 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> |
The MatchField condition accepts the list of possible session states here, i.e.: AttemptToConnect
, Established
, Terminated correctly
, Non-gracefully terminated
Example of
...
an email notification with customized
...
email content
A user can filter session state alerts by checking the value of of the (147) Subject tag of of an Email (C) message from a fake:fake
session and change the message content with JavaScript before sending to the SMTP Adapter.
The business logic is the following:
Code Block | ||||
---|---|---|---|---|
| ||||
<!-- 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 the custom implementation of emails, the SMTP Transport Adaptor must have DefaultSmartEmailProcessing or SmartEmailProcessing enabled.
Code Block | ||||
---|---|---|---|---|
| ||||
TransportLayer.SmtpTA.SMTPSession.SMTPClient.SmartEmailProcessing = true # OtOr for multiple SMTP sessions configuration TransportLayer.SmtpTA.SMTPSessions.DefaultSmartEmailProcessing=true |
If this property is not defined, the SMTP Transport Adaptor uses the a default one, which is false.
For example, outgoing Emails emails should have the following changes.:
- The subject Subject text was adjusted and got remapped the priority of the event and got remapped, as well as 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 value entries of the repeating group, with a size defined in (33) LinesOfText, the . The following mapping would be used:
Item | Email Content | Placeholder explanation |
---|---|---|
Subject | [< examples:
| The subject is taken from (147) Subject of Email (C) message
|
Message Body | PRIORITY: < DATE and TIME: < CONNECTION NAME: < CURRENT CONNECTION STATUS: < PREVIOUS CONNECTION STATUS: < FIXEDGE NOTIFICATION EVENT MESSAGE: < < Original FIX message: < |
|
JavaScript isStateNotification.js for filtering messages:
Code Block | ||||
---|---|---|---|---|
| ||||
// The script check if it is an important session state notification that should be routed to the 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 of prepareEmail.js above:
Code Block | ||||
---|---|---|---|---|
| ||||
// 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("|")); |
...
Custom Notification. Session is Online.msg
...
Status description
- Established - The FIX session is online and is sending heartbeats.
- AttemptToConnect - The FIX session is down.
In For the case of the initiator session: the session is about to try to connect.
In the case of For 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 or the session is stopped by the schedule.
For example, FIXEdge is configured to terminate a session after receiving a 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 a 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 <
|
|
Severity is set to NOTE because the action is expected. If events don't have the previous state, they |
will have the NULL state instead of the Initial state. | [NOTE] <(49) SenderCompID >:<(56) TargetCompID > AttemptToConnect |
AttemptToConnect → Established | The FIX Session < |
has been established. |
Severity is set to NOTE because the action is |
expected. | [NOTE] <(49) SenderCompID >:<(56) TargetCompID > Established |
Established → Non-gracefully terminated | The FIX Session < Possible reasons:
The severity is set to WARN because the disconnection is not expected at this time according to the configuration |
. | [WARN] <(49) SenderCompID >:<(56) TargetCompID > Non-gracefully terminated |
Non-gracefully terminated → AttemptToConnect | The FIX Session <
|
|
Severity is set to NOTE because the action is expected. | [NOTE] <(49) SenderCompID >:<(56) TargetCompID > AttemptToConnect |
Established → Terminated correctly | The FIX Session < |
Severity is set to NOTE because the disconnection is expected at this time according to the |
configuration. | [NOTE] <(49) SenderCompID >:<(56) TargetCompID > Terminated correctly |
Terminated correctly → AttemptToConnect | The FIX Session < |
|
|
The severity is set to WARN because the disconnection is not expected at this time according to the |
configuration. | [WARN] <(49) SenderCompID >:<(56) TargetCompID > AttemptToConnect |
Sending
...
emails about certain Logout message content
Sometimes the counterparty sends sends a 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 the Logout contains the a 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 a Logout with DestroySessionEvent routing with JavaScript
FIXEdge raises the DestroySessionEvent when it receives receives a FIX message (35=5, logout) when the session is being closed by the counterparty.
If the logout contains SessionStatus (1409) then the FIXEdge , 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 an email.
The configuration below configuration notifies about 1409=5
(Invalid username or password) and 1409=6
(Account locked) Logout reasons from all of the sessions
...
JavaScript sendSMTP.js just sends a FIX message (Logout) to SMTP TA
...
- Email examples:
Invalid_username _or_password.msg FIX message example:
Code Block 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 the Send
...
action from DestroySessionAction outside of
...
JavaScript is not supported
<DestroySessionEvent> can't route a message with the Send instruction outside of the javascriptJavaScript
The examples below lead to the errors.:
Sending to the FIX session:
Code Block language xml <DestroySessionAction> <Send> <Client Name="SMTPClient"/> </Send> </DestroySessionAction>
Resulted with error:
Incorrect event found: found unknown action 'Send'
Sending to a Transport Adapter:
Code Block language xml <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 javaScriptJavaScript
Code Block | ||
---|---|---|
| ||
<DestroySessionAction> <Script Language="JavaScript" FileName="../FIXEdge1/conf/sendSMTP.js"/> </DestroySessionAction> |
...
Other notifications
Apart from the the Email (C) message about a session state change, FIXEdge can also can generate other internal notifications:
...
These events have a custom message type 35=UFL defined in fixdic40.xml.
Info |
---|
The support Support for internal 35=UFL messages is mandatory, hence the fixidc40.xml dictionary is mandatory for correct FIXEdge functioning. |
Related pages
- https://kbb2bits.b2bitsatlassian.comnet/wiki/display/B2BITS/Monitoring+and+Management+of+EPAM+B2BITS+products