This commit is contained in:
root
2025-12-14 21:34:42 +05:00
parent 46da25f001
commit 13bd7859c7
2 changed files with 98 additions and 15 deletions
@@ -40,7 +40,10 @@ public class MongoConfig {
public static class StringToMapConverter implements Converter<String, Map<String, Object>> {
@Override
public Map<String, Object> convert(String source) {
logger.debug("StringToMapConverter: Converting string to Map: {}", source);
long startTime = System.currentTimeMillis();
int sourceLength = source != null ? source.length() : 0;
logger.info("StringToMapConverter: Starting conversion. Source length: {} chars", sourceLength);
if (source == null || source.trim().isEmpty()) {
logger.debug("StringToMapConverter: Source is null or empty, returning empty Map");
return new HashMap<>();
@@ -49,17 +52,44 @@ public class MongoConfig {
try {
// Если это уже JSON строка, парсим её
if (source.trim().startsWith("{") || source.trim().startsWith("[")) {
logger.debug("StringToMapConverter: Parsing JSON string (starts with {} or [)",
source.trim().charAt(0));
long parseStartTime = System.currentTimeMillis();
Map<String, Object> result = objectMapper.readValue(source,
new TypeReference<Map<String, Object>>() {
});
logger.debug("StringToMapConverter: Successfully parsed JSON string to Map");
long parseDuration = System.currentTimeMillis() - parseStartTime;
int resultSize = result != null ? result.size() : 0;
logger.info("StringToMapConverter: Successfully parsed JSON string to Map. " +
"Source length: {} chars, Result size: {} keys, Parse duration: {} ms",
sourceLength, resultSize, parseDuration);
if (parseDuration > 1000) {
logger.warn("StringToMapConverter: Parse took {} ms, which is longer than expected",
parseDuration);
}
if (sourceLength > 100000) {
logger.warn(
"StringToMapConverter: Parsed very large JSON ({} chars). This may cause performance issues.",
sourceLength);
}
long totalDuration = System.currentTimeMillis() - startTime;
logger.debug("StringToMapConverter: Conversion completed. Total duration: {} ms", totalDuration);
return result;
}
// Если это простая строка, создаём пустой Map
logger.warn("StringToMapConverter: target_audience is a plain string, not JSON: {}", source);
return new HashMap<>();
} catch (Exception e) {
logger.error("StringToMapConverter: Error converting string to Map for target_audience: {}", source, e);
logger.error("StringToMapConverter: Error converting string to Map. Source length: {} chars",
sourceLength, e);
logger.error("StringToMapConverter: Stack trace: ", e);
return new HashMap<>();
}
}
@@ -71,32 +101,65 @@ public class MongoConfig {
*/
@ReadingConverter
public static class DocumentToMapConverter implements Converter<Document, Map<String, Object>> {
private static final int MAX_RECURSION_DEPTH = 50;
@Override
public Map<String, Object> convert(Document source) {
logger.debug("DocumentToMapConverter: Converting Document to Map");
return convert(source, 0);
}
private Map<String, Object> convert(Document source, int depth) {
logger.debug("DocumentToMapConverter: Converting Document to Map (depth: {})", depth);
if (source == null) {
logger.debug("DocumentToMapConverter: Source is null, returning empty Map");
return new HashMap<>();
}
if (depth > MAX_RECURSION_DEPTH) {
logger.error(
"DocumentToMapConverter: Maximum recursion depth ({}) exceeded. Possible circular reference!",
MAX_RECURSION_DEPTH);
return new HashMap<>();
}
long startTime = System.currentTimeMillis();
int keyCount = source.keySet().size();
logger.debug("DocumentToMapConverter: Processing Document with {} keys at depth {}", keyCount, depth);
Map<String, Object> result = new HashMap<>();
int nestedCount = 0;
for (String key : source.keySet()) {
Object value = source.get(key);
// Рекурсивно конвертируем вложенные Document
if (value instanceof Document) {
logger.debug("DocumentToMapConverter: Found nested Document for key: {}", key);
result.put(key, convert((Document) value));
nestedCount++;
logger.debug("DocumentToMapConverter: Found nested Document for key: {} at depth {}", key, depth);
result.put(key, convert((Document) value, depth + 1));
} else if (value instanceof org.bson.types.BSONTimestamp ||
value instanceof org.bson.types.ObjectId ||
value instanceof java.util.Date) {
// Сохраняем специальные типы BSON как строки
result.put(key, value.toString());
} else {
result.put(key, value);
}
}
long duration = System.currentTimeMillis() - startTime;
logger.debug("DocumentToMapConverter: Successfully converted Document to Map with {} keys. Duration: {} ms",
result.size(), duration);
logger.info("DocumentToMapConverter: Successfully converted Document to Map. " +
"Keys: {}, Nested documents: {}, Depth: {}, Duration: {} ms",
result.size(), nestedCount, depth, duration);
if (duration > 1000) {
logger.warn("DocumentToMapConverter: Conversion took {} ms, which is longer than expected", duration);
logger.warn("DocumentToMapConverter: Conversion took {} ms at depth {}, which is longer than expected",
duration, depth);
}
if (keyCount > 100) {
logger.warn("DocumentToMapConverter: Converted Document with {} keys, which is unusually large",
keyCount);
}
return result;
@@ -154,13 +154,33 @@ public class MarketingAnalysisService {
"processAnalysis: About to save analysis to MongoDB for ID: {}. This may take time for large reportData...",
analysisId);
long saveStartTime = System.currentTimeMillis();
repository.save(analysis);
long saveDuration = System.currentTimeMillis() - saveStartTime;
logger.info("processAnalysis: Analysis saved successfully to MongoDB for ID: {}. Save duration: {} ms",
analysisId, saveDuration);
if (saveDuration > 10000) {
logger.warn("processAnalysis: Save operation took {} ms, which is longer than expected", saveDuration);
try {
logger.debug("processAnalysis: Calling repository.save() for ID: {}", analysisId);
MarketingAnalysis savedAnalysis = repository.save(analysis);
long saveDuration = System.currentTimeMillis() - saveStartTime;
logger.info("processAnalysis: repository.save() completed for ID: {}. Save duration: {} ms",
analysisId, saveDuration);
if (saveDuration > 10000) {
logger.warn("processAnalysis: Save operation took {} ms, which is longer than expected",
saveDuration);
}
// Логируем, что произошло после save
logger.debug(
"processAnalysis: After save, checking if Spring Data MongoDB is reading back the document...");
if (savedAnalysis != null && savedAnalysis.getReportData() != null) {
logger.debug("processAnalysis: Saved analysis has reportData with {} keys",
savedAnalysis.getReportData().keySet().size());
}
} catch (Exception saveException) {
long saveDuration = System.currentTimeMillis() - saveStartTime;
logger.error(
"processAnalysis: Exception during repository.save() for ID: {}. Duration before exception: {} ms",
analysisId, saveDuration, saveException);
throw saveException;
}
logger.info("processAnalysis: Marketing analysis completed successfully for ID: {}", analysisId);