Add comprehensive console logging for Wren API calls
All checks were successful
Build and Push Docker Images / docker (push) Successful in 48s

- Added detailed request/response logging for getPortfolios()
- Added detailed request/response logging for createOffsetOrder()
- Logs include timestamps, durations, request parameters, and response details
- Visual indicators: 🔵 for info,  for success,  for errors, ⚠️ for warnings
- Helps track API calls and debug issues in production console logs

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Matt 2025-10-30 14:49:15 +01:00
parent 8b92e1673c
commit 0b2d8685d8

View File

@ -108,19 +108,39 @@ const logError = (error: unknown) => {
};
export async function getPortfolios(): Promise<Portfolio[]> {
const startTime = Date.now();
console.log('🔵 [WREN API] ========================================');
console.log('🔵 [WREN API] GET /portfolios - Request initiated');
console.log('🔵 [WREN API] Timestamp:', new Date().toISOString());
try {
if (!config.wrenApiKey) {
console.warn('⚠️ [WREN API] No API token configured, using fallback portfolio');
logger.warn('[wrenClient] No Wren API token configured, using fallback portfolio');
return [DEFAULT_PORTFOLIO];
}
console.log('🔵 [WREN API] API Key:', config.wrenApiKey ? '********' + config.wrenApiKey.slice(-4) : 'MISSING');
logger.log('[wrenClient] Getting portfolios with token:', config.wrenApiKey ? '********' + config.wrenApiKey.slice(-4) : 'MISSING');
const api = createApiClient();
// Removed the /api prefix to match the working example
console.log('🔵 [WREN API] Making request to: https://www.wren.co/api/portfolios');
const response = await api.get('/portfolios');
const duration = Date.now() - startTime;
console.log('✅ [WREN API] GET /portfolios - Success');
console.log('✅ [WREN API] Status:', response.status);
console.log('✅ [WREN API] Duration:', duration + 'ms');
console.log('✅ [WREN API] Portfolios returned:', response.data?.portfolios?.length || 0);
if (response.data?.portfolios?.length > 0) {
console.log('✅ [WREN API] Portfolio IDs:', response.data.portfolios.map((p: any) => `#${p.id} (${p.name})`).join(', '));
}
console.log('🔵 [WREN API] ========================================');
if (!response.data?.portfolios?.length) {
console.warn('⚠️ [WREN API] No portfolios in response, using fallback');
logger.warn('[wrenClient] No portfolios returned from API, using fallback');
return [DEFAULT_PORTFOLIO];
}
@ -180,6 +200,20 @@ export async function getPortfolios(): Promise<Portfolio[]> {
};
});
} catch (error) {
const duration = Date.now() - startTime;
console.error('❌ [WREN API] GET /portfolios - Failed');
console.error('❌ [WREN API] Duration:', duration + 'ms');
if (axios.isAxiosError(error)) {
console.error('❌ [WREN API] Status:', error.response?.status || 'No response');
console.error('❌ [WREN API] Status Text:', error.response?.statusText || 'N/A');
console.error('❌ [WREN API] Error Data:', JSON.stringify(error.response?.data, null, 2));
console.error('❌ [WREN API] Request URL:', error.config?.url);
} else {
console.error('❌ [WREN API] Error:', error instanceof Error ? error.message : String(error));
}
console.log('🔵 [WREN API] ========================================');
logError(error);
logger.warn('[wrenClient] Failed to fetch portfolios from API, using fallback');
return [DEFAULT_PORTFOLIO];
@ -191,15 +225,26 @@ export async function createOffsetOrder(
tons: number,
dryRun: boolean = false
): Promise<OffsetOrder> {
const startTime = Date.now();
console.log('🔵 [WREN API] ========================================');
console.log('🔵 [WREN API] POST /offset-orders - Request initiated');
console.log('🔵 [WREN API] Timestamp:', new Date().toISOString());
console.log('🔵 [WREN API] Parameters:', JSON.stringify({ portfolioId, tons, dryRun }, null, 2));
try {
if (!config.wrenApiKey) {
console.error('❌ [WREN API] Cannot create order - missing API token');
console.error('[wrenClient] Cannot create order - missing API token');
throw new Error('Carbon offset service is currently unavailable. Please contact support.');
}
console.log('🔵 [WREN API] API Key:', config.wrenApiKey ? '********' + config.wrenApiKey.slice(-4) : 'MISSING');
logger.log(`[wrenClient] Creating offset order: portfolio=${portfolioId}, tons=${tons}, dryRun=${dryRun}`);
const api = createApiClient();
console.log('🔵 [WREN API] Making request to: https://www.wren.co/api/offset-orders');
console.log('🔵 [WREN API] Request payload:', JSON.stringify({ portfolioId, tons, dryRun }, null, 2));
// Removed the /api prefix to match the working example
const response = await api.post('/offset-orders', {
// Using exactly the format shown in the API tutorial
@ -208,21 +253,37 @@ export async function createOffsetOrder(
dryRun // Use the provided dryRun parameter
});
const duration = Date.now() - startTime;
console.log('✅ [WREN API] POST /offset-orders - Success');
console.log('✅ [WREN API] Status:', response.status);
console.log('✅ [WREN API] Duration:', duration + 'ms');
// Add detailed response logging
logger.log('[wrenClient] Offset order response:',
response.status,
response.data ? 'has data' : 'no data');
if (response.status === 400) {
console.error('❌ [WREN API] Bad request - Status 400');
console.error('❌ [WREN API] Bad request details:', response.data);
console.error('[wrenClient] Bad request details:', response.data);
throw new Error(`Failed to create offset order: ${JSON.stringify(response.data)}`);
}
const order = response.data;
if (!order) {
console.error('❌ [WREN API] Empty response received');
throw new Error('Empty response received from offset order API');
}
console.log('✅ [WREN API] Order ID:', order.id || 'N/A');
console.log('✅ [WREN API] Amount Charged:', order.amountCharged ? `$${order.amountCharged}` : 'N/A');
console.log('✅ [WREN API] Tons:', order.tons || 'N/A');
console.log('✅ [WREN API] Status:', order.status || 'N/A');
console.log('✅ [WREN API] Dry Run:', order.dryRun !== undefined ? order.dryRun : 'N/A');
console.log('🔵 [WREN API] ========================================')
// Log to help diagnose issues
logger.log('[wrenClient] Order data keys:', Object.keys(order).join(', '));
if (order.portfolio) {
@ -267,11 +328,23 @@ export async function createOffsetOrder(
dryRun: getSafeProp(order, 'dryRun', true)
};
} catch (error: unknown) {
const duration = Date.now() - startTime;
console.error('❌ [WREN API] POST /offset-orders - Failed');
console.error('❌ [WREN API] Duration:', duration + 'ms');
logError(error);
if (axios.isAxiosError(error)) {
const axiosError = error as AxiosError;
console.error('❌ [WREN API] Status:', axiosError.response?.status || 'No response');
console.error('❌ [WREN API] Status Text:', axiosError.response?.statusText || 'N/A');
console.error('❌ [WREN API] Error Data:', JSON.stringify(axiosError.response?.data, null, 2));
console.error('❌ [WREN API] Request URL:', axiosError.config?.url);
console.error('❌ [WREN API] Request Method:', axiosError.config?.method?.toUpperCase());
console.error('❌ [WREN API] Request Data:', JSON.stringify(axiosError.config?.data, null, 2));
console.log('🔵 [WREN API] ========================================');
console.error('[wrenClient] Axios error details:', {
status: axiosError.response?.status,
statusText: axiosError.response?.statusText,
@ -301,6 +374,9 @@ export async function createOffsetOrder(
if (axiosError.response.status === 401) {
throw new Error('Carbon offset service authentication failed. Please check your API token.');
}
} else {
console.error('❌ [WREN API] Error:', error instanceof Error ? error.message : String(error));
console.log('🔵 [WREN API] ========================================');
}
throw new Error('Failed to create offset order. Please try again.');