Summary
Add optional PostHog support to DocSpec so that conversion events and usage patterns can be tracked when enabled via environment variable at runtime.
Motivation
When DocSpec is used in production services, understanding usage patterns — which formats are converted most, conversion durations, document sizes, failure rates by format — helps prioritize development effort. PostHog provides this product analytics layer.
PostHog must be off by default and enabled only when explicitly configured.
Proposal
Approach: Runtime toggle via environment variable
Since DocSpec ships as a Burrito native binary, all dependencies are compiled into the release. Compile-time optional: true doesn't help — the binary includes PostHog either way. Instead, the toggle is purely runtime:
-
Add posthog as a regular dependency in mix.exs:
-
Create a wrapper module gated by an env var:
defmodule DocSpec.Analytics do
@moduledoc "Captures analytics events via PostHog when enabled, no-ops otherwise."
def capture(event, properties \\ %{}) do
if enabled?() do
Posthog.capture(event, properties)
else
:ok
end
end
defp enabled? do
# Truthy when DOCSPEC_POSTHOG_KEY is set to a non-empty value
case System.get_env("DOCSPEC_POSTHOG_KEY") do
nil -> false
"" -> false
_key -> true
end
end
end
-
PostHog API key and host are configured via environment variables:
DOCSPEC_POSTHOG_KEY — API key. When unset or empty, all analytics calls are no-ops.
DOCSPEC_POSTHOG_HOST — Optional. PostHog instance URL (defaults to https://app.posthog.com).
-
Instrument key conversion paths with lightweight events:
conversion_started — format pair (e.g. docx → blocknote), document size
conversion_completed — duration, output size
conversion_failed — format pair, error type (no PII)
validation_completed — finding count by severity
What this does NOT do
- Does not enable PostHog by default — requires explicit env var
- Does not change any return types or public API
- Does not capture document content or PII — only structural metadata
- Does not block conversion on analytics failures — fire-and-forget
Co-existence with Sentry (#24)
Both PostHog and Sentry must work independently and together. A consumer should be able to enable either, both, or neither. The two modules (DocSpec.Analytics for PostHog, DocSpec.ErrorReporter for Sentry) are intentionally separate — they serve different purposes (product analytics vs error tracking), have non-overlapping interfaces, and each checks its own env var at runtime. No shared abstraction needed; keeping them independent ensures enabling one never affects the other.
When both are active, a failed conversion would:
- Report the error to Sentry (via
DocSpec.ErrorReporter) — for debugging
- Emit a
conversion_failed event to PostHog (via DocSpec.Analytics) — for trend tracking
These happen independently with no coupling between them.
Usage
# Analytics disabled (default)
docspec convert -i doc.docx -o out.html
# Analytics enabled
DOCSPEC_POSTHOG_KEY=phc_abc123 docspec convert -i doc.docx -o out.html
# With self-hosted PostHog
DOCSPEC_POSTHOG_KEY=phc_abc123 DOCSPEC_POSTHOG_HOST=https://posthog.internal.example.com docspec convert -i doc.docx -o out.html
Related
Files to modify
mix.exs (add dep)
- New:
lib/docspec/analytics.ex
- Reader/Writer modules (instrument conversion paths)
Summary
Add optional PostHog support to DocSpec so that conversion events and usage patterns can be tracked when enabled via environment variable at runtime.
Motivation
When DocSpec is used in production services, understanding usage patterns — which formats are converted most, conversion durations, document sizes, failure rates by format — helps prioritize development effort. PostHog provides this product analytics layer.
PostHog must be off by default and enabled only when explicitly configured.
Proposal
Approach: Runtime toggle via environment variable
Since DocSpec ships as a Burrito native binary, all dependencies are compiled into the release. Compile-time
optional: truedoesn't help — the binary includes PostHog either way. Instead, the toggle is purely runtime:Add
posthogas a regular dependency inmix.exs:Create a wrapper module gated by an env var:
PostHog API key and host are configured via environment variables:
DOCSPEC_POSTHOG_KEY— API key. When unset or empty, all analytics calls are no-ops.DOCSPEC_POSTHOG_HOST— Optional. PostHog instance URL (defaults tohttps://app.posthog.com).Instrument key conversion paths with lightweight events:
conversion_started— format pair (e.g.docx → blocknote), document sizeconversion_completed— duration, output sizeconversion_failed— format pair, error type (no PII)validation_completed— finding count by severityWhat this does NOT do
Co-existence with Sentry (#24)
Both PostHog and Sentry must work independently and together. A consumer should be able to enable either, both, or neither. The two modules (
DocSpec.Analyticsfor PostHog,DocSpec.ErrorReporterfor Sentry) are intentionally separate — they serve different purposes (product analytics vs error tracking), have non-overlapping interfaces, and each checks its own env var at runtime. No shared abstraction needed; keeping them independent ensures enabling one never affects the other.When both are active, a failed conversion would:
DocSpec.ErrorReporter) — for debuggingconversion_failedevent to PostHog (viaDocSpec.Analytics) — for trend trackingThese happen independently with no coupling between them.
Usage
Related
Files to modify
mix.exs(add dep)lib/docspec/analytics.ex