This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
FLORES (FortiGate Log Reference Scraper) extracts FortiGate log field documentation from Fortinet's official docs site and produces Elasticsearch-ready field definitions.
Two scripts, run from the repo root:
# Step 1: Scrape Fortinet docs for configured versions
python3 fortigate_scraper.py
# Step 2: Generate changelogs, field matrices, and consolidated field CSVs
python3 generate_changelog.py # all outputs
python3 generate_changelog.py --changelog # per-minor CHANGELOG.md only
python3 generate_changelog.py --matrices # per-minor field matrix CSVs only
python3 generate_changelog.py --fields # per-major consolidated field CSVs only
python3 generate_changelog.py --index # root INDEX.md + per-major {major}/INDEX.md
# Step 3: Generate Elasticsearch component templates (lives in fortinet-2-elasticsearch)
# python3 ../fortinet-2-elasticsearch/datasets/Fortinet/elasticsearch_mappings.pyfortigate_scraper_config.yaml controls the scraper:
versions— list of FortiOS versions to scrape (format:"X.Y.Z")settings.base_delay— seconds between HTTP requests (default:1.0)settings.max_retries— additional attempts per URL after an error (default:3;0= no retries)settings.retry_backoff— exponential backoff multiplier:base_delay × (backoff ^ attempt)(default:2.0)settings.concurrency— max parallel LOGID fetches per version viaasyncio.Semaphore(default:5)settings.force_rescrape— re-scrape versions that already have output (default:false)settings.dry_run— log which versions would be scraped without fetching (default:false)settings.output_dir— root output directory (default:".", i.e. repo root)
<major>/ # e.g., 7.6/
├── <minor>/ # e.g., 7.6.4/
│ ├── LOGID/ # one CSV per LOGID
│ │ └── <LOGID_description>.csv
│ ├── CHANGELOG.md # intra-version conflicts + inter-version diffs
│ ├── traffic_matrix.csv # field × category occurrence counts
│ ├── event_matrix.csv
│ └── utm_matrix.csv
└── fields/
├── traffic_fields.csv # consolidated across all minor versions
├── event_fields.csv
├── utm_fields.csv
└── action_descriptions.csv # UTM action field variants (one column per subtype)
Log type classification:
Traffic—Type == 'Traffic', subtype fromCategorycolumnEvent—Type == 'Event', subtype fromCategorycolumnUTM— everything else (including GTP), subtype fromTypecolumn;actionfield written to a separateaction_descriptions.csvbecause its values differ significantly per subtype
Description consolidation: When a field has the same meaning across subtypes, a single plain description is used. When meanings differ, each variant is labeled subtype: description and joined with \n\n.
Scraper resumes at LOGID granularity — skips individual CSVs that already exist unless force_rescrape: true.
All new code must follow the conventions established in generate_changelog.py:
from __future__ import annotationsat the top of every script- Type hints on all functions — use built-in generics (
list[str],dict[str, str],X | None); notypingmodule imports pathlib.Pathfor all file operations — noos.path,os.makedirs, orglob.glob; usePath.open(),Path.read_text(),Path.write_text()rather than builtinopen()with string paths- Async HTTP with
httpx.AsyncClient— one shared client created inrun()as a context manager and passed to callers; all network functions areasync def; concurrency bounded per version byasyncio.Semaphore(self.concurrency). NeverrequestsorThreadPoolExecutor - Logging via
logging.getLogger(__name__)in every module — neverprint().logging.basicConfigis called only inmain(), never at module level - Dataclasses for structured results — use
@dataclassinstead of raw dicts or untyped tuples - Vectorized pandas — no
iterrows(); usegroupby, boolean indexing, andmapwith scalar functions - No defensive
.copy()unless an in-place mutation follows - One-line docstrings —
Args:/Returns:blocks that restate the signature are noise; delete them - Small, single-responsibility functions — separate I/O from data transformation
For internal design, data flow diagrams, and full method documentation, see DEVELOPERS_GUIDE.md.
Update it afeter every code change or refactoring.
pip install httpx[http2] beautifulsoup4 pandas lxml pyyaml