Enhance myTischtennis URL controller with improved error handling and logging

Updated MyTischtennisUrlController to include detailed error messages for missing user IDs and team configurations. Added logging for session details and automatic login attempts, improving debugging capabilities. Enhanced request logging for API calls to myTischtennis, ensuring all requests are logged, even in case of errors. Updated requestLoggingMiddleware to only log myTischtennis-related requests, streamlining log management. Improved validation checks in autoFetchMatchResultsService for team and league data integrity.
This commit is contained in:
Torsten Schulz (local)
2025-10-29 18:07:43 +01:00
parent c2b8656783
commit 89329607dc
5 changed files with 295 additions and 50 deletions

View File

@@ -102,7 +102,13 @@ class ApiLogService {
}
if (path) {
where.path = { [Op.like]: `%${path}%` };
// Handle "NOT:" prefix for excluding paths (e.g., "NOT:/mytischtennis")
if (path.startsWith('NOT:')) {
const excludePath = path.substring(4);
where.path = { [Op.not]: { [Op.like]: `%${excludePath}%` } };
} else {
where.path = { [Op.like]: `%${path}%` };
}
}
if (statusCode !== null) {

View File

@@ -1,5 +1,6 @@
import myTischtennisService from './myTischtennisService.js';
import myTischtennisFetchLogService from './myTischtennisFetchLogService.js';
import apiLogService from './apiLogService.js';
import myTischtennisClient from '../clients/myTischtennisClient.js';
import MyTischtennis from '../models/MyTischtennis.js';
import ClubTeam from '../models/ClubTeam.js';
@@ -182,6 +183,14 @@ class AutoFetchMatchResultsService {
* Fetch results for a specific team
*/
async fetchTeamResults(account, team) {
// Validate required data
if (!team.league) {
throw new Error('Team league is required');
}
if (!team.league.season || !team.league.season.season) {
throw new Error('Team league season is required');
}
const league = team.league;
const season = league.season;
@@ -207,26 +216,83 @@ class AutoFetchMatchResultsService {
const playerStatsUrl = `https://www.mytischtennis.de/click-tt/${league.association}/${seasonStr}/ligen/${league.groupname}/gruppe/${league.myTischtennisGroupId}/mannschaft/${team.myTischtennisTeamId}/${teamnameEncoded}/spielerbilanzen/gesamt?_data=routes%2Fclick-tt%2B%2F%24association%2B%2F%24season%2B%2F%24type%2B%2F%28%24groupname%29.gruppe.%24urlid_.mannschaft.%24teamid.%24teamname%2B%2Fspielerbilanzen.%24filter`;
devLog(`Fetching player stats from: ${playerStatsUrl}`);
const fetchStartTime = Date.now();
let playerStatsResponse = null;
let fetchExecutionTime = 0;
let responseStatus = 0;
let responseBodyData = null;
let fetchError = null;
const playerStatsResponse = await fetch(playerStatsUrl, {
headers: {
'Cookie': account.cookie || '',
'Authorization': `Bearer ${account.accessToken}`,
'Accept': 'application/json'
try {
playerStatsResponse = await fetch(playerStatsUrl, {
headers: {
'Cookie': account.cookie || '',
'Authorization': `Bearer ${account.accessToken}`,
'Accept': 'application/json'
}
});
fetchExecutionTime = Date.now() - fetchStartTime;
responseStatus = playerStatsResponse.status;
if (playerStatsResponse.ok) {
const playerStatsData = await playerStatsResponse.json();
responseBodyData = playerStatsData;
// Log complete response for debugging
console.log('=== PLAYER STATS RESPONSE START ===');
console.log(JSON.stringify(playerStatsData, null, 2));
console.log('=== PLAYER STATS RESPONSE END ===');
const playerCount = await this.processTeamData(team, playerStatsData);
totalProcessed += playerCount;
devLog(`Processed ${playerCount} player statistics`);
} else {
// Read error response body
try {
responseBodyData = await playerStatsResponse.text();
} catch (e) {
responseBodyData = `Error reading response: ${e.message}`;
}
}
});
if (playerStatsResponse.ok) {
const playerStatsData = await playerStatsResponse.json();
// Log complete response for debugging
console.log('=== PLAYER STATS RESPONSE START ===');
console.log(JSON.stringify(playerStatsData, null, 2));
console.log('=== PLAYER STATS RESPONSE END ===');
const playerCount = await this.processTeamData(team, playerStatsData);
totalProcessed += playerCount;
devLog(`Processed ${playerCount} player statistics`);
} catch (error) {
fetchExecutionTime = Date.now() - fetchStartTime;
fetchError = error.message || String(error);
responseStatus = 0;
console.error('Error fetching from myTischtennis:', error);
}
// Log external request to myTischtennis - IMMER, auch bei Fehlern
try {
await apiLogService.logRequest({
userId: account.userId,
method: 'GET',
path: playerStatsUrl.replace('https://www.mytischtennis.de', ''), // Relative path for consistency
statusCode: responseStatus || (fetchError ? 0 : 200),
requestBody: JSON.stringify({
url: playerStatsUrl,
myTischtennisTeamId: team.myTischtennisTeamId,
clubTeamId: team.id,
teamName: team.name,
association: league.association,
groupname: league.groupname,
groupId: league.myTischtennisGroupId
}),
responseBody: responseBodyData ? (typeof responseBodyData === 'string' ? responseBodyData.substring(0, 10000) : JSON.stringify(responseBodyData).substring(0, 10000)) : null,
executionTime: fetchExecutionTime,
errorMessage: fetchError || (playerStatsResponse && !playerStatsResponse.ok ? `myTischtennis API returned ${responseStatus}` : null),
logType: 'api_request',
schedulerJobType: 'mytischtennis_fetch'
});
} catch (logError) {
console.error('Error logging myTischtennis request:', logError);
// Don't throw - logging failures shouldn't break the main operation
}
// Re-throw error if fetch failed
if (fetchError) {
throw new Error(`Failed to fetch from myTischtennis: ${fetchError}`);
}
// Note: Match results are already included in the player stats response above