Overview
The analytics system consists of:- Analytics Sink component - Indexes workflow output data into OpenSearch
- Results output port - Structured findings from security scanners
- OpenSearch storage - Time-series index for querying and visualization
- View Analytics button - Quick access to filtered dashboards
Architecture
Each scanner outputs findings through itsresults port, which connects to the Analytics Sink. The sink indexes each finding as a separate document with workflow metadata.
Document Structure
Indexed documents follow this structure:Field Categories
Nested objects in findings are automatically serialized to JSON strings to prevent OpenSearch field explosion (1000 field limit).
shipsec context fields
The Analytics Sink automatically adds workflow context under the shipsec namespace:
Finding Hash for Deduplication
Thefinding_hash is a stable 16-character identifier that enables tracking findings across workflow runs.
Purpose
- New vs recurring: Determine if a finding appeared before
- First-seen / last-seen: Track when findings were first and last detected
- Resolution tracking: Findings that stop appearing may be resolved
- Deduplication: Remove duplicates in dashboards across runs
Generation
Each scanner generates the hash from key identifying fields:
Fields are normalized (lowercase, trimmed) and hashed with SHA-256, truncated to 16 hex characters.
Querying Data
Basic Queries (KQL)
Tracking Findings Over Time
Common Aggregations
Setting Up OpenSearch
Environment Variables
Set these in yourworker/.env:
frontend/.env:
Docker Compose
The infrastructure stack includes OpenSearch and OpenSearch Dashboards:Index Pattern
After indexing data, create an index pattern in OpenSearch Dashboards:- Go to Dashboards Management > Index Patterns
- Create pattern:
security-findings-* - Select
@timestampas the time field - Click Create index pattern
Analytics API Limits
The analytics query API enforces sane bounds to protect OpenSearch:sizemust be a non-negative integer and is capped at 1000frommust be a non-negative integer and is capped at 10000
400 Bad Request.
Analytics Settings Updates
The analytics settings API supports partial updates:analyticsRetentionDaysis optionalsubscriptionTieris optional
Using Analytics Sink
Basic Workflow
- Add a security scanner to your workflow (Nuclei, TruffleHog, etc.)
- Add an Analytics Sink component
- Connect the scanner’s
resultsport to the Analytics Sink’sdatainput - Run the workflow
Component Parameters
Fire-and-Forget Mode
By default, Analytics Sink operates in fire-and-forget mode:- Indexing errors are logged but don’t stop the workflow
- Useful for non-critical analytics that shouldn’t block security scans
- Enable “Fail on Error” for strict indexing requirements
View Analytics Button
The workflow builder includes a “View Analytics” button that opens OpenSearch Dashboards with pre-filtered data:- When a run is selected: Filters by
shipsec.run_id - When no run is selected: Filters by
shipsec.workflow_id - Time range: Last 7 days
VITE_OPENSEARCH_DASHBOARDS_URL is configured.
Index Naming
Indexes follow the pattern:security-findings-{orgId}-{suffix}
Example:
security-findings-org_abc123-2025.01.21
Building Dashboards
Recommended Visualizations
Alert Examples
Troubleshooting
Data not appearing in OpenSearch
- Check worker logs for
[OpenSearchIndexer]messages - Verify
OPENSEARCH_URLis set in worker environment - Ensure Analytics Sink is connected to a
resultsport - Check if OpenSearch is running:
curl http://localhost:9200/_cluster/health
Field mapping errors
If you see “Limit of total fields [1000] has been exceeded”:- Delete the problematic index:
curl -X DELETE "http://localhost:9200/security-findings-*" - Re-run the workflow (new index will use correct schema)
shipsec fields not visible
- Fields starting with
_are hidden in OpenSearch UI - Ensure you’re using
shipsec.*(no underscore prefix) - Refresh the index pattern in Dashboards Management
pm2 not loading environment variables
pm2’senv_file doesn’t auto-inject variables. The worker uses a custom loadWorkerEnv() function in pm2.config.cjs. After changing worker/.env:
Best Practices
Do
- Connect
resultsports (notrawOutput) to Analytics Sink - Use meaningful index suffixes for organization
- Monitor index size and implement retention policies
- Create saved searches for common queries
Don’t
- Don’t connect deeply nested JSON (causes field explosion)
- Don’t rely on analytics for critical workflow logic
- Don’t store PII or secrets in indexed findings
Component Author Guidelines
If you’re building a security scanner component, see Analytics Output Port for implementation details on adding theresults output port.
Related
- Component Development - Building scanner components
- Core Components - Analytics Sink reference
- Analytics (PostHog) - Product analytics (different system)