Java大任务 :日志分析

Java大任务 :日志分析,第1张

Java大任务 :日志分析 Java基础-E:日志分析

分析提供的 redis.log 日志文件,要求:

统计数据库的存盘次数(以「DB saved on disk」的出现为标识);

统计出最小存盘时间和最大存盘时间(以「Background saving started by pid xxxx」为开始时间,以「DB saved on disk」为结束时间,这两个时间之间的长度间隔即为存盘时间),如果有多个最小存盘时间和最大存盘时间,那么就取开始时间最早的那个;

找出存盘时是否出现了重复的进程号(就是开始时间 pid 后的数值);

以「*」为分界,统计「*」之后出现的单词数量,以及出现频率最高的单词,并从大到小排序(如果有多个单词并列最大,那么全列出来);

要求代码中必须使用 Lambda 表达式;

答:

实现代码:

package com.xxm.advanced_camp.greatmission4_loganalysis;

import java.io.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.Map;


public class LogAnalysis_List {

    public static void readFile(String filePath) throws Exception {
        //初始化数组。
        List list = new ArrayList<>();

        //定义计数器,用于记录存盘次数
        int saveCounts = 0;

        File file = new File(filePath);
        FileInputStream fileInputStream = new FileInputStream(file);
        InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream);
        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);


        while (bufferedReader.read() != -1) {
            list.add(bufferedReader.readLine());
        }
        //文件行数
        long fileLen = list.size();

        List savedCountList = list.stream()
                .filter(s -> s.contains("DB saved on disk"))
                .collect(Collectors.toList());
        for (String s : savedCountList) {
            saveCounts++;
        }


        //开始存储时间的数组。
        List saveStartTimeList = timeInList(list, "Background saving started by pid");

        //调用 toDate 方法,把字符串列表转化为 Date 列表
        List saveStartTimeDateList = toDate(saveStartTimeList);

        //完成存储时间的数组。
        List saveEndTimeList = timeInList(list, "DB saved on disk");

        //调用 toDate 方法,把字符串列表转化为时间列表
        List saveEndTimeDateList = toDate(saveEndTimeList);


        //存储消耗时间的数组
        List saveSpentTimeList = new ArrayList<>();
        for (int i = 0; i < saveStartTimeList.size(); i++) {
            saveSpentTimeList.add(saveEndTimeDateList.get(i).getTime() - saveStartTimeDateList.get(i).getTime());
        }
        long maxSaveTime = saveSpentTimeList.get(0);
        long minSaveTime = saveSpentTimeList.get(0);

        for (int i = 0; i < saveSpentTimeList.size(); i++) {
            if (saveSpentTimeList.get(i) < minSaveTime) {
                minSaveTime = saveSpentTimeList.get(i);
            } else if (saveSpentTimeList.get(i) > maxSaveTime) {
                maxSaveTime = saveSpentTimeList.get(i);
            }
        }


        //统计 * 号后出现的单词
        HashMap wordMap = new HashMap<>(100);

        for (String str : list) {
            String[] arr = str.split(" ");
            for (int i = 4; i < arr.length; i++) {
                //先判断它是不是数字
                if (!isNumeric(arr[i])) {
                    //如果集合中没有该单词,则添加,并且次数记为 1。
                    if (!wordMap.containsKey(arr[i])) {
                        wordMap.put(arr[i], 1);
                    }
                    //如果集合中有该单词,则将其次数 +1。
                    else if (wordMap.containsKey(arr[i])) {
                        Integer count = wordMap.get(arr[i]);
                        wordMap.replace(arr[i], count + 1);
                    }
                }
            }
        }

        //统计 pid
        HashMap pidMap = new HashMap<>(100);

        List pidList = list.stream()
                .filter(s -> s.contains("pid"))
                .collect(Collectors.toList());

        for (String str : pidList) {
            String[] arr = str.split(" ");
            //因为 pid 在日志中是第 10 个,因此索引为 9
            //如果集合中没有该 pid,则添加,并且次数记为 1。
            if (!pidMap.containsKey(arr[9])) {
                pidMap.put(arr[9], 1);
            }
            //如果集合中有该 pid,则将其次数 +1。
            else if (pidMap.containsKey(arr[9])) {
                Integer count = pidMap.get(arr[9]);
                pidMap.replace(arr[9], count + 1);
            }
        }


        //对 wordMap 中的数据排序
        List> sortedWordMap = new ArrayList>(wordMap.entrySet());
        //通过比较器降序排序
        Collections.sort(sortedWordMap, ((o1, o2) -> o2.getValue().
                compareTo(o1.getValue())));

        //筛选 pidMap 中 value 大于 1 的数据
        Collection values = pidMap.values();
        while (values.contains(1)) {
            values.remove(1);
        }

        List> repeatedPidMap = new ArrayList>(pidMap.entrySet());


        //此处为代码末尾:
        //输出文件的总行数
        System.out.println("文件总行数为:" + fileLen + "行");

        // 输出存储数据的次数
        System.out.println("存储数据的次数为:" + saveCounts + "次");

        //输出最大、最小存储时间
        System.out.println("最大存储时间为:" + maxSaveTime + "毫秒");
        System.out.println("最小存储时间为:" + minSaveTime + "毫秒");

        //输出 * 后出现的单词,及其次数
        System.out.println("单词出现的次数为(降序排列):");
        for (
                Map.Entry entry : sortedWordMap) {
            System.out.println(entry.getKey() + ":" + entry.getValue() + " 次");
        }

        //输出重复出现的pid
        System.out.println("重复出现的pid有:");
        for (
                Map.Entry entry : repeatedPidMap) {
            System.out.println(entry.getKey() + ":" + entry.getValue() + " 次");
        }

    }

    // toDate方法:
    public static List toDate(List stringList) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        List dateList = new ArrayList<>();
        for (String s : stringList) {
            try {
                Date d = sdf.parse(s);
                dateList.add(d);
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        return dateList;
    }


    //获取时间数组的方法,传入参数为list列表和关键字
    public static List timeInList(List list, String keyword) {
        List TimeList = new ArrayList<>();

        list.stream()
                .filter(s -> s.contains(keyword))
                .forEach(s -> {
                    s = (s.split(" ")[1] + " " + s.split(" ")[2]);
                    TimeList.add(s);
                });
        return TimeList;
    }

    //判断字符串是否为数字的方法
    public static boolean isNumeric(String str) {
        return str.chars().allMatch(Character::isDigit);
    }


    public static void main(String[] args) {
        try {
            readFile("C:\Users\yyq\Desktop\redis.log");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

输出结果:

文件总行数为:101143行
存储数据的次数为:20229次
最大存储时间为:5200毫秒
最小存储时间为:4毫秒
单词出现的次数为(降序排列):
Background:40457 次
saving:40457 次
by:40457 次
saved:20229 次
pid:20229 次
seconds:20229 次
in:20229 次
disk:20229 次
changes:20229 次
on:20229 次
started:20229 次
DB:20229 次
used:20228 次
MB:20228 次
success:20228 次
memory:20228 次
RDB::20228 次
copy-on-write:20228 次
of:20228 次
terminated:20228 次
with:20228 次
重复出现的pid有:
4970:2 次
2304:2 次
3631:2 次
3633:2 次
2309:2 次
3635:2 次
  ...后略

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5434935.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-11
下一篇 2022-12-11

发表评论

登录后才能评论

评论列表(0条)

保存