Olympus Docs
InternalsHera

Hera, analytics

PKCE analytics, social-login tracking, MFA challenge stats

Hera emits analytics events for several flow-related decisions. They're collected as stdout JSON (audit log shape) and consumable by your log shipper.

Events emitted

PKCE flow events

{"type":"audit","event":"pkce_authorize","client_id":"...","domain":"ciam","ts":"..."}
{"type":"audit","event":"pkce_token_exchange","client_id":"...","domain":"ciam","ts":"..."}
{"type":"audit","event":"pkce_failed","reason":"verifier_mismatch","client_id":"...","ts":"..."}

Useful for:

  • Tracking PKCE adoption per client.
  • Detecting clients that are misimplementing PKCE.
  • Validating that verify-prod-config.yml's PKCE-enforcement is actually firing.

Social login events

{"type":"audit","event":"social_login_initiated","provider":"google","domain":"ciam","ts":"..."}
{"type":"audit","event":"social_login_completed","provider":"google","first_login":true,"domain":"ciam","ts":"..."}
{"type":"audit","event":"social_link_initiated","provider":"google","domain":"ciam","ts":"..."}

Useful for:

  • Per-provider login counts.
  • First-time vs returning per provider.
  • Adoption tracking for new social providers.

MFA events

{"type":"audit","event":"mfa_challenge_displayed","method":"totp","domain":"ciam","ts":"..."}
{"type":"audit","event":"mfa_challenge_succeeded","method":"totp","domain":"ciam","ts":"..."}
{"type":"audit","event":"mfa_challenge_failed","method":"totp","domain":"ciam","ts":"..."}

Useful for:

  • Step-up frequency.
  • MFA method preference.
  • Failure rate per method (high TOTP fail = users have clock skew or typos).

Captcha events

{"type":"audit","event":"captcha_displayed","flow":"login","domain":"ciam","ts":"..."}
{"type":"audit","event":"captcha_succeeded","flow":"login","domain":"ciam","ts":"..."}
{"type":"audit","event":"captcha_failed","flow":"login","reason":"timeout","domain":"ciam","ts":"..."}

Useful for:

  • Captcha rate.
  • False-positive rate (challenges shown to real users).

Breach-check events

{"type":"audit","event":"breach_check_passed","domain":"ciam","ts":"..."}
{"type":"audit","event":"breach_check_failed","reason":"in_hibp","domain":"ciam","ts":"..."}

Useful for:

  • How many users pick weak passwords (need to be redirected).

Why stdout JSON

Three reasons:

  1. No external dependency for Hera (no metrics client to configure).
  2. Standard log shipper integration.
  3. Audit-grade, every event is timestamped, structured, parseable.

Where to consume

Operators' choice of log aggregator:

  • Loki + Grafana: parse JSON, build dashboards.
  • CloudWatch Insights: query JSON natively.
  • Datadog / Honeycomb: same.
  • Postgres: log shipper writes to a table; Athena reads for the analytics dashboard.

Athena's /analytics page reads from the security_audit table (which recordSecurityAudit from the SDK writes to). If you also want to surface Hera's per-flow analytics there, ship Hera's stdout to the same table via an external log shipper.

PII handling

Hera's analytics events deliberately exclude:

  • Identity ID (use the security audit log for that, where access is gated).
  • Email address.
  • IP address (Caddy log has it; Hera doesn't echo).

This makes the events safe for less-restricted log destinations.

Sampling

Hera doesn't sample, every event is emitted. For high-traffic deployments where event volume becomes a concern, post-process at the log shipper. The cost of sampling at emission time is losing visibility for low-volume flows (which is exactly when you want full data).

Adding a new event

  1. Decide the event name (<noun>_<verb>).
  2. Define the payload shape, add to hera/src/lib/events.ts.
  3. Emit at the relevant code path:
    import { emitEvent } from "@/lib/events";
    emitEvent({ event: "new_thing", foo: "bar" });
  4. Document the event in this page.

On this page