<commit_before>package com.dtolabs.rundeck.app.internal.logging

import com.dtolabs.rundeck.core.logging.LogEvent
import com.dtolabs.rundeck.core.logging.LogLevel
import com.dtolabs.rundeck.core.logging.LogUtil
import com.dtolabs.rundeck.core.utils.Utility

import java.text.SimpleDateFormat

/**
 * $INTERFACE is ...
 * User: greg
 * Date: 5/21/13
 * Time: 2:03 PM
 */
class RundeckLogFormat implements OutputLogFormat, LineLogFormat {
    public static final String FORMAT_MIME = "text/x-rundeck-log-v2.0"
    public static final String DELIM = '^'
    public static final String FILE_START = DELIM + FORMAT_MIME + DELIM
    public static final String FILE_END = DELIM + "END" + DELIM
    static final char BACKSLASH = '\\' as char
    SimpleDateFormat w3cDateFormat

    public RundeckLogFormat() {
        w3cDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
        w3cDateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
    }

    public String getHead() {
        return FILE_START ;
    }

    public String getTail() {
        return FILE_END ;
    }

    @Override
    String outputBegin() {
        return getHead()
    }

    @Override
    String outputFinish() {
        return getTail()
    }

    static boolean detectFormat(String firstLine){
        return firstLine.startsWith(FILE_START)
    }
    /**
     * @param context data
     * @param message message
     *
     * @return
     */
    @Override
    String outputEvent(LogEvent entry) {
        def String date = w3cDateFormat.format(entry.datetime)
        String dMesg = entry.message ?: '';
        while (dMesg.endsWith('\r')) {
            dMesg = dMesg.substring(0, dMesg.length() - 1)
        }
        StringBuffer sb = new StringBuffer()
        sb.append(DELIM)
        //date
        sb.append(date).append('|')
        sb.append(entry.eventType?entry.eventType.replaceAll('\\|',''):'').append('|')
        //level
        sb.append(entry.loglevel).append("|")

        //metadata
        def metadata = entry.metadata
        if (metadata) {
            sb.append('{')
            def sort = metadata.keySet().sort()
            for (int i = 0; i < sort.size(); i++) {
                def key = sort[i]
                if (i > 0) {
                    sb.append('|')
                }
                sb.append(backslashEscape(key,'=|}'))
                sb.append('=')
                sb.append(backslashEscape(metadata[key],'=|}'))
            }

            sb.append('}')
        }

        sb.append("|")
        //mesg
        sb.append(backslashEscape(dMesg, DELIM))
        //end
        sb.append(DELIM)

        return sb.toString()
    }

    static String backslashEscape(String dMesg, String chars) {
        dMesg.replaceAll('([\\\\' + chars + '])', '\\\\$1')
    }

    static class RDFormatItem implements LineLogFormat.FormatItem {
        boolean fileEnd
        boolean lineComplete
        boolean fileStart
        boolean invalid
        LogEvent entry
        String partial
        String errorMessage

        @Override
        String toString() {
            if (invalid) {
                return "Invalid Line: " + errorMessage
            } else {
                return genToString()
            }
        }

        @Override
        public java.lang.String genToString() {
            return "RDFormatItem{" +
                    "fileEnd=" + fileEnd +
                    ", lineComplete=" + lineComplete +
                    ", fileStart=" + fileStart +
                    ", entry=" + entry +
                    ", partial='" + partial + '\'' +
                    '}';
        }

