Skip to content

Commit 83025c7

Browse files
fix(web): consistent analytics data
1 parent f90292d commit 83025c7

File tree

2 files changed

+93
-4
lines changed

2 files changed

+93
-4
lines changed

apps/web/scripts/generate-analytics.ts

Lines changed: 84 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,51 @@ async function generateAnalyticsData() {
5959
console.log("🔄 Fetching analytics data...");
6060

6161
const response = await fetch("https://r2.amanv.dev/export.csv");
62-
const csvText = await response.text();
62+
let csvText = await response.text();
63+
64+
// Fix malformed CSV data - if it's all on one line, try to split it properly
65+
if (!csvText.includes("\n") || csvText.split("\n").length < 3) {
66+
console.log("⚠️ Detected malformed CSV data, attempting to fix...");
67+
68+
// Try to split by common patterns that indicate row boundaries
69+
const possibleSplitters = [
70+
/\s{3,}/, // 3 or more spaces
71+
/\s{2,}0{8,}/, // 2+ spaces followed by 8+ zeros (UUID pattern)
72+
/\s{2,}[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}/, // UUID pattern
73+
];
74+
75+
for (const splitter of possibleSplitters) {
76+
const parts = csvText.split(splitter);
77+
if (parts.length > 2) {
78+
console.log(`✅ Fixed CSV using pattern: ${splitter}`);
79+
csvText = parts.join("\n");
80+
break;
81+
}
82+
}
83+
84+
// If still malformed, try manual parsing
85+
if (!csvText.includes("\n") || csvText.split("\n").length < 3) {
86+
console.log("⚠️ CSV still malformed, attempting manual parsing...");
87+
88+
// Extract header and data manually
89+
const headerMatch = csvText.match(/^([^,]+(?:,[^,]+)*)/);
90+
if (headerMatch) {
91+
const header = headerMatch[1];
92+
const dataPart = csvText.substring(header.length);
93+
94+
// Split data by UUID patterns
95+
const dataRows = dataPart
96+
.split(
97+
/\s{2,}[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}/,
98+
)
99+
.filter((row) => row.trim().length > 0)
100+
.map((row) => row.trim());
101+
102+
csvText = header + "\n" + dataRows.join("\n");
103+
console.log(`✅ Manually parsed ${dataRows.length} rows`);
104+
}
105+
}
106+
}
63107

64108
console.log("📊 Processing CSV data...");
65109

@@ -90,16 +134,43 @@ async function generateAnalyticsData() {
90134

91135
Papa.parse<CSVRow>(csvText, {
92136
header: true,
137+
skipEmptyLines: true,
93138
complete: (results) => {
94139
try {
95-
results.data.forEach((row) => {
96-
const timestamp = row["*.timestamp"] || new Date().toISOString();
140+
console.log("📈 Processing", results.data.length, "rows...");
141+
console.log(
142+
"📋 Sample row keys:",
143+
Object.keys(results.data[0] || {}),
144+
);
145+
146+
results.data.forEach((row, index) => {
147+
// Skip rows that don't have essential data
148+
if (!row["*.timestamp"] && !row["timestamp"]) {
149+
if (index < 5) {
150+
console.log(
151+
`⚠️ Skipping row ${index} - no timestamp:`,
152+
Object.keys(row),
153+
);
154+
}
155+
return;
156+
}
157+
158+
const timestamp =
159+
row["*.timestamp"] ||
160+
row["timestamp"] ||
161+
new Date().toISOString();
97162
const date = timestamp.includes("T")
98163
? timestamp.split("T")[0]
99164
: timestamp.split(" ")[0];
100165

101166
// Skip invalid records
102167
if (!date || row["*.properties.platform"] === "unknown") {
168+
if (index < 5) {
169+
console.log(
170+
`⚠️ Skipping row ${index} - invalid date or platform:`,
171+
{ date, platform: row["*.properties.platform"] },
172+
);
173+
}
103174
return;
104175
}
105176

@@ -113,6 +184,7 @@ async function generateAnalyticsData() {
113184
const monthKey = `${timestampDate.getFullYear()}-${String(timestampDate.getMonth() + 1).padStart(2, "0")}`;
114185
monthlyCounts[monthKey] = (monthlyCounts[monthKey] || 0) + 1;
115186

187+
// Use UTC hours for consistent timezone handling
116188
const hour = timestampDate.getUTCHours();
117189
hourlyCounts[hour] = (hourlyCounts[hour] || 0) + 1;
118190
}
@@ -250,6 +322,15 @@ async function generateAnalyticsData() {
250322
dbORMComboCounts[combo] = (dbORMComboCounts[combo] || 0) + 1;
251323
}
252324
});
325+
326+
console.log(
327+
"✅ Successfully processed",
328+
totalRecords,
329+
"valid records",
330+
);
331+
console.log("📊 Platform distribution:", platformCounts);
332+
console.log("📊 Backend distribution:", backendCounts);
333+
console.log("📊 Database distribution:", databaseCounts);
253334
} catch (error) {
254335
console.error("Error parsing CSV:", error);
255336
}

apps/web/src/app/(home)/analytics/page.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@ const platformConfig = {
9393
label: "Windows",
9494
color: "hsl(var(--chart-3))",
9595
},
96+
android: {
97+
label: "Android", // there are 2 records with this platform :)
98+
color: "hsl(var(--chart-4))",
99+
},
96100
} satisfies ChartConfig;
97101

98102
const packageManagerConfig = {
@@ -946,7 +950,11 @@ export default function AnalyticsPage() {
946950
? "hsl(var(--chart-1))"
947951
: entry.name === "linux"
948952
? "hsl(var(--chart-2))"
949-
: "hsl(var(--chart-3))"
953+
: entry.name === "win32"
954+
? "hsl(var(--chart-3))"
955+
: entry.name === "android"
956+
? "hsl(var(--chart-4))"
957+
: "hsl(var(--chart-5))"
950958
}
951959
/>
952960
))}

0 commit comments

Comments
 (0)