.
This commit is contained in:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user