|
@@ -508,6 +508,10 @@ public class QueryTdengineDataServiceImpl extends AbstractCrudService<QueryTdeng
|
|
|
if (rows == null) {
|
|
if (rows == null) {
|
|
|
return ApiResult.error("CSV 解析失败");
|
|
return ApiResult.error("CSV 解析失败");
|
|
|
}
|
|
}
|
|
|
|
|
+ if (rows.isEmpty()) {
|
|
|
|
|
+ log.error("CSV 无有效数据行, deviceUuid=" + normalizedUuid + ", tableName=" + tableName);
|
|
|
|
|
+ return ApiResult.error("CSV 无有效可导入数据行");
|
|
|
|
|
+ }
|
|
|
int importedRows = batchInsertRows(tableName, rows);
|
|
int importedRows = batchInsertRows(tableName, rows);
|
|
|
if (importedRows == 0) {
|
|
if (importedRows == 0) {
|
|
|
log.error("CSV 无有效可导入数据行, deviceUuid=" + normalizedUuid + ", tableName=" + tableName);
|
|
log.error("CSV 无有效可导入数据行, deviceUuid=" + normalizedUuid + ", tableName=" + tableName);
|
|
@@ -560,24 +564,30 @@ public class QueryTdengineDataServiceImpl extends AbstractCrudService<QueryTdeng
|
|
|
headerResolved = true;
|
|
headerResolved = true;
|
|
|
}
|
|
}
|
|
|
if (parts.length <= Math.max(tsIndex, pIndex)) {
|
|
if (parts.length <= Math.max(tsIndex, pIndex)) {
|
|
|
- log.error("CSV 第 " + lineNo + " 行列数不足");
|
|
|
|
|
- return null;
|
|
|
|
|
|
|
+ log.error("CSV 第 " + lineNo + " 行列数不足,已跳过");
|
|
|
|
|
+ continue;
|
|
|
}
|
|
}
|
|
|
- Long tsMillis = parseTimestamp(parts[tsIndex], lineNo);
|
|
|
|
|
|
|
+ String tsRaw = parts[tsIndex];
|
|
|
|
|
+ String pRaw = parts[pIndex];
|
|
|
|
|
+ if (StringUtils.isBlank(tsRaw) || StringUtils.isBlank(pRaw)) {
|
|
|
|
|
+ log.error("CSV 第 " + lineNo + " 行 ts 或 p 存在空值,已跳过");
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ Long tsMillis = parseTimestamp(tsRaw, lineNo);
|
|
|
if (tsMillis == null) {
|
|
if (tsMillis == null) {
|
|
|
- return null;
|
|
|
|
|
|
|
+ continue;
|
|
|
}
|
|
}
|
|
|
- Double pValue = parseMetricValue(parts[pIndex], lineNo);
|
|
|
|
|
|
|
+ Double pValue = parseMetricValue(pRaw, lineNo);
|
|
|
if (pValue == null) {
|
|
if (pValue == null) {
|
|
|
- return null;
|
|
|
|
|
|
|
+ continue;
|
|
|
}
|
|
}
|
|
|
- rows.add(new TsdbCsvRow(tsMillis, pValue));
|
|
|
|
|
|
|
+ TsdbCsvRow row = new TsdbCsvRow(lineNo, tsMillis, pValue);
|
|
|
|
|
+ if (!isImportableRow(row)) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ rows.add(row);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- if (rows.isEmpty()) {
|
|
|
|
|
- log.error("CSV 无有效数据行");
|
|
|
|
|
- return null;
|
|
|
|
|
- }
|
|
|
|
|
return rows;
|
|
return rows;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -612,8 +622,16 @@ public class QueryTdengineDataServiceImpl extends AbstractCrudService<QueryTdeng
|
|
|
return importedRows;
|
|
return importedRows;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private static boolean isImportableRow(TsdbCsvRow row) {
|
|
|
|
|
- return row.tsMillis > 0 && Double.isFinite(row.pValue);
|
|
|
|
|
|
|
+ private boolean isImportableRow(TsdbCsvRow row) {
|
|
|
|
|
+ if (row.tsMillis <= 0) {
|
|
|
|
|
+ log.error("CSV 第 " + row.lineNo + " 行 ts 无效,已跳过");
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!Double.isFinite(row.pValue)) {
|
|
|
|
|
+ log.error("CSV 第 " + row.lineNo + " 行 p 不是有效数值,已跳过");
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ return true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private static String[] splitCsvLine(String line) {
|
|
private static String[] splitCsvLine(String line) {
|
|
@@ -645,7 +663,7 @@ public class QueryTdengineDataServiceImpl extends AbstractCrudService<QueryTdeng
|
|
|
private Long parseTimestamp(String rawValue, int lineNo) {
|
|
private Long parseTimestamp(String rawValue, int lineNo) {
|
|
|
String value = rawValue == null ? "" : rawValue.trim();
|
|
String value = rawValue == null ? "" : rawValue.trim();
|
|
|
if (value.isEmpty()) {
|
|
if (value.isEmpty()) {
|
|
|
- log.error("CSV 第 " + lineNo + " 行 ts 为空");
|
|
|
|
|
|
|
+ log.error("CSV 第 " + lineNo + " 行 ts 为空,已跳过");
|
|
|
return null;
|
|
return null;
|
|
|
}
|
|
}
|
|
|
if (value.matches("\\d+")) {
|
|
if (value.matches("\\d+")) {
|
|
@@ -663,7 +681,7 @@ public class QueryTdengineDataServiceImpl extends AbstractCrudService<QueryTdeng
|
|
|
try {
|
|
try {
|
|
|
return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").parse(value).getTime();
|
|
return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").parse(value).getTime();
|
|
|
} catch (ParseException ex) {
|
|
} catch (ParseException ex) {
|
|
|
- log.error("CSV 第 " + lineNo + " 行 ts 格式无效: " + value);
|
|
|
|
|
|
|
+ log.error("CSV 第 " + lineNo + " 行 ts 格式无效: " + value + ",已跳过");
|
|
|
return null;
|
|
return null;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -671,13 +689,13 @@ public class QueryTdengineDataServiceImpl extends AbstractCrudService<QueryTdeng
|
|
|
private Double parseMetricValue(String rawValue, int lineNo) {
|
|
private Double parseMetricValue(String rawValue, int lineNo) {
|
|
|
String value = rawValue == null ? "" : rawValue.trim();
|
|
String value = rawValue == null ? "" : rawValue.trim();
|
|
|
if (value.isEmpty()) {
|
|
if (value.isEmpty()) {
|
|
|
- log.error("CSV 第 " + lineNo + " 行 p 为空");
|
|
|
|
|
|
|
+ log.error("CSV 第 " + lineNo + " 行 p 为空,已跳过");
|
|
|
return null;
|
|
return null;
|
|
|
}
|
|
}
|
|
|
try {
|
|
try {
|
|
|
return new BigDecimal(value).doubleValue();
|
|
return new BigDecimal(value).doubleValue();
|
|
|
} catch (NumberFormatException ex) {
|
|
} catch (NumberFormatException ex) {
|
|
|
- log.error("CSV 第 " + lineNo + " 行 p 不是有效数值: " + value);
|
|
|
|
|
|
|
+ log.error("CSV 第 " + lineNo + " 行 p 不是有效数值: " + value + ",已跳过");
|
|
|
return null;
|
|
return null;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -687,10 +705,12 @@ public class QueryTdengineDataServiceImpl extends AbstractCrudService<QueryTdeng
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private static final class TsdbCsvRow {
|
|
private static final class TsdbCsvRow {
|
|
|
|
|
+ private final int lineNo;
|
|
|
private final long tsMillis;
|
|
private final long tsMillis;
|
|
|
private final double pValue;
|
|
private final double pValue;
|
|
|
|
|
|
|
|
- private TsdbCsvRow(long tsMillis, double pValue) {
|
|
|
|
|
|
|
+ private TsdbCsvRow(int lineNo, long tsMillis, double pValue) {
|
|
|
|
|
+ this.lineNo = lineNo;
|
|
|
this.tsMillis = tsMillis;
|
|
this.tsMillis = tsMillis;
|
|
|
this.pValue = pValue;
|
|
this.pValue = pValue;
|
|
|
}
|
|
}
|