All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.credibledoc.combiner.CombinerService Maven / Gradle / Ivy

package com.credibledoc.combiner;

import com.credibledoc.combiner.config.Config;
import com.credibledoc.combiner.config.ConfigService;
import com.credibledoc.combiner.config.TacticConfig;
import com.credibledoc.combiner.date.DateService;
import com.credibledoc.combiner.exception.CombinerRuntimeException;
import com.credibledoc.combiner.file.FileService;
import com.credibledoc.combiner.log.buffered.LogBufferedReader;
import com.credibledoc.combiner.log.reader.ReaderService;
import com.credibledoc.combiner.node.file.NodeFile;
import com.credibledoc.combiner.node.file.NodeFileService;
import com.credibledoc.combiner.state.FilesMergerState;
import com.credibledoc.combiner.tactic.Tactic;
import com.credibledoc.combiner.tactic.TacticService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Pattern;

/**
 * This stateless instance contains methods for launching of
 * the {@link CombinerCommandLineMain#LOG_COMBINER_MODULE_NAME} tool.
 *
 * @author Kyrylo Semenko
 */
public class CombinerService {
    private static final Logger logger = LoggerFactory.getLogger(CombinerService.class);

    private static final String EMPTY_STRING = "";
    private static final String REPORT_FOLDER_EXTENSION = "_generated";
    private static final String NOT_IMPLEMENTED = "Not implemented";

    /**
     * Singleton.
     */
    private static CombinerService instance;

    /**
     * @return The {@link CombinerService} singleton.
     */
    static CombinerService getInstance() {
        if (instance == null) {
            instance = new CombinerService();
        }
        return instance;
    }