        static LineLogFormat.FormatItem error(String message) {
            def item = new RDFormatItem()
            item.invalid = true
            item.errorMessage = message
            return item
        }
    }
    /**
     * Parse the log line, and if aany log entries are completed add them to the buffer
     * @param line
     */
    LineLogFormat.FormatItem parseLine(String line) {
        if (line == FILE_END) {
            return new RDFormatItem(fileEnd: true)
        } else if (line == FILE_START) {
            return new RDFormatItem(fileStart: true)
        } else if (line.startsWith(DELIM)) {
            def temp = line.substring(DELIM.length())
            def item = new RDFormatItem()
            def arr = temp.split("\\|", 4)

            if (arr.length != 4) {
                return RDFormatItem.error("Expected 4 sections: " + arr.length)
            }
            Date time = w3cDateFormat.parse(arr[0])
            String eventType = arr[1] ?: LogUtil.EVENT_TYPE_LOG
            LogLevel level = LogLevel.valueOf(arr[2])
            def rest = arr[3]<commit_msg>Fix date format synchronization for #584<commit_after>package com.dtolabs.rundeck.app.internal.logging

import com.dtolabs.rundeck.core.logging.LogEvent
import com.dtolabs.rundeck.core.logging.LogLevel
import com.dtolabs.rundeck.core.logging.LogUtil
import com.dtolabs.rundeck.core.utils.Utility

import java.text.DateFormat
import java.text.SimpleDateFormat

/**
 * $INTERFACE is ...
 * User: greg
 * Date: 5/21/13
 * Time: 2:03 PM
 */
class RundeckLogFormat implements OutputLogFormat, LineLogFormat {
    public static final String FORMAT_MIME = "text/x-rundeck-log-v2.0"
    public static final String DELIM = '^'
    public static final String FILE_START = DELIM + FORMAT_MIME + DELIM
    public static final String FILE_END = DELIM + "END" + DELIM
    static final char BACKSLASH = '\\' as char
    private static final ThreadLocal<DateFormat> w3cDateFormat = new ThreadLocal<DateFormat>() {
        protected DateFormat initialValue() {
            SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
            fmt.setTimeZone(TimeZone.getTimeZone("GMT"));
            return fmt;
        }
    };

    public RundeckLogFormat() {

    }

    public String getHead() {
        return FILE_START ;
    }

    public String getTail() {
        return FILE_END ;
    }

    @Override
    String outputBegin() {
        return getHead()
    }

    @Override
    String outputFinish() {
        return getTail()
    }

    static boolean detectFormat(String firstLine){
        return firstLine.startsWith(FILE_START)
    }
    /**
     * @param context data
     * @param message message
     *
     * @return
     */
    @Override
    String outputEvent(LogEvent entry) {
        def String date = w3cDateFormat.get().format(entry.datetime)
        String dMesg = entry.message ?: '';
        while (dMesg.endsWith('\r')) {
            dMesg = dMesg.substring(0, dMesg.length() - 1)
        }
        StringBuffer sb = new StringBuffer()
        sb.append(DELIM)
        //date
        sb.append(date).append('|')
        sb.append(entry.eventType?entry.eventType.replaceAll('\\|',''):'').append('|')
        //level
        sb.append(entry.loglevel).append("|")

        //metadata
        def metadata = entry.metadata
        if (metadata) {
            sb.append('{')
            def sort = metadata.keySet().sort()
            for (int i = 0; i < sort.size(); i++) {
                def key = sort[i]
                if (i > 0) {
                    sb.append('|')
                }
                sb.append(backslashEscape(key,'=|}'))
                sb.append('=')
                sb.append(backslashEscape(metadata[key],'=|}'))
            }

            sb.append('}')
        }

        sb.append("|")
        //mesg
        sb.append(backslashEscape(dMesg, DELIM))
        //end
        sb.append(DELIM)

        return sb.toString()
    }

    static String backslashEscape(String dMesg, String chars) {
        dMesg.replaceAll('([\\\\' + chars + '])', '\\\\$1')
    }

    static class RDFormatItem implements LineLogFormat.FormatItem {
        boolean fileEnd
        boolean lineComplete
        boolean fileStart
        boolean invalid
        LogEvent entry
        String partial
        String errorMessage

        @Override
        String toString() {
            if (invalid) {
                return "Invalid Line: " + errorMessage
            } else {
                return genToString()
            }
        }

        @Override
        public java.lang.String genToString() {
            return "RDFormatItem{" +
                    "fileEnd=" + fileEnd +
                    ", lineComplete=" + lineComplete +
                    ", fileStart=" + fileStart +
                    ", entry=" + entry +
                    ", partial='" + partial + '\'' +
                    '}';
        }

        static LineLogFormat.FormatItem error(String message) {
            def item = new RDFormatItem()
            item.invalid = true
            item.errorMessage = message
            return item
        }
    }
    /**
     * Parse the log line, and if aany log entries are completed add them to the buffer
     * @param line
     */
    LineLogFormat.FormatItem parseLine(String line) {
        if (line == FILE_END) {
            return new RDFormatItem(fileEnd: true)
        } else if (line == FILE_START) {
            return new RDFormatItem(fileStart: true)
        } else if (line.startsWith(DELIM)) {
            def temp = line.substring(DELIM.length())
            def item = new RDFormatItem()
            def arr = temp.split("\\|", 4)

            if (arr.length != 4) {
                return RDFormatItem.error("Expected 4 sections: " + arr.length)
            }
            Date time = w3cDateFormat.get().parse(arr[0])
            String eventType = arr[1] ?: LogUtil.EVENT_TYPE_LOG
            LogLevel level = LogLevel.valueOf(arr[2])
            def rest = arr[3]
{'fraction_non_alphanumeric': 0.11613969828476958, 'fraction_numerical': 0.005682992353792105, 'mean_word_length': 1.790141251081003, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4445719', 'n_tokens_mistral': 2894, 'n_tokens_neox': 2746, 'n_words': 627}