Add build info metric and diagnostic logging for Garmin sync
All checks were successful
Deploy / deploy (push) Successful in 1m44s
All checks were successful
Deploy / deploy (push) Successful in 1m44s
- Add phaseflow_build_info metric with version and commit labels - Inject GIT_COMMIT env var at build time via next.config.ts - Add logging to all Garmin fetch functions (HRV, body battery, intensity) - Log API response status codes, actual data values, and errors This enables verifying which build is deployed and diagnosing silent failures where Garmin API returns errors but sync reports success. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
// ABOUTME: Garmin Connect API client using stored OAuth tokens.
|
||||
// ABOUTME: Fetches body battery, HRV, and intensity minutes from Garmin.
|
||||
|
||||
import { logger } from "@/lib/logger";
|
||||
import type { GarminTokens, HrvStatus } from "@/types";
|
||||
|
||||
const GARMIN_BASE_URL = "https://connect.garmin.com/modern/proxy";
|
||||
@@ -63,6 +65,10 @@ export async function fetchHrvStatus(
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
logger.warn(
|
||||
{ status: response.status, endpoint: "hrv-service" },
|
||||
"Garmin HRV API error",
|
||||
);
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
@@ -70,13 +76,23 @@ export async function fetchHrvStatus(
|
||||
const status = data?.hrvSummary?.status;
|
||||
|
||||
if (status === "BALANCED") {
|
||||
logger.info({ status: "BALANCED" }, "Garmin HRV data received");
|
||||
return "Balanced";
|
||||
}
|
||||
if (status === "UNBALANCED") {
|
||||
logger.info({ status: "UNBALANCED" }, "Garmin HRV data received");
|
||||
return "Unbalanced";
|
||||
}
|
||||
logger.info(
|
||||
{ rawStatus: status, hasData: !!data?.hrvSummary },
|
||||
"Garmin HRV returned unknown status",
|
||||
);
|
||||
return "Unknown";
|
||||
} catch {
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
{ err: error, endpoint: "hrv-service" },
|
||||
"Garmin HRV fetch failed",
|
||||
);
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
@@ -97,6 +113,10 @@ export async function fetchBodyBattery(
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
logger.warn(
|
||||
{ status: response.status, endpoint: "bodyBattery" },
|
||||
"Garmin body battery API error",
|
||||
);
|
||||
return { current: null, yesterdayLow: null };
|
||||
}
|
||||
|
||||
@@ -108,8 +128,22 @@ export async function fetchBodyBattery(
|
||||
const yesterdayStats = data?.bodyBatteryStatList?.[0];
|
||||
const yesterdayLow = yesterdayStats?.min ?? null;
|
||||
|
||||
logger.info(
|
||||
{
|
||||
current,
|
||||
yesterdayLow,
|
||||
hasCurrentData: !!currentData,
|
||||
hasYesterdayData: !!yesterdayStats,
|
||||
},
|
||||
"Garmin body battery data received",
|
||||
);
|
||||
|
||||
return { current, yesterdayLow };
|
||||
} catch {
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
{ err: error, endpoint: "bodyBattery" },
|
||||
"Garmin body battery fetch failed",
|
||||
);
|
||||
return { current: null, yesterdayLow: null };
|
||||
}
|
||||
}
|
||||
@@ -129,6 +163,10 @@ export async function fetchIntensityMinutes(
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
logger.warn(
|
||||
{ status: response.status, endpoint: "fitnessstats" },
|
||||
"Garmin intensity minutes API error",
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -136,14 +174,28 @@ export async function fetchIntensityMinutes(
|
||||
const weeklyTotal = data?.weeklyTotal;
|
||||
|
||||
if (!weeklyTotal) {
|
||||
logger.info(
|
||||
{ hasWeeklyTotal: false },
|
||||
"Garmin intensity minutes: no weekly data",
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const moderate = weeklyTotal.moderateIntensityMinutes ?? 0;
|
||||
const vigorous = weeklyTotal.vigorousIntensityMinutes ?? 0;
|
||||
const total = moderate + vigorous;
|
||||
|
||||
return moderate + vigorous;
|
||||
} catch {
|
||||
logger.info(
|
||||
{ moderate, vigorous, total },
|
||||
"Garmin intensity minutes data received",
|
||||
);
|
||||
|
||||
return total;
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
{ err: error, endpoint: "fitnessstats" },
|
||||
"Garmin intensity minutes fetch failed",
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user