org.apache.metron.parsers.syslog.BaseSyslogParser.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.metron.parsers.syslog.BaseSyslogParser.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.metron.parsers.syslog;

import com.github.palindromicity.syslog.SyslogParser;
import com.github.palindromicity.syslog.dsl.SyslogFieldKeys;
import org.apache.commons.lang3.StringUtils;
import org.apache.metron.parsers.DefaultMessageParserResult;
import org.apache.metron.parsers.ParseException;
import org.apache.metron.parsers.interfaces.MessageParser;
import org.apache.metron.parsers.interfaces.MessageParserResult;
import org.apache.metron.parsers.utils.SyslogUtils;
import org.json.simple.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.io.Serializable;
import java.io.StringReader;
import java.lang.invoke.MethodHandles;
import java.time.Clock;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Consumer;

/**
 * Parser for well structured RFC 5424 messages.
 */
public abstract class BaseSyslogParser implements MessageParser<JSONObject>, Serializable {
    protected static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

    private Optional<Consumer<JSONObject>> messageProcessorOptional = Optional.empty();
    private transient SyslogParser syslogParser;

    protected Clock deviceClock;

    protected void setSyslogParser(SyslogParser syslogParser) {
        this.syslogParser = syslogParser;
    }

    protected void setMessageProcessor(Consumer<JSONObject> function) {
        this.messageProcessorOptional = Optional.of(function);
    }

    protected abstract SyslogParser buildSyslogParser(Map<String, Object> config);

    @Override
    public void configure(Map<String, Object> parserConfig) {
        // we'll pull out the clock stuff ourselves
        String timeZone = (String) parserConfig.get("deviceTimeZone");
        if (timeZone != null)
            deviceClock = Clock.system(ZoneId.of(timeZone));
        else {
            deviceClock = Clock.systemUTC();
            LOG.warn("[Metron] No device time zone provided; defaulting to UTC");
        }
        syslogParser = buildSyslogParser(parserConfig);
    }

    @Override
    public void init() {
    }

    @Override
    public boolean validate(JSONObject message) {
        if (!(message.containsKey("original_string"))) {
            LOG.trace("[Metron] Message does not have original_string: {}", message);
            return false;
        } else if (!(message.containsKey("timestamp"))) {
            LOG.trace("[Metron] Message does not have timestamp: {}", message);
            return false;
        } else {
            LOG.trace("[Metron] Message conforms to schema: {}", message);
            return true;
        }
    }

    @Override
    @SuppressWarnings("unchecked")
    public Optional<MessageParserResult<JSONObject>> parseOptionalResult(byte[] rawMessage) {
        try {
            if (rawMessage == null || rawMessage.length == 0) {
                return Optional.empty();
            }

            String originalString = new String(rawMessage);
            final List<JSONObject> returnList = new ArrayList<>();
            Map<Object, Throwable> errorMap = new HashMap<>();
            try (Reader reader = new BufferedReader(new StringReader(originalString))) {
                syslogParser.parseLines(reader, (m) -> {
                    JSONObject jsonObject = new JSONObject(m);
                    // be sure to put in the original string, and the timestamp.
                    // we wil just copy over the timestamp from the syslog
                    jsonObject.put("original_string", originalString);
                    try {
                        setTimestamp(jsonObject);
                    } catch (ParseException pe) {
                        errorMap.put(originalString, pe);
                        return;
                    }
                    messageProcessorOptional.ifPresent((c) -> c.accept(jsonObject));
                    returnList.add(jsonObject);
                }, errorMap::put);

                return Optional.of(new DefaultMessageParserResult<JSONObject>(returnList, errorMap));
            }
        } catch (IOException e) {
            String message = "Unable to read buffer " + new String(rawMessage) + ": " + e.getMessage();
            LOG.error(message, e);
            return Optional.of(new DefaultMessageParserResult<JSONObject>(new IllegalStateException(message, e)));
        }
    }

    @SuppressWarnings("unchecked")
    private void setTimestamp(JSONObject message) throws ParseException {
        String timeStampString = (String) message.get(SyslogFieldKeys.HEADER_TIMESTAMP.getField());
        if (!StringUtils.isBlank(timeStampString) && !timeStampString.equals("-")) {
            message.put("timestamp", SyslogUtils.parseTimestampToEpochMillis(timeStampString, deviceClock));
        } else {
            message.put("timestamp", LocalDateTime.now().toEpochSecond(ZoneOffset.UTC));
        }
    }
}