    /**
     * Load configuration by calling the {@link ConfigService#loadConfig(String)} method.
     * 
     * If the configuration does not have the {@link Config#getTacticConfigs()} defined, all log files will be
     * joined by calling the {@link #joinFiles(File, String)} method.
     * 
     * Else prepare a log files reader by calling the {@link #prepareReader(File, Config)} method.
     * 
     * And finally combine files line by line by calling the {@link #combine(OutputStream, FilesMergerState)} method.
     * 
     * @param sourceFolder a folder with log files
     * @param configAbsolutePath this configuration file will be used for filling out a {@link Config} instance.
     */
    public void combine(File sourceFolder, String configAbsolutePath) {
        try {
            Config config = ConfigService.getInstance().loadConfig(configAbsolutePath);
            if (config.getTacticConfigs().isEmpty()) {
                logger.info("Configuration not found. Files will be joined by last modification time.");
                joinFiles(sourceFolder, config.getTargetFileName());
                return;
            }
            prepareReader(sourceFolder, config);
            File targetFile = prepareTargetFile(sourceFolder, config.getTargetFileName());
            TacticService tacticService = TacticService.getInstance();
            try (OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(targetFile))) {
                ReaderService readerService = ReaderService.getInstance();
                readerService.prepareBufferedReaders(tacticService.getTactics());

                FilesMergerState filesMergerState = new FilesMergerState();
                NodeFileService nodeFileService = NodeFileService.getInstance();
                filesMergerState.setNodeFiles(nodeFileService.getNodeFiles());

                combine(outputStream, filesMergerState);
            }
            logger.info("All files combined to '{}'", targetFile.getAbsolutePath());
        } catch (Exception e) {
            throw new CombinerRuntimeException("Cannot combine files. Folder: '" + sourceFolder.getAbsolutePath() +
                "', configAbsolutePath: '" + configAbsolutePath + "'.", e);
        }
    }

    void combine(OutputStream outputStream, FilesMergerState filesMergerState) {
        ReaderService readerService = ReaderService.getInstance();
        LogBufferedReader logBufferedReader = readerService.getCurrentReader(filesMergerState);
        int currentLineNumber = 0;
        NodeFileService nodeFileService = NodeFileService.getInstance();
        String line = null;
        Config config = ConfigService.getInstance().loadConfig(null);
        try {
            line = readerService.readLineFromReaders(filesMergerState);
            logBufferedReader = readerService.getCurrentReader(filesMergerState);
            String substring = line.substring(0, 35);
            logger.info("The first line read from {}. Line: '{}...'", ReaderService.class.getSimpleName(), substring);
            while (line != null) {
                List multiline = readerService.readMultiline(line, logBufferedReader);

                currentLineNumber = currentLineNumber + multiline.size();
                if (currentLineNumber % 100000 == 0) {
                    logger.debug("{} lines processed", currentLineNumber);
                }

                writeMultiline(config, outputStream, nodeFileService, logBufferedReader, multiline);

                line = readerService.readLineFromReaders(filesMergerState);
                logBufferedReader = readerService.getCurrentReader(filesMergerState);
            }
            logger.debug("{} lines processed (100%)", currentLineNumber);
        } catch (Exception e) {
            String fileName = "null";
            if (logBufferedReader != null) {
                fileName = readerService.getFile(logBufferedReader).getAbsolutePath();
            }
            String message =
                "Creation of reports failed. File: '" + fileName +
                    "', line: '" + line + "'";
            throw new CombinerRuntimeException(message, e);
        }
    }

    /**
     * Create a {@link Tactic} instance for each {@link Config#getTacticConfigs()}.
     * 

* Add created {@link Tactic} instances to the {@link com.credibledoc.combiner.tactic.TacticService}. *

* Call the {@link TacticService#prepareReaders(Set, Set)} method. * * @param folder the folder with log files * @param config contains configuration of {@link Config#getTacticConfigs()} */ void prepareReader(File folder, Config config) { TacticService tacticService = TacticService.getInstance(); Set tactics = tacticService.getTactics(); for (final TacticConfig tacticConfig : config.getTacticConfigs()) { final Tactic tactic = createTactic(tacticConfig); tactics.add(tactic); } Set files = FileService.getInstance().collectFiles(folder); tacticService.prepareReaders(files, tactics); } private void writeMultiline(Config config, OutputStream outputStream, NodeFileService nodeFileService, LogBufferedReader logBufferedReader, List multiline) throws IOException { NodeFile nodeFile = nodeFileService.findNodeFile(logBufferedReader); for (String nextLine : multiline) { if (config.isPrintNodeName()) { outputStream.write(nodeFile.getNodeLog().getName().getBytes()); outputStream.write(" ".getBytes()); } String shortName = nodeFile.getNodeLog().getTactic().getShortName(); if (!shortName.isEmpty()) { outputStream.write(shortName.getBytes()); outputStream.write(" ".getBytes()); } outputStream.write(nextLine.getBytes()); outputStream.write(System.lineSeparator().getBytes()); } } private void joinFiles(File folder, String targetFileName) throws IOException { List files = new ArrayList<>(); collectFilesRecursively(folder, files); Collections.sort(files, new Comparator() { @Override public int compare(File left, File right) { if (left.lastModified() == right.lastModified()) { return 0; } return left.lastModified() > right.lastModified() ? 1 : -1; } }); File targetFile = prepareTargetFile(folder, targetFileName); byte[] buffer = new byte[1024]; try (OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(targetFile))) { for (File file : files) { try (InputStream inputStream = new BufferedInputStream(new FileInputStream(file))) { int lengthRead; while ((lengthRead = inputStream.read(buffer)) > 0) { outputStream.write(buffer, 0, lengthRead); } if (file != files.get(files.size() - 1)) { outputStream.write(System.lineSeparator().getBytes()); logger.info("File combined and line separator appended: '{}'", file.getAbsolutePath()); } else { logger.info("File combined: '{}'", file.getAbsolutePath()); } outputStream.flush(); } } } logger.info("All files combined to '{}'", targetFile.getAbsolutePath()); } private void collectFilesRecursively(File folder, List collectedFiles) { File[] files = folder.listFiles(); if (files == null) { throw new CombinerRuntimeException("The file is not a folder. File: '" + folder.getAbsolutePath() + "'"); } for (File file : files) { if (file.isFile()) { collectedFiles.add(file); } else { collectFilesRecursively(file, collectedFiles); } } } File prepareTargetFile(File targetFolder, String targetFileName) { File newFolder = new File(targetFolder.getParent(), targetFolder.getName() + REPORT_FOLDER_EXTENSION); boolean created = newFolder.mkdirs(); if (created) { logger.info("New folder created: '{}'", newFolder.getAbsolutePath()); } File newFile = new File(newFolder, targetFileName); logger.info("New file created: '{}'", newFile.getAbsolutePath()); return newFile; } private Tactic createTactic(final TacticConfig tacticConfig) { return new Tactic() { private SimpleDateFormat simpleDateFormat = new SimpleDateFormat(tacticConfig.getSimpleDateFormat()); private Pattern pattern = Pattern.compile(tacticConfig.getRegex()); @Override public Date findDate(File file) { Date date = DateService.getInstance() .findDateInFile(file, simpleDateFormat, pattern, tacticConfig.getMaxIndexEndOfTime()); if (date == null) { throw new CombinerRuntimeException("Cannot recognize some line with Date pattern " + tacticConfig.getSimpleDateFormat() + " in file: " + file.getAbsolutePath()); } return date; } @Override public Date findDate(String line, NodeFile nodeFile) { int maxIndex = tacticConfig.getMaxIndexEndOfTime() == null ? line.length() : tacticConfig.getMaxIndexEndOfTime(); return DateService.getInstance().parseDateTimeFromLine( line, simpleDateFormat, pattern, maxIndex); } @Override public boolean containsDate(String line) { return findDate(line) != null; } @Override public String parseDateStingFromLine(String line) { throw new CombinerRuntimeException(NOT_IMPLEMENTED); } @Override public String findThreadName(String line) { throw new CombinerRuntimeException(NOT_IMPLEMENTED); } @Override public Date findDate(String line) { return findDate(line, null); } @Override public String getShortName() { return tacticConfig.getApplicationName() != null ? tacticConfig.getApplicationName() : EMPTY_STRING; } @Override public boolean identifyApplication(String line, LogBufferedReader logBufferedReader) { return containsDate(line); } }; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy