diff --git a/iotdb-core/datanode/src/main/i18n/zh/org/apache/iotdb/db/i18n/DataNodeSchemaMessages.java b/iotdb-core/datanode/src/main/i18n/zh/org/apache/iotdb/db/i18n/DataNodeSchemaMessages.java index 6d1d7c190ac9..773702664094 100644 --- a/iotdb-core/datanode/src/main/i18n/zh/org/apache/iotdb/db/i18n/DataNodeSchemaMessages.java +++ b/iotdb-core/datanode/src/main/i18n/zh/org/apache/iotdb/db/i18n/DataNodeSchemaMessages.java @@ -30,7 +30,7 @@ public final class DataNodeSchemaMessages { "更新模板 {} 在 schemaRegion {} 中的子树测点计数失败"; public static final String RECOVER_SPEND = "恢复 [{}] 耗时:{} ms"; public static final String SCHEMA_REGION_FAILED_TO_RECOVER = - "StorageGroup [%s] 中的 SchemaRegion [%d] 恢复失败。"; + "SchemaRegion [%d] 在 StorageGroup [%s] 中恢复失败。"; public static final String SCHEMA_REGION_ALREADY_DELETED = "SchemaRegion(id = {}) 已被删除,已跳过"; public static final String FAILED_TO_GET_TABLE_FOR_TIMESERIES_COUNT = @@ -104,7 +104,7 @@ public final class DataNodeSchemaMessages { public static final String CANNOT_FORCE_MLOG = "无法将 {} 的 mlog 强制写入 schema region"; public static final String SPEND_TIME_DESERIALIZE_MTREE = - "从 mlog.bin 反序列化 {} 的 mtree 耗时 {} ms"; + "从 mlog.bin 反序列化 MTree 耗时 {} ms,对应路径 {}"; public static final String FAILED_TO_PARSE_MLOG = "解析 "; public static final String MLOG_BIN_SUFFIX = " mlog.bin 失败"; public static final String PARSE_MLOG_ERROR = "在行号 {} 处解析 mlog 出错:"; @@ -116,7 +116,7 @@ public final class DataNodeSchemaMessages { public static final String MLOG_RECOVERY_CHECK_POINT = "MLog 恢复检查点:{}"; public static final String CANNOT_GET_MLOG_CHECKPOINT = "无法从 MLogDescription 文件获取检查点,原因:{},使用默认值 0。"; - public static final String FAILED_TO_SKIP_MLOG = "从 {} 跳过 {} 失败"; + public static final String FAILED_TO_SKIP_MLOG = "跳过 {} 失败,schemaRegion 目录为 {}"; public static final String UPDATE_MLOG_DESCRIPTION_FAILED = "更新 {} 失败,原因:{}"; public static final String DIRECT_BUFFER_MEMORY_EXCEEDED = "直接缓冲区的总分配内存将达到 "; @@ -162,7 +162,7 @@ public final class DataNodeSchemaMessages { public static final String ERROR_DURING_INIT_SCHEMA_REGION = "初始化 schemaRegion {} 过程中发生错误"; public static final String FAILED_TO_RECOVER_TAG_INDEX = - "在 schemaRegion {} 中恢复 {} 的 tagIndex 失败。"; + "恢复 {} 的 tagIndex 失败,schemaRegion 为 {}。"; public static final String FAILED_TO_READ_TAG_ATTRIBUTE = "读取 tag 和 attribute 信息失败:{}"; @@ -556,7 +556,7 @@ public final class DataNodeSchemaMessages { // ======================== CachedMTreeStore / Scheduler 相关消息 ======================== public static final String MTREE_FLUSH_COST = - "在 SchemaRegion {} 中刷写 MTree 耗时 {}ms"; + "MTree 刷写耗时 {}ms,SchemaRegion 为 {}"; // ======================== DataNodeTableCache 相关消息 ======================== diff --git a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/i18n/DataNodeSchemaMessagesZhFormatTest.java b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/i18n/DataNodeSchemaMessagesZhFormatTest.java new file mode 100644 index 000000000000..294ebf04b1ba --- /dev/null +++ b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/i18n/DataNodeSchemaMessagesZhFormatTest.java @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.iotdb.db.i18n; + +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.helpers.MessageFormatter; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class DataNodeSchemaMessagesZhFormatTest { + + private static final String ZH_MESSAGES_RELATIVE_PATH = + "src/main/i18n/zh/org/apache/iotdb/db/i18n/DataNodeSchemaMessages.java"; + + @Test + public void testZhSlf4jTemplatesPreserveLoggerArgumentOrder() throws IOException { + Assert.assertEquals( + "从 mlog.bin 反序列化 MTree 耗时 12 ms,对应路径 root.sg", + formatSlf4j(readZhMessage("SPEND_TIME_DESERIALIZE_MTREE"), 12, "root.sg")); + Assert.assertEquals( + "跳过 128 失败,schemaRegion 目录为 C:/schema", + formatSlf4j(readZhMessage("FAILED_TO_SKIP_MLOG"), 128, "C:/schema")); + Assert.assertEquals( + "恢复 root.sg.d.s 的 tagIndex 失败,schemaRegion 为 SchemaRegionId{1}。", + formatSlf4j( + readZhMessage("FAILED_TO_RECOVER_TAG_INDEX"), "root.sg.d.s", "SchemaRegionId{1}")); + Assert.assertEquals( + "MTree 刷写耗时 321ms,SchemaRegion 为 SchemaRegionId{1}", + formatSlf4j(readZhMessage("MTREE_FLUSH_COST"), 321, "SchemaRegionId{1}")); + } + + @Test + public void testZhStringFormatTemplatePreservesArgumentTypesAndOrder() throws IOException { + Assert.assertEquals( + "SchemaRegion [7] 在 StorageGroup [root.sg] 中恢复失败。", + String.format(readZhMessage("SCHEMA_REGION_FAILED_TO_RECOVER"), 7, "root.sg")); + } + + private static String formatSlf4j(String template, Object... arguments) { + return MessageFormatter.arrayFormat(template, arguments).getMessage(); + } + + private static String readZhMessage(String constantName) throws IOException { + Path basePath = resolveZhMessagesPath(); + Assert.assertTrue("Missing zh messages file: " + basePath, Files.exists(basePath)); + + String content = new String(Files.readAllBytes(basePath), StandardCharsets.UTF_8); + Matcher matcher = + Pattern.compile( + "public static final String\\s+" + + Pattern.quote(constantName) + + "\\s*=\\s*\"([^\"]*)\";", + Pattern.DOTALL) + .matcher(content); + Assert.assertTrue("Missing zh message constant: " + constantName, matcher.find()); + return matcher.group(1); + } + + private static Path resolveZhMessagesPath() throws IOException { + try { + Path testClassesDir = + Paths.get( + DataNodeSchemaMessagesZhFormatTest.class + .getProtectionDomain() + .getCodeSource() + .getLocation() + .toURI()); + Path moduleBaseDir = testClassesDir.getParent().getParent(); + return moduleBaseDir.resolve(ZH_MESSAGES_RELATIVE_PATH); + } catch (URISyntaxException e) { + throw new IOException("Failed to resolve zh messages path", e); + } + } +}