How data moves

A log line, a visit, a beacon report and a panel page, step by step through the classes.

The path a log line, a visit, a beacon report and a panel page take through the Loghound code, plus where configuration, state and the two indexes live. Written for a developer who has never seen the project.

01 · How data moves through the code

A log line, into the hits index

  1. Tail reads the new line and remembers its position in State.
  2. LogFormat and Parser turn it into a request with named fields; lines that do not parse are sampled to a file.
  3. Enrich\Geo, Enrich\Asn and Score\Attacks add context; Exclusions and AttackPatterns apply the operator's rules.
  4. Sessionizer attaches the request to a visit (same network and browser, 30 minutes of inactivity closes it).
  5. Solr::addDocs() writes the batch into the hits index, after Quota confirms there is room.

A visit, into the sessions index

  1. loghound-score finds visits that went idle.
  2. Beacon::mergeIntoSession() adds what the browser reported.
  3. Score\Signals gathers the evidence and Score\Rules computes the score, the verdict and its reasons.
  4. The visit document, and the daily rollups, are written into the sessions index.

A beacon hit

  1. b.js in the visitor's browser posts to collect.php.
  2. The collector checks the signed token, size, origin and allowed hosts, rate-limits, stages the row in SQLite, and always answers 204. It never touches Solr.
  3. The next scorer run merges the staged row into its visit.

A panel page

  1. public/index.php sets security headers, loads the configuration, sends first-time visitors to the installer, and checks sign-in and CSRF.
  2. The view named in ?v= is looked up in Layout::routes(); its controller draws the page frame without querying Solr.
  3. Each card then asks the server for its own data (?api=); the controller answers through Gateway, Cache and Solr, so one slow card never blocks the others.
  4. On the browser side, public/assets/js/app.js loads the matching module from public/assets/js/views/, which fills its cards with loadCard() from core.js.
02 · Configuration, state and secrets
  • The configuration is a PHP array in config/loghound.php, mode 0640, written by Config::save(). Its sections are documented in config/loghound.example.php and on settings.
  • Secrets — the Opensolr API key, the beacon secret, the IP salt, the panel password hash and the two-factor secret — live in that file; sign-in state lives in files under var/ with mode 0600. None of them is ever committed.
  • Working state is var/state.db (SQLite) and a few status files, also under var/.
03 · The two indexes

solr/hits/conf holds one document per request; solr/sessions/conf one per visit plus daily rollups. Every field is explained on the Solr schema. The schema rules are strict: fields are not stored unless needed, string fields carry no norms, one full-text catchall field (on by default, ingest.catchall) feeds the free-text search, and an undeclared field is silently ignored.

  1. Change solr/hits/conf/schema.xml or solr/sessions/conf/schema.xml.
  2. Run bin/loghound-schema --check to see what differs from the live index.
  3. Run bin/loghound-schema --apply to upload it. Operators do the same after upgrading.

For developers

Loghound is open source and MIT licensed. Questions about the Opensolr half — the account, the indexes, the plan — go to opensolr.com/contact; questions about the software itself belong on GitHub.

Loghound Documentation