Samples :: SBE Log Decoder

SBE Log Decoder

Description

SBE Log Decoder reads a Base64-encoded summary file, decodes each message using the SBE template, and writes the decoded output to a text file.

Directory Contents

Item Description
conf configuration directory
src source code

Usage

  • Run the sample (scripts are under src/main/script/):
    • win: SbeLogDecoder.bat
    • linux: SbeLogDecoder.sh
  • Clean everything (scripts are under samples/src/main/script/ at the repo root):
    • win: clean.bat
    • linux: clean.sh

Arguments

The sample expects [SummaryFileName]. Set CMD_LINE_ARGS in the script or pass the argument when running the main class directly.

Source Code

import biz.onixs.cme.ilink3.handler.Utils;
import biz.onixs.sbe.ByteDecoder;
import biz.onixs.sbe.ByteDecoderFactory;
import biz.onixs.sbe.IMessage;
import biz.onixs.sbe.def.MessageSchema;
import biz.onixs.util.File;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.Base64;

/**
 * Sbe Log Decoder sample.
 */
public class SbeLogDecoder implements Runnable {
    private static final Logger LOG = LoggerFactory.getLogger(SbeLogDecoder.class);
    private static final String templateFile = "sample/ilinkbinary.xml";
    private static final char FileExtensionDelimiter = '.';
    private static final String DecodedSummaryFileExtension = ".txt";
    private final String summaryFileName;
    private final ByteDecoder decoder;

    public SbeLogDecoder(final String summaryFileName) {
        this.summaryFileName = summaryFileName;
        final MessageSchema messageSchema = Utils.loadTemplate(templateFile);
        decoder = new ByteDecoderFactory().create(messageSchema);
    }

    public void run() {
        // CME log format guarantees a timestamp prefix and base64 payload per line.
        final String decodedSummaryFileName = summaryFileName.
                substring(0, summaryFileName.indexOf(FileExtensionDelimiter)) + DecodedSummaryFileExtension;
        int messageCounter = 0;
        File inputFile = null;
        File outputFile = null;
        boolean outputOpened = false;
        try {
            inputFile = new File(summaryFileName, "rw");
            outputFile = new File(decodedSummaryFileName, "rw");
            outputOpened = true;
            String line;
            while (!("").equals(line = inputFile.getLine('\n'))) {
                final String rawMsg = line.substring(line.lastIndexOf(' ') + 1)
                        .replace("\n", "").replace("\r", "");
                final byte[] rawMsgBytes = Base64.getDecoder().decode(rawMsg);
                try {
                    // Decode the base64 payload into a readable SBE message.
                    final IMessage msg = decoder.decodePreCreatedMessage(rawMsgBytes, 0, rawMsgBytes.length);
                    outputFile.write(line.substring(0, 26));
                    outputFile.write(msg.toString());
                    outputFile.write(System.lineSeparator());
                    ++messageCounter;
                } catch (final Exception e) {
                    LOG.warn("Failed to parse message: {}", rawMsg, e);
                }
            }
        } catch (final IOException e) {
            throw new RuntimeException("Failed to open file: " + e.getMessage(), e);
        } finally {
            closeQuietly(outputFile, "output file");
            closeQuietly(inputFile, "input file");
            if (outputOpened) {
                LOG.info("{} messages are decoded successfully and written into {} file.",
                        messageCounter, decodedSummaryFileName);
            }
        }
    }

    private static void closeQuietly(final File file, final String name) {
        if (null == file) {
            return;
        }
        try {
            file.close();
        } catch (final IOException e) {
            LOG.warn("Failed to close {}.", name, e);
        }
    }

    public static void main(final String[] args) {
        LOG.info("CME iLink 3 SbeLogDecoder Sample.");
        String summaryFileName = "";
        if (args.length >= 1) {
            summaryFileName = args[0];
        }
        if (summaryFileName.isEmpty()) {
            LOG.error("Usage: SbeLogDecoder [SummaryFileName]");
            return;
        }
        try {
            LOG.info("Decoding {} log file...", summaryFileName);
            final SbeLogDecoder sbeLogDecoder = new SbeLogDecoder(summaryFileName);
            sbeLogDecoder.run();
        } catch (final Exception e) {
            LOG.error("EXCEPTION: {}", e.getMessage());
            e.printStackTrace();
        }
    }
}