Analytics Engine
The Analytics Engine is the core of GitHub Wrapped, processing raw GitHub data into meaningful insights and visualizations. It’s implemented inlib/analytics.ts as the AnalyticsEngine class.
Architecture
The engine uses a service-based architecture:GitHubService, allowing the analytics engine to focus purely on data transformation and calculation.
Commit Pattern Analysis
The engine provides sophisticated commit pattern analysis to reveal development workflows.By Month
Tracks commit distribution across calendar months:lib/analytics.ts:501-555):
- Parses commit timestamps using
date-fns - Groups commits by month name
- Calculates busiest month by comparing counts
By Day of Week
Identifies which days of the week are most active:- Distinguish between work and personal projects
- Identify weekend warriors
- Understand team work schedules
By Hour
Reveals productivity patterns throughout the day:- Uses
getHours()fromdate-fnsto extract hour (0-23) - Builds histogram of commit activity
- Enables “Night Owl” detection (commits after 22:00)
Average Per Day
Calculates the daily commit rate:Contributor Analysis
The engine analyzes contributors from multiple perspectives.Top by Commits
Ranks contributors by total commit count:/repos/{owner}/{repo}/contributors endpoint
Top by Lines Changed
Ranks by total lines added + removed:lib/analytics.ts:557-654):
- Filters commits to top 5 contributors only
- Samples maximum 20 commits to reduce API calls
- Falls back to estimated values if stats unavailable
- Uses
Promise.allSettled()for resilient error handling
New Contributors
Estimates newcomers to the project:Language Statistics
Calculation Method
lib/analytics.ts:780-796):
-
Sum Total Bytes
-
Calculate Percentages
-
Sort and Limit
- Sort by bytes (descending)
- Return top 10 languages
Output Format
Community Growth Metrics
Tracks repository growth across multiple dimensions:Stars Gained
Ideal: Fetch stargazers with timestamps and count those in range Fallback: If API limit reached, estimate as 10% of total starsForks Gained
Counts forks created during the year:Issues and PRs
Direct counts from GitHub API:- Issues opened: Filter by
created_atin range - Issues closed: Filter by
closed_atin range - PRs merged: Filter by
merged_atin range
Monthly Snapshots
Provides granular month-by-month tracking.Data Structure
Generation Process
Implementation (lib/analytics.ts:656-778):
-
Initialize Monthly Map
- Create entry for each month (Jan-Dec or Jan-current month)
- Initialize all counters to 0
-
Process Commits
- Parse commit timestamp
- Verify it’s in the target year
- Extract month label (“Jan”, “Feb”, etc.)
- Increment commit counter
- Track unique contributor usernames
-
Process PRs, Issues, Stars, Forks
- Similar process for each data type
- Use appropriate date field:
- PRs:
merged_at(orclosed_at,created_atas fallback) - Issues opened:
created_at - Issues closed:
closed_at - Stars:
starred_at - Forks:
created_at
- PRs:
-
Build Output Array
- Convert map to sorted array
- Include contributor count (Set size)
Monthly snapshots enable trend visualization, helping users identify growth spurts, quiet periods, and seasonal patterns.
Performance Optimizations
Parallel Data Fetching
The engine fetches all required data in parallel:Rate Limit Protection
Sampling
Only samples 20 commits when calculating line changes to reduce API calls
Delays
Includes 100ms delays between commit stat requests
Repository Limit
User wrapped scans max 15 repositories to prevent timeout
Fallback Values
Uses estimates when API limits are hit
Caching Strategy
All wrapped data is cached in Redis:- TTL: 24 hours
- Key pattern:
wrapped:{type}:v2:{identifier}:{year} - Benefit: Subsequent views are instant
Error Handling
The engine uses resilient error handling:- Partial failures don’t crash generation
- Users get best-effort results
- Errors are logged for debugging
Extensibility
TheAnalyticsEngine is designed for extension:
- New metrics: Add new calculation methods
- Custom date ranges: Use
generateWrappedRange()orgenerateUserWrappedRange() - Monthly reports: Use
generateUserWrappedForMonth()