第六课：网络日志分类与统计工具

一、打开材料
解压 lesson-6-exercises.zip，用 VS Code 打开其中的 lesson-6-exercises 文件夹。
左侧应同时看到 log_loader.py、log_tools.py、analyzer.py、main.py 和 data 文件夹。
右击这个文件夹，在集成终端中打开。Windows 通常用 python，macOS 可把命令开头换成 python3。
本课不需要额外安装软件包。提供的读取、显示和观察工具可以直接使用，具体文件解析在后续课程学习。

二、先看输入，再编写两个函数
1. 运行 python observe_input.py data/familiar.log，观察八条可转换记录和第一条日志。
2. 在 log_tools.py 中写 split_records(records)，返回有效和规则无效两个新列表。
   沿用第五课规则：级别为 INFO、WARN、ERROR 且耗时非负；不修改原记录，保持先后顺序。
3. 运行 python observe_steps.py split data/familiar.log，应看到有效6、规则无效2。
4. 在 analyzer.py 中写 analyze_logs(records, threshold_ms=1000, k=3)。
   组合筛选、四类计数、不同IP与设备数量、IP与事件排名、耗时判断，返回约定的结果字典。
5. 运行 python observe_steps.py counts data/familiar.log，再运行 python observe_steps.py ranking data/familiar.log。
6. 在 main.py 中把三行读取提示替换为已有注释给出的分析调用和 show_report 调用。
   显示结果的函数已提供；重点是由自己写的分析函数产生真实结果。

三、使用完整数据
python main.py data/practice.log
python main.py data/practice.log 1500 2
命令后面的三项依次是文件名、耗时阈值、K；省略阈值与K时使用1000与3。
data/practice.log 是固定的课堂模拟日志，共24行；包含重复事件、并列次数、规则无效和无法转换行。
重复行仍表示输入中的一条记录，本课计次时保留它；不同IP和设备数量使用集合去重。
八条熟悉日志、二十四条综合日志、三条原始日志副本分别用于不同学习步骤，比较前先说清文件名。

四、理解三种去向
load_logs(filename) 返回 records, unreadable_lines。
records 中每条记录只有 timestamp、log_level、source_ip、device、event、duration_ms 六个字段。
duration_ms 已转换为有限浮点数；未知级别和负耗时仍交给 split_records 判断。
空白行、字段不齐、空字段、非数字或无穷/非数耗时无法转换，保留行号、原文与原因。
空文件没有行；空白行是一条需要保留的无法转换行，两者不同。
读取失败会显示原因并结束，不能把它当成空文件继续统计。
总行数 = 可转换记录数 + 无法转换行数。
总无效数 = 规则无效记录数 + 无法转换行数。
四类计数、去重、排名和阈值判断只使用有效记录。
筛选新建列表，列表里的字典仍与原记录共用；本课统计只读取这些字典。

五、比较边界与重复调用
完成两个函数后运行 python check_cases.py，先预测再看实际结果。
data/empty.log：0行；data/all_invalid.log：3条规则无效记录。
data/thresholds.log：999、1000、1001毫秒；data/unreadable.log：空白行与无法转换内容。
K为0时排名为空；K超过项目数时显示已有项目；次数并列时保留首次出现顺序。
所有观察都使用自己写出的函数，运行结果不一致时回到对应函数修改，再重新运行。

六、接入自己第三课的日志
data/network.log 是第三课A、B、C三条课堂输出的示范副本，不是你的个人文件。
先在实验1文件夹中为自己的 network.log 保留备份，再把另一份副本复制到本课 data 文件夹。
只替换本课 data/network.log；保留实验1原文件和备份，不从本课覆盖回去。
运行 python observe_input.py data/network.log，再运行 python main.py data/network.log。
把本人文件的行数、统计和结果解释写进报告，不直接沿用课堂副本的数字。

七、整理成果
保留整个程序文件夹、本人原始日志副本、综合运行结果、边界结果、本人截图和实验报告。
能够沿 main → analyze_logs → split_records / count_by_field / is_slow / top_k 说明调用和返回。
说明无法转换行与规则无效记录分别在哪里保留，以及每项结果使用了哪些有效记录。
