|
1 | 1 | import json |
2 | 2 | import logging |
3 | | -from os import path |
4 | 3 | from pathlib import Path |
5 | 4 | import tempfile |
6 | 5 | import time |
7 | 6 | import xml.etree.ElementTree as ET |
8 | 7 |
|
9 | | -import pandas as pd |
| 8 | +import numpy as np |
10 | 9 | from src.collector.interface import ( |
11 | 10 | CollectorOutputReaderException, |
12 | 11 | CollectorOutputReaderInterface, |
|
36 | 35 | "ipfix:msgLength": "MSG_LENGTH", |
37 | 36 | } |
38 | 37 |
|
| 38 | +CSV_DTYPES = { |
| 39 | + "BYTES": np.uint64, |
| 40 | + "PACKETS": np.uint64, |
| 41 | + "PROTOCOL": np.uint8, |
| 42 | + "SRC_PORT": np.uint16, |
| 43 | + "SRC_IP": str, |
| 44 | + "DST_PORT": np.uint16, |
| 45 | + "DST_IP": str, |
| 46 | + "START_TIME": np.uint64, |
| 47 | + "END_TIME": np.uint64, |
| 48 | + "EXPORT_TIME": np.uint32, |
| 49 | + "SEQ_NUMBER": np.uint32, |
| 50 | + "MSG_LENGTH": np.uint64, |
| 51 | +} |
| 52 | + |
39 | 53 |
|
40 | 54 | class JQ(CollectorOutputReaderInterface): |
41 | 55 | CONFIG_FILE = "config.xml" |
@@ -275,36 +289,29 @@ def save_csv(self, csv_file: str): |
275 | 289 | csv_file: str |
276 | 290 | Path to CSV file. Local file, CSV will be downloaded when collector running on remote. |
277 | 291 | """ |
| 292 | + header = CSV_HEADER_TO_ANALYZER_HEADER.values() |
278 | 293 |
|
279 | | - rsync = Rsync(self._executor) |
280 | | - filename = path.basename(csv_file) |
281 | | - tmp_file = path.join(rsync.get_data_directory(), filename) |
282 | | - header = ",".join( |
283 | | - [f'"{field}"' for field in CSV_HEADER_TO_ANALYZER_HEADER.keys()] |
284 | | - ) |
| 294 | + batch_size = 100_000 |
| 295 | + buffer = [] |
285 | 296 |
|
286 | 297 | logging.getLogger().info( |
287 | 298 | "Preparing CSV output by calling ipfixcol2 + jq command..." |
288 | 299 | ) |
289 | 300 | start = time.time() |
290 | | - Tool(f"echo '{header}' > {tmp_file}", executor=self._executor).run() |
291 | 301 | # write csv |
292 | | - Tool(f"({self._cmd_csv}) >> {tmp_file}", executor=self._executor).run() |
293 | | - end = time.time() |
294 | | - logging.getLogger().info("CSV output saved in %.2f seconds.", (end - start)) |
| 302 | + process = AsyncTool(self._cmd_csv, executor=self._executor) |
| 303 | + process.run() |
295 | 304 |
|
296 | | - start = time.time() |
297 | | - tmp_dir = tempfile.mkdtemp() |
298 | | - flows_file = rsync.pull_path(tmp_file, tmp_dir) |
299 | | - end = time.time() |
300 | | - df = pd.read_csv(flows_file) |
301 | | - # Filter columns |
302 | | - df = df[list(CSV_HEADER_TO_ANALYZER_HEADER.keys())] |
303 | | - # rename columns |
304 | | - df = df.rename(columns=CSV_HEADER_TO_ANALYZER_HEADER) |
| 305 | + with open(csv_file, mode="w", buffering=1024**2) as f: |
| 306 | + f.write(",".join(header) + "\n") |
| 307 | + for line in process.stdout: |
| 308 | + buffer.append(line + "\n") |
| 309 | + if len(buffer) >= batch_size: |
| 310 | + f.writelines(buffer) |
| 311 | + buffer = [] |
305 | 312 |
|
306 | | - df.to_csv(csv_file, index=False) |
| 313 | + if buffer: |
| 314 | + f.writelines(buffer) |
307 | 315 |
|
308 | | - logging.getLogger().info( |
309 | | - "CSV output downloaded in %.2f seconds.", (end - start) |
310 | | - ) |
| 316 | + end = time.time() |
| 317 | + logging.getLogger().info("CSV output saved in %.2f seconds.", (end - start)) |
0 commit comments