core/unittest/processor/ProcessorParseApsaraNativeUnittest.cpp (1,156 lines of code) (raw):

// Copyright 2023 iLogtail Authors // // Licensed 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. #include <cstdlib> #include "collection_pipeline/plugin/instance/ProcessorInstance.h" #include "common/JsonUtil.h" #include "common/StringView.h" #include "config/CollectionConfig.h" #include "models/LogEvent.h" #include "plugin/processor/ProcessorParseApsaraNative.h" #include "plugin/processor/inner/ProcessorMergeMultilineLogNative.h" #include "plugin/processor/inner/ProcessorSplitLogStringNative.h" #include "plugin/processor/inner/ProcessorSplitMultilineLogStringNative.h" #include "unittest/Unittest.h" namespace logtail { class ProcessorParseApsaraNativeUnittest : public ::testing::Test { public: void SetUp() override { mContext.SetConfigName("project##config_0"); BOOL_FLAG(ilogtail_discard_old_data) = false; } void TestInit(); void TestProcessWholeLine(); void TestProcessWholeLinePart(); void TestProcessKeyOverwritten(); void TestUploadRawLog(); void TestAddLog(); void TestProcessEventKeepUnmatch(); void TestProcessEventDiscardUnmatch(); void TestMultipleLines(); void TestProcessEventMicrosecondUnmatch(); void TestApsaraEasyReadLogTimeParser(); void TestApsaraLogLineParser(); CollectionPipelineContext mContext; }; UNIT_TEST_CASE(ProcessorParseApsaraNativeUnittest, TestInit); UNIT_TEST_CASE(ProcessorParseApsaraNativeUnittest, TestProcessWholeLine); UNIT_TEST_CASE(ProcessorParseApsaraNativeUnittest, TestProcessWholeLinePart); UNIT_TEST_CASE(ProcessorParseApsaraNativeUnittest, TestProcessKeyOverwritten); UNIT_TEST_CASE(ProcessorParseApsaraNativeUnittest, TestUploadRawLog); UNIT_TEST_CASE(ProcessorParseApsaraNativeUnittest, TestAddLog); UNIT_TEST_CASE(ProcessorParseApsaraNativeUnittest, TestProcessEventKeepUnmatch); UNIT_TEST_CASE(ProcessorParseApsaraNativeUnittest, TestProcessEventDiscardUnmatch); UNIT_TEST_CASE(ProcessorParseApsaraNativeUnittest, TestMultipleLines); UNIT_TEST_CASE(ProcessorParseApsaraNativeUnittest, TestProcessEventMicrosecondUnmatch); UNIT_TEST_CASE(ProcessorParseApsaraNativeUnittest, TestApsaraEasyReadLogTimeParser); UNIT_TEST_CASE(ProcessorParseApsaraNativeUnittest, TestApsaraLogLineParser); PluginInstance::PluginMeta getPluginMeta() { PluginInstance::PluginMeta pluginMeta{"1"}; return pluginMeta; } void ProcessorParseApsaraNativeUnittest::TestApsaraEasyReadLogTimeParser() { // make config Json::Value config; config["SourceKey"] = "content"; config["KeepingSourceWhenParseFail"] = false; config["KeepingSourceWhenParseSucceed"] = false; config["CopingRawLog"] = false; config["RenamedSourceKey"] = "rawLog"; config["Timezone"] = "GMT+08:00"; ProcessorParseApsaraNative* processor = new ProcessorParseApsaraNative; processor->SetContext(mContext); ProcessorInstance processorInstance(processor, getPluginMeta()); APSARA_TEST_TRUE_FATAL(processorInstance.Init(config, mContext)); StringView buffer = "[1378972170425093]\tA:B"; StringView lastStr; LogtailTime lastTime = {0, 0}; int64_t microTime = 0; uint32_t dateTime = 0; dateTime = processor->ApsaraEasyReadLogTimeParser(buffer, lastStr, lastTime, microTime); APSARA_TEST_EQUAL(dateTime, 1378972170); APSARA_TEST_EQUAL(microTime, 1378972170425093); APSARA_TEST_EQUAL(lastTime.tv_sec, 0); buffer = "[1378972171093]\tA:B"; microTime = 0; dateTime = 0; dateTime = processor->ApsaraEasyReadLogTimeParser(buffer, lastStr, lastTime, microTime); APSARA_TEST_EQUAL(dateTime, 1378972171); APSARA_TEST_EQUAL(microTime, 1378972171093000); APSARA_TEST_EQUAL(lastTime.tv_sec, 0); buffer = "[1378972172]\tA:B"; microTime = 0; dateTime = 0; dateTime = processor->ApsaraEasyReadLogTimeParser(buffer, lastStr, lastTime, microTime); APSARA_TEST_EQUAL(dateTime, 1378972172); APSARA_TEST_EQUAL(microTime, 1378972172000000); APSARA_TEST_EQUAL(lastTime.tv_sec, 0); buffer = "[2013-09-12 22:18:28.819129]\tA:B"; microTime = 0; dateTime = 0; dateTime = processor->ApsaraEasyReadLogTimeParser(buffer, lastStr, lastTime, microTime); APSARA_TEST_EQUAL(dateTime, 1378995508); APSARA_TEST_EQUAL(microTime, 1378995508819129); APSARA_TEST_EQUAL(dateTime, lastTime.tv_sec); APSARA_TEST_EQUAL(lastStr, "2013-09-12 22:18:28"); buffer = "[2013-09-12 22:18:28.819139]\tA:B"; microTime = 0; dateTime = 0; dateTime = processor->ApsaraEasyReadLogTimeParser(buffer, lastStr, lastTime, microTime); APSARA_TEST_EQUAL(dateTime, 1378995508); APSARA_TEST_EQUAL(microTime, 1378995508819139); APSARA_TEST_EQUAL(dateTime, lastTime.tv_sec); APSARA_TEST_EQUAL(lastStr, "2013-09-12 22:18:28"); buffer = "[2013-09-12 22:18:29.819139]\tA:B"; microTime = 0; dateTime = 0; dateTime = processor->ApsaraEasyReadLogTimeParser(buffer, lastStr, lastTime, microTime); APSARA_TEST_EQUAL(dateTime, 1378995509); APSARA_TEST_EQUAL(microTime, 1378995509819139); APSARA_TEST_EQUAL(dateTime, lastTime.tv_sec); APSARA_TEST_EQUAL(lastStr, "2013-09-12 22:18:29"); LOG_INFO(sLogger, ("TestApsaraEasyReadLogTimeParser() end", time(NULL))); buffer = "[2013-09-12 22:18:29.819]\tA:B"; microTime = 0; dateTime = 0; dateTime = processor->ApsaraEasyReadLogTimeParser(buffer, lastStr, lastTime, microTime); APSARA_TEST_EQUAL(dateTime, 1378995509); APSARA_TEST_EQUAL(microTime, 1378995509819000); APSARA_TEST_EQUAL(dateTime, lastTime.tv_sec); APSARA_TEST_EQUAL(lastStr, "2013-09-12 22:18:29"); } void ProcessorParseApsaraNativeUnittest::TestApsaraLogLineParser() { const char* logLine[] = { "[2013-03-13 18:05:09.493309]\t[WARNING]\t[13000]\t[build/debug64/ilogtail/core/ilogtail.cpp:1753]", // 1 "[2013-03-13 18:05:09.493309]\t[WARNING]\t[13000]\t[build/debug64/ilogtail/core/ilogtail.cpp:1753]\t", // 2 "[2013-03-13 18:05:09.493309]\t[WARNING]\t[13000]\t[build/debug64/ilogtail/core/ilogtail.cpp:1754]\tsomestring", // 3 "[2013-03-13 " "18:05:09.493309]\t[WARNING]\t[13000]\t[build/debug64/ilogtail/core/ilogtail.cpp:1755]\tRealRecycle#Command:rm " "-rf /apsara/tubo/.fuxi_tubo_trash/*", // 4 "[2013-03-13 " "18:14:57.365716]\t[ERROR]\t[12835]\t[build/debug64/ilogtail/core/" "ilogtail.cpp:1945]\tParseWhiteListOK:{\n\\\"sys/" "pangu/ChunkServerRole\\\": \\\"\\\",\n\\\"sys/pangu/PanguMasterRole\\\": \\\"\\\"}", // 5 "[2013-03-13 18:14:57.365716]\t[12835]\t[ERROR]\t[build/debug64/ilogtail/core/ilogtail.cpp:1945]", // 6 "[2013-03-13 18:14:57.365716]\t[build/debug64/ilogtail/core/ilogtail.cpp:1945]\t[12835]\t[ERROR]", // 7 "[2013-03-13 18:14:57.365716]\t[build/debug64/ilogtail/core/ilogtail.cpp:1945]\t[ERROR]", // 8 "[2013-03-13 18:14:57.365716]\t[build/debug64/ilogtail/core/ilogtail.cpp:1945]\t[12835]\t[ERROR]\t[5432187]", // 9 "[2013-03-13 " "18:14:57.365716]\t[build/debug64/ilogtail/core/ilogtail.cpp:1945]\t[12835]\t[ERROR]\t[5432187]\tcount:55", // 10 "[2013-03-13 18:14:57.365716]\t[trace_id:787]\t[ERROR]", // 11 "[2013-03-13 18:14:57.365716]\t[trace_id:787]\t[ERROR]\t", // 12 "[2013-03-13 18:14:57.365716]\t[trace_id:787]\t[ERROR]\n", // 13 "[2013-03-13 18:14:57.365716]\t[trace_id:787]\t[ERROR]\tother\tcount:45", // 14 "[2013-03-13 18:14:57.365716]\t[trace_id:787]\t[ERROR]\tother:\tcount:45", // 15 "[2013-03-13 18:14:57.365716]\t[trace_id:787]\t[ERROR]\tcount:45", // 16 "[2013-03-13 18:14:57.365716]\t[trace_id:787]\t[ERROR]\tcount:45\tnum:88\tjob:ss", // 17 "[2013-03-13 18:14:57.365716]\t[trace_id:787]\t[ERROR]\t[corrupt\tcount:45\tnum:88\tjob:ss", // 18 "[2013-03-13 18:14:57.365716]\t[trace_id:787]\t[ERROR]\t[corruptcount:45\tnum:88\tjob:ss", // 19 "[2013-03-13 18:14:57.365716]\t[trace_id:787]\t[ERROR]\t[corrupt]count:45\tnum:88\tjob:ss", // 20 "[2013-03-13 18:14:57.365716]\t[build/debug64]\t[ERROR]\tcount:45\tnum:88\tjob:ss", // 21 "[2013-03-13 18:14:57.365716]\t[build/debug64:]\t[ERROR]\tcount:45\tnum:88\tjob:ss", // 22 "[2013-03-13 18:14:57.365716]\t[build/debug64:]\t[ERROR]\tcount:45\t:88\tjob:ss", // 23 "[2013-03-13 18:14:57.365716]", // 24 "[2013-03-13 18:14:57.365716]\t", // 25 "[2013-03-13 18:14:57.365716]\n", // 26 "[2013-03-13 18:14:57.365716]\t\t\t", // 27 "", // 28 "[2013-03-13 " "18:05:09.493309]\t[WARNING]\t[13000]\t[13003]\t[ERROR]\t[build/debug64/ilogtail/core/ilogtail.cpp:1753]", // 29 "[2013-03-13 18:05:09.493309]\t[WARNING]\t[13000]\t[13003]\t[ERROR]\t[tubo.cpp:1753]", // 30 "[2013-03-13 18:05:09.493309" // 31 }; static const char* APSARA_FIELD_LEVEL = "__LEVEL__"; static const char* APSARA_FIELD_THREAD = "__THREAD__"; static const char* APSARA_FIELD_FILE = "__FILE__"; static const char* APSARA_FIELD_LINE = "__LINE__"; const char* logParseResult[][16] = { {"microtime", "1363169109493309", APSARA_FIELD_LEVEL, "WARNING", APSARA_FIELD_THREAD, "13000", APSARA_FIELD_FILE, "build/debug64/ilogtail/core/ilogtail.cpp", APSARA_FIELD_LINE, "1753", NULL}, // 1 {"microtime", "1363169109493309", APSARA_FIELD_LEVEL, "WARNING", APSARA_FIELD_THREAD, "13000", APSARA_FIELD_FILE, "build/debug64/ilogtail/core/ilogtail.cpp", APSARA_FIELD_LINE, "1753", NULL}, // 2 {"microtime", "1363169109493309", APSARA_FIELD_LEVEL, "WARNING", APSARA_FIELD_THREAD, "13000", APSARA_FIELD_FILE, "build/debug64/ilogtail/core/ilogtail.cpp", APSARA_FIELD_LINE, "1754", NULL}, // 3 {APSARA_FIELD_LEVEL, "WARNING", APSARA_FIELD_THREAD, "13000", APSARA_FIELD_FILE, "build/debug64/ilogtail/core/ilogtail.cpp", APSARA_FIELD_LINE, "1755", "RealRecycle#Command", "rm -rf /apsara/tubo/.fuxi_tubo_trash/*", NULL}, // 4 {APSARA_FIELD_LEVEL, "ERROR", APSARA_FIELD_THREAD, "12835", APSARA_FIELD_FILE, "build/debug64/ilogtail/core/ilogtail.cpp", APSARA_FIELD_LINE, "1945", "ParseWhiteListOK", "{\n\"sys/pangu/ChunkServerRole\": \"\",\n\"sys/pangu/PanguMasterRole\": \"\"}", NULL}, // 5 {APSARA_FIELD_THREAD, "12835", APSARA_FIELD_LEVEL, "ERROR", APSARA_FIELD_FILE, "build/debug64/ilogtail/core/ilogtail.cpp", APSARA_FIELD_LINE, "1945", NULL}, // 6 {APSARA_FIELD_FILE, "build/debug64/ilogtail/core/ilogtail.cpp", APSARA_FIELD_LINE, "1945", APSARA_FIELD_THREAD, "12835", APSARA_FIELD_LEVEL, "ERROR", NULL}, // 7 {APSARA_FIELD_FILE, "build/debug64/ilogtail/core/ilogtail.cpp", APSARA_FIELD_LINE, "1945", APSARA_FIELD_LEVEL, "ERROR", NULL}, // 8 {APSARA_FIELD_FILE, "build/debug64/ilogtail/core/ilogtail.cpp", APSARA_FIELD_LINE, "1945", APSARA_FIELD_THREAD, "12835", APSARA_FIELD_LEVEL, "ERROR", NULL}, // 9 {APSARA_FIELD_FILE, "build/debug64/ilogtail/core/ilogtail.cpp", APSARA_FIELD_LINE, "1945", APSARA_FIELD_THREAD, "12835", APSARA_FIELD_LEVEL, "ERROR", "count", "55", NULL}, // 10 {APSARA_FIELD_LEVEL, "ERROR", NULL}, // 11 {APSARA_FIELD_LEVEL, "ERROR", NULL}, // 12 {APSARA_FIELD_LEVEL, "ERROR", NULL}, // 13 {APSARA_FIELD_LEVEL, "ERROR", "count", "45", NULL}, // 14 {APSARA_FIELD_LEVEL, "ERROR", "other", "", "count", "45", NULL}, // 15 {APSARA_FIELD_LEVEL, "ERROR", "count", "45", NULL}, // 16 {APSARA_FIELD_LEVEL, "ERROR", "count", "45", "num", "88", "job", "ss", NULL}, // 17 {APSARA_FIELD_LEVEL, "ERROR", "count", "45", "num", "88", "job", "ss", NULL}, // 18 {APSARA_FIELD_LEVEL, "ERROR", "[corruptcount", "45", "num", "88", "job", "ss", NULL}, // 19 {APSARA_FIELD_LEVEL, "ERROR", "[corrupt]count", "45", "num", "88", "job", "ss", NULL}, // 20 {APSARA_FIELD_FILE, "build/debug64", APSARA_FIELD_LEVEL, "ERROR", "count", "45", "num", "88", "job", "ss", NULL}, // 21 {APSARA_FIELD_FILE, "build/debug64", APSARA_FIELD_LINE, "", APSARA_FIELD_LEVEL, "ERROR", "count", "45", "num", "88", "job", "ss", NULL}, // 22 {APSARA_FIELD_FILE, "build/debug64", APSARA_FIELD_LINE, "", APSARA_FIELD_LEVEL, "ERROR", "count", "45", "", "88", "job", "ss", NULL}, // 23 {"microtime", "1363169697365716", NULL}, // 24 {"microtime", "1363169697365716", NULL}, // 25 {"microtime", "1363169697365716", NULL}, // 26 {"microtime", "1363169697365716", NULL}, // 27 {"content", "", NULL}, // 28 {APSARA_FIELD_LEVEL, "WARNING", APSARA_FIELD_THREAD, "13000", APSARA_FIELD_FILE, "build/debug64/ilogtail/core/ilogtail.cpp", APSARA_FIELD_LINE, "1753", NULL}, // 29 {APSARA_FIELD_LEVEL, "WARNING", APSARA_FIELD_THREAD, "13000", APSARA_FIELD_FILE, "tubo.cpp", APSARA_FIELD_LINE, "1753", NULL}, // 30 {NULL} // 31 }; // make config Json::Value config; config["SourceKey"] = "content"; config["KeepingSourceWhenParseFail"] = false; config["KeepingSourceWhenParseSucceed"] = false; config["CopingRawLog"] = false; config["RenamedSourceKey"] = "rawLog"; config["Timezone"] = "GMT+08:00"; ProcessorInstance processorInstance(new ProcessorParseApsaraNative, getPluginMeta()); APSARA_TEST_TRUE_FATAL(processorInstance.Init(config, mContext)); for (uint32_t i = 0; i < sizeof(logLine) / sizeof(logLine[0]); i++) { auto sourceBuffer = std::make_shared<SourceBuffer>(); PipelineEventGroup eventGroup(sourceBuffer); std::string inJson = R"({ "events" : [ { "contents" : { "content" : ")" + std::string(logLine[i]) + R"(" }, "timestamp" : 12345678901, "type" : 1 } ] })"; eventGroup.FromJsonString(inJson); std::vector<PipelineEventGroup> eventGroupList; eventGroupList.emplace_back(std::move(eventGroup)); processorInstance.Process(eventGroupList); Json::Value outJson = eventGroupList[0].ToJson(); if (logParseResult[i][0] == NULL) { APSARA_TEST_EQUAL(eventGroupList[0].ToJsonString(), "null"); continue; } for (int j = 0; j < 10 && logParseResult[i][j] != NULL; j++) { if (j % 2 == 0) { APSARA_TEST_TRUE(outJson.isMember("events")); APSARA_TEST_TRUE(outJson["events"].isArray()); APSARA_TEST_TRUE(outJson["events"][0].isObject()); APSARA_TEST_TRUE(outJson["events"][0].isMember("contents")); APSARA_TEST_TRUE(outJson["events"][0]["contents"].isMember(logParseResult[i][j])); APSARA_TEST_EQUAL(outJson["events"][0]["contents"][logParseResult[i][j]], std::string(logParseResult[i][j + 1])); } else { continue; } } } } void ProcessorParseApsaraNativeUnittest::TestMultipleLines() { // 第一个contents 测试多行下的解析,第二个contents测试多行下time的解析 std::string inJson = R"({ "events" : [ { "contents" : { "content" : "[2023-09-04 13:15:50.1]\t[ERROR]\t[1]\t/ilogtail/AppConfigBase.cpp:1\t\tAppConfigBase AppConfigBase:1 [2023-09-04 13:15:33.2]\t[INFO]\t[2]\t/ilogtail/AppConfigBase.cpp:2\t\tAppConfigBase AppConfigBase:2 [2023-09-04 13:15:22.3]\t[WARNING]\t[3]\t/ilogtail/AppConfigBase.cpp:3\t\tAppConfigBase AppConfigBase:3" }, "timestamp" : 12345678901, "type" : 1 }, { "contents" : { "content" : "[2023-09-04 13:15 :50.1]\t[ERROR]\t[1]\t/ilogtail/AppConfigBase.cpp:1\t\tAppConfigBase AppConfigBase:1 [2023-09-04 13:15:22.3]\t[WARNING]\t[3]\t/ilogtail/AppConfigBase.cpp:3\t\tAppConfigBase AppConfigBase:3" }, "timestamp" : 12345678901, "type" : 1 } ] })"; std::string expectJson = R"({ "events": [ { "contents": { "/ilogtail/AppConfigBase.cpp": "1", "AppConfigBase AppConfigBase": "1", "__LEVEL__": "ERROR", "__THREAD__": "1", "microtime": "1693833350100000" }, "timestamp": 1693833350, "timestampNanosecond": 100000000, "type": 1 }, { "contents": { "/ilogtail/AppConfigBase.cpp": "2", "AppConfigBase AppConfigBase": "2", "__LEVEL__": "INFO", "__THREAD__": "2", "microtime": "1693833333200000" }, "timestamp": 1693833333, "timestampNanosecond": 200000000, "type": 1 }, { "contents": { "/ilogtail/AppConfigBase.cpp": "3", "AppConfigBase AppConfigBase": "3", "__LEVEL__": "WARNING", "__THREAD__": "3", "microtime": "1693833322300000" }, "timestamp": 1693833322, "timestampNanosecond": 300000000, "type": 1 }, { "contents": { "__raw__": "[2023-09-04 13:15" }, "timestamp": 12345678901, "type": 1 }, { "contents": { "__raw__": ":50.1]\t[ERROR]\t[1]\t/ilogtail/AppConfigBase.cpp:1\t\tAppConfigBase AppConfigBase:1" }, "timestamp": 12345678901, "type": 1 }, { "contents": { "/ilogtail/AppConfigBase.cpp": "3", "AppConfigBase AppConfigBase": "3", "__LEVEL__": "WARNING", "__THREAD__": "3", "microtime": "1693833322300000" }, "timestamp": 1693833322, "timestampNanosecond": 300000000, "type": 1 } ] })"; // ProcessorSplitLogStringNative { // make events auto sourceBuffer = std::make_shared<SourceBuffer>(); PipelineEventGroup eventGroup(sourceBuffer); eventGroup.FromJsonString(inJson); // make config Json::Value config; config["SourceKey"] = "content"; config["Timezone"] = "GMT+00:00"; config["KeepingSourceWhenParseFail"] = true; config["KeepingSourceWhenParseSucceed"] = false; config["CopingRawLog"] = false; config["RenamedSourceKey"] = "__raw__"; // run function ProcessorSplitLogStringNative ProcessorSplitLogStringNative processorSplitLogStringNative; processorSplitLogStringNative.SetContext(mContext); APSARA_TEST_TRUE_FATAL(processorSplitLogStringNative.Init(config)); processorSplitLogStringNative.Process(eventGroup); // run function ProcessorParseApsaraNative ProcessorParseApsaraNative& processor = *(new ProcessorParseApsaraNative); ProcessorInstance processorInstance(&processor, getPluginMeta()); APSARA_TEST_TRUE_FATAL(processorInstance.Init(config, mContext)); processor.Process(eventGroup); // judge result std::string outJson = eventGroup.ToJsonString(); APSARA_TEST_STREQ_FATAL(CompactJson(expectJson).c_str(), CompactJson(outJson).c_str()); } // ProcessorSplitMultilineLogStringNative { // make events auto sourceBuffer = std::make_shared<SourceBuffer>(); PipelineEventGroup eventGroup(sourceBuffer); eventGroup.FromJsonString(inJson); // make config Json::Value config; config["SourceKey"] = "content"; config["Timezone"] = "GMT+00:00"; config["KeepingSourceWhenParseFail"] = true; config["KeepingSourceWhenParseSucceed"] = false; config["CopingRawLog"] = false; config["RenamedSourceKey"] = "__raw__"; config["StartPattern"] = "[a-zA-Z0-9]*"; config["UnmatchedContentTreatment"] = "single_line"; // run function ProcessorSplitMultilineLogStringNative ProcessorSplitMultilineLogStringNative processorSplitMultilineLogStringNative; processorSplitMultilineLogStringNative.SetContext(mContext); processorSplitMultilineLogStringNative.SetMetricsRecordRef(ProcessorSplitMultilineLogStringNative::sName, "1"); APSARA_TEST_TRUE_FATAL(processorSplitMultilineLogStringNative.Init(config)); processorSplitMultilineLogStringNative.Process(eventGroup); // run function ProcessorParseApsaraNative ProcessorParseApsaraNative& processor = *(new ProcessorParseApsaraNative); ProcessorInstance processorInstance(&processor, getPluginMeta()); APSARA_TEST_TRUE_FATAL(processorInstance.Init(config, mContext)); processor.Process(eventGroup); // judge result std::string outJson = eventGroup.ToJsonString(); APSARA_TEST_STREQ_FATAL(CompactJson(expectJson).c_str(), CompactJson(outJson).c_str()); } } void ProcessorParseApsaraNativeUnittest::TestInit() { // make config Json::Value config; config["SourceKey"] = "content"; config["KeepingSourceWhenParseFail"] = true; config["KeepingSourceWhenParseSucceed"] = false; config["CopingRawLog"] = false; config["RenamedSourceKey"] = "rawLog"; config["Timezone"] = ""; ProcessorParseApsaraNative& processor = *(new ProcessorParseApsaraNative); processor.SetContext(mContext); ProcessorInstance processorInstance(&processor, getPluginMeta()); APSARA_TEST_TRUE_FATAL(processorInstance.Init(config, mContext)); } void ProcessorParseApsaraNativeUnittest::TestProcessWholeLine() { // make config Json::Value config; config["SourceKey"] = "content"; config["KeepingSourceWhenParseFail"] = true; config["KeepingSourceWhenParseSucceed"] = false; config["CopingRawLog"] = false; config["RenamedSourceKey"] = "rawLog"; config["Timezone"] = ""; // make events auto sourceBuffer = std::make_shared<SourceBuffer>(); PipelineEventGroup eventGroup(sourceBuffer); std::string inJson = R"({ "events" : [ { "contents" : { "content" : "[2023-09-04 13:15:04.862181] [INFO] [385658] /ilogtail/AppConfigBase.cpp:100 AppConfigBase AppConfigBase:success" }, "timestamp" : 12345678901, "type" : 1 }, { "contents" : { "content" : "[2023-09-04 13:16:04.862181] [INFO] [385658] /ilogtail/AppConfigBase.cpp:100 AppConfigBase AppConfigBase:success" }, "timestamp" : 12345678901, "type" : 1 }, { "contents" : { "content" : "[1693833364862181] [INFO] [385658] /ilogtail/AppConfigBase.cpp:100 AppConfigBase AppConfigBase:success" }, "timestamp" : 12345678901, "type" : 1 } ] })"; eventGroup.FromJsonString(inJson); // run function ProcessorParseApsaraNative& processor = *(new ProcessorParseApsaraNative); processor.SetContext(mContext); ProcessorInstance processorInstance(&processor, getPluginMeta()); APSARA_TEST_TRUE_FATAL(processorInstance.Init(config, mContext)); std::vector<PipelineEventGroup> eventGroupList; eventGroupList.emplace_back(std::move(eventGroup)); processorInstance.Process(eventGroupList); std::string expectJson = R"({ "events": [ { "contents": { "/ilogtail/AppConfigBase.cpp": "100", "AppConfigBase AppConfigBase": "success", "__LEVEL__": "INFO", "__THREAD__": "385658", "microtime": "1693833304862181" }, "timestamp": 1693833304, "timestampNanosecond": 862181000, "type": 1 }, { "contents": { "/ilogtail/AppConfigBase.cpp": "100", "AppConfigBase AppConfigBase": "success", "__LEVEL__": "INFO", "__THREAD__": "385658", "microtime": "1693833364862181" }, "timestamp": 1693833364, "timestampNanosecond": 862181000, "type": 1 }, { "contents": { "/ilogtail/AppConfigBase.cpp": "100", "AppConfigBase AppConfigBase": "success", "__LEVEL__": "INFO", "__THREAD__": "385658", "microtime": "1693833364862181" }, "timestamp": 1693833364, "timestampNanosecond": 862181000, "type": 1 } ] })"; // judge result std::string outJson = eventGroupList[0].ToJsonString(); APSARA_TEST_STREQ_FATAL(CompactJson(expectJson).c_str(), CompactJson(outJson).c_str()); } void ProcessorParseApsaraNativeUnittest::TestProcessWholeLinePart() { // make config Json::Value config; config["SourceKey"] = "content"; config["KeepingSourceWhenParseFail"] = false; config["KeepingSourceWhenParseSucceed"] = false; config["CopingRawLog"] = false; config["RenamedSourceKey"] = "rawLog"; config["Timezone"] = ""; // make events auto sourceBuffer = std::make_shared<SourceBuffer>(); PipelineEventGroup eventGroup(sourceBuffer); std::string inJson = R"({ "events" : [ { "contents" : { "content" : "[2023-09-04 13:15:0] [INFO] [385658] /ilogtail/AppConfigBase.cpp:100 AppConfigBase AppConfigBase:success" }, "timestamp" : 12345678901, "type" : 1 }, { "contents" : { "content" : "[2023-09-04 13:16:0[INFO] [385658] /ilogtail/AppConfigBase.cpp:100 AppConfigBase AppConfigBase:success" }, "timestamp" : 12345678901, "type" : 1 }, { "contents" : { "content" : "[1234560 [INFO] [385658] /ilogtail/AppConfigBase.cpp:100 AppConfigBase AppConfigBase:success" }, "timestamp" : 12345678901, "type" : 1 } ] })"; eventGroup.FromJsonString(inJson); // run function ProcessorParseApsaraNative& processor = *(new ProcessorParseApsaraNative); processor.SetContext(mContext); ProcessorInstance processorInstance(&processor, getPluginMeta()); APSARA_TEST_TRUE_FATAL(processorInstance.Init(config, mContext)); std::vector<PipelineEventGroup> eventGroupList; eventGroupList.emplace_back(std::move(eventGroup)); processorInstance.Process(eventGroupList); // judge result std::string outJson = eventGroupList[0].ToJsonString(); std::string expectJson = R"({ "events": [ { "contents": { "/ilogtail/AppConfigBase.cpp": "100", "AppConfigBase AppConfigBase": "success", "__LEVEL__": "INFO", "__THREAD__": "385658", "microtime": "1693833300000000" }, "timestamp": 1693833300, "timestampNanosecond": 0, "type": 1 }, { "contents": { "/ilogtail/AppConfigBase.cpp": "100", "AppConfigBase AppConfigBase": "success", "__THREAD__": "385658", "microtime": "1693833360000000" }, "timestamp": 1693833360, "timestampNanosecond": 0, "type": 1 } ] })"; APSARA_TEST_STREQ_FATAL(CompactJson(expectJson).c_str(), CompactJson(outJson).c_str()); // check observablity APSARA_TEST_EQUAL_FATAL(uint64_t(3), processorInstance.mInEventsTotal->GetValue()); // only timestamp failed, so output is 2 APSARA_TEST_EQUAL_FATAL(uint64_t(2), processorInstance.mOutEventsTotal->GetValue()); APSARA_TEST_EQUAL_FATAL(uint64_t(1), processor.mDiscardedEventsTotal->GetValue()); APSARA_TEST_EQUAL_FATAL(uint64_t(1), processor.mOutFailedEventsTotal->GetValue()); } void ProcessorParseApsaraNativeUnittest::TestProcessKeyOverwritten() { // make config Json::Value config; config["SourceKey"] = "content"; config["KeepingSourceWhenParseFail"] = true; config["KeepingSourceWhenParseSucceed"] = true; config["CopingRawLog"] = true; config["RenamedSourceKey"] = "rawLog"; config["Timezone"] = ""; // make events auto sourceBuffer = std::make_shared<SourceBuffer>(); PipelineEventGroup eventGroup(sourceBuffer); std::string inJson = R"({ "events" : [ { "contents" : { "content" : "[2023-09-04 13:15:04.862181] [INFO] [385658] content:100 rawLog:success __raw_log__:success" }, "timestamp" : 12345678901, "type" : 1 }, { "contents" : { "content" : "value1" }, "timestamp" : 12345678901, "type" : 1 } ] })"; eventGroup.FromJsonString(inJson); // run function ProcessorParseApsaraNative& processor = *(new ProcessorParseApsaraNative); processor.SetContext(mContext); ProcessorInstance processorInstance(&processor, getPluginMeta()); APSARA_TEST_TRUE_FATAL(processorInstance.Init(config, mContext)); std::vector<PipelineEventGroup> eventGroupList; eventGroupList.emplace_back(std::move(eventGroup)); processorInstance.Process(eventGroupList); std::string expectJson = R"({ "events": [ { "contents": { "__LEVEL__": "INFO", "__THREAD__": "385658", "__raw_log__": "success", "content": "100", "microtime": "1693833304862181", "rawLog": "success" }, "timestamp": 1693833304, "timestampNanosecond": 862181000, "type": 1 }, { "contents" : { "__raw_log__": "value1", "rawLog": "value1" }, "timestamp": 12345678901, "type": 1 } ] })"; // judge result std::string outJson = eventGroupList[0].ToJsonString(); APSARA_TEST_STREQ_FATAL(CompactJson(expectJson).c_str(), CompactJson(outJson).c_str()); } void ProcessorParseApsaraNativeUnittest::TestUploadRawLog() { // make config Json::Value config; config["SourceKey"] = "content"; config["KeepingSourceWhenParseFail"] = true; config["KeepingSourceWhenParseSucceed"] = true; config["CopingRawLog"] = true; config["RenamedSourceKey"] = "rawLog"; config["Timezone"] = ""; // make events auto sourceBuffer = std::make_shared<SourceBuffer>(); PipelineEventGroup eventGroup(sourceBuffer); std::string inJson = R"({ "events" : [ { "contents" : { "content" : "[2023-09-04 13:15:04.862181] [INFO] [385658] /ilogtail/AppConfigBase.cpp:100 AppConfigBase AppConfigBase:success" }, "timestamp" : 12345678901, "type" : 1 }, { "contents" : { "content" : "value1" }, "timestamp" : 12345678901, "type" : 1 } ] })"; eventGroup.FromJsonString(inJson); // run function ProcessorParseApsaraNative& processor = *(new ProcessorParseApsaraNative); processor.SetContext(mContext); ProcessorInstance processorInstance(&processor, getPluginMeta()); APSARA_TEST_TRUE_FATAL(processorInstance.Init(config, mContext)); std::vector<PipelineEventGroup> eventGroupList; eventGroupList.emplace_back(std::move(eventGroup)); processorInstance.Process(eventGroupList); std::string expectJson = R"({ "events": [ { "contents": { "/ilogtail/AppConfigBase.cpp": "100", "AppConfigBase AppConfigBase": "success", "__LEVEL__": "INFO", "__THREAD__": "385658", "microtime": "1693833304862181", "rawLog" : "[2023-09-04 13:15:04.862181]\t[INFO]\t[385658]\t/ilogtail/AppConfigBase.cpp:100\t\tAppConfigBase AppConfigBase:success" }, "timestamp": 1693833304, "timestampNanosecond": 862181000, "type": 1 }, { "contents" : { "__raw_log__": "value1", "rawLog": "value1" }, "timestamp": 12345678901, "type": 1 } ] })"; // judge result std::string outJson = eventGroupList[0].ToJsonString(); APSARA_TEST_STREQ_FATAL(CompactJson(expectJson).c_str(), CompactJson(outJson).c_str()); } void ProcessorParseApsaraNativeUnittest::TestAddLog() { // make config Json::Value config; config["SourceKey"] = "content"; config["KeepingSourceWhenParseFail"] = true; config["KeepingSourceWhenParseSucceed"] = false; config["CopingRawLog"] = false; config["RenamedSourceKey"] = "rawLog"; ProcessorParseApsaraNative& processor = *(new ProcessorParseApsaraNative); processor.SetContext(mContext); ProcessorInstance processorInstance(&processor, getPluginMeta()); APSARA_TEST_TRUE_FATAL(processorInstance.Init(config, mContext)); auto eventGroup = PipelineEventGroup(std::make_shared<SourceBuffer>()); auto logEvent = eventGroup.CreateLogEvent(); char key[] = "key"; char value[] = "value"; processor.AddLog(key, value, *logEvent); // check observability // Todo: add metrics for check result } void ProcessorParseApsaraNativeUnittest::TestProcessEventKeepUnmatch() { // make config Json::Value config; config["SourceKey"] = "content"; config["KeepingSourceWhenParseFail"] = true; config["KeepingSourceWhenParseSucceed"] = false; config["CopingRawLog"] = false; config["RenamedSourceKey"] = "rawLog"; // make events auto sourceBuffer = std::make_shared<SourceBuffer>(); PipelineEventGroup eventGroup(sourceBuffer); std::string inJson = R"({ "events" : [ { "contents" : { "content" : "value1" }, "timestamp" : 12345678901, "type" : 1 }, { "contents" : { "content" : "value1" }, "timestamp" : 12345678901, "type" : 1 }, { "contents" : { "content" : "value1" }, "timestamp" : 12345678901, "type" : 1 }, { "contents" : { "content" : "value1" }, "timestamp" : 12345678901, "type" : 1 }, { "contents" : { "content" : "value1" }, "timestamp" : 12345678901, "type" : 1 } ] })"; eventGroup.FromJsonString(inJson); // run function ProcessorParseApsaraNative& processor = *(new ProcessorParseApsaraNative); ProcessorInstance processorInstance(&processor, getPluginMeta()); APSARA_TEST_TRUE_FATAL(processorInstance.Init(config, mContext)); std::vector<PipelineEventGroup> eventGroupList; eventGroupList.emplace_back(std::move(eventGroup)); processorInstance.Process(eventGroupList); // judge result std::string expectJson = R"({ "events" : [ { "contents" : { "rawLog" : "value1" }, "timestamp" : 12345678901, "type" : 1 }, { "contents" : { "rawLog" : "value1" }, "timestamp" : 12345678901, "type" : 1 }, { "contents" : { "rawLog" : "value1" }, "timestamp" : 12345678901, "type" : 1 }, { "contents" : { "rawLog" : "value1" }, "timestamp" : 12345678901, "type" : 1 }, { "contents" : { "rawLog" : "value1" }, "timestamp" : 12345678901, "type" : 1 } ] })"; std::string outJson = eventGroupList[0].ToJsonString(); APSARA_TEST_STREQ_FATAL(CompactJson(expectJson).c_str(), CompactJson(outJson).c_str()); // check observablity int count = 5; APSARA_TEST_EQUAL_FATAL(uint64_t(count), processorInstance.mInEventsTotal->GetValue()); APSARA_TEST_EQUAL_FATAL(uint64_t(count), processorInstance.mOutEventsTotal->GetValue()); APSARA_TEST_EQUAL_FATAL(uint64_t(0), processor.mDiscardedEventsTotal->GetValue()); APSARA_TEST_EQUAL_FATAL(uint64_t(count), processor.mOutFailedEventsTotal->GetValue()); } void ProcessorParseApsaraNativeUnittest::TestProcessEventDiscardUnmatch() { // make config Json::Value config; config["SourceKey"] = "content"; config["KeepingSourceWhenParseFail"] = false; config["KeepingSourceWhenParseSucceed"] = false; config["CopingRawLog"] = false; config["RenamedSourceKey"] = "rawLog"; // make events auto sourceBuffer = std::make_shared<SourceBuffer>(); PipelineEventGroup eventGroup(sourceBuffer); std::string inJson = R"({ "events" : [ { "contents" : { "content" : "value1" }, "timestamp" : 12345678901, "type" : 1 }, { "contents" : { "content" : "value1" }, "timestamp" : 12345678901, "type" : 1 }, { "contents" : { "content" : "value1" }, "timestamp" : 12345678901, "type" : 1 }, { "contents" : { "content" : "value1" }, "timestamp" : 12345678901, "type" : 1 }, { "contents" : { "content" : "value1" }, "timestamp" : 12345678901, "type" : 1 } ] })"; eventGroup.FromJsonString(inJson); // run function ProcessorParseApsaraNative& processor = *(new ProcessorParseApsaraNative); ProcessorInstance processorInstance(&processor, getPluginMeta()); APSARA_TEST_TRUE_FATAL(processorInstance.Init(config, mContext)); std::vector<PipelineEventGroup> eventGroupList; eventGroupList.emplace_back(std::move(eventGroup)); processorInstance.Process(eventGroupList); // judge result std::string outJson = eventGroupList[0].ToJsonString(); APSARA_TEST_STREQ_FATAL("null", CompactJson(outJson).c_str()); // check observablity int count = 5; APSARA_TEST_EQUAL_FATAL(uint64_t(count), processorInstance.mInEventsTotal->GetValue()); // discard unmatch, so output is 0 APSARA_TEST_EQUAL_FATAL(uint64_t(0), processorInstance.mOutEventsTotal->GetValue()); // event group size is not 0 APSARA_TEST_NOT_EQUAL_FATAL(uint64_t(0), processorInstance.mOutSizeBytes->GetValue()); APSARA_TEST_EQUAL_FATAL(uint64_t(count), processor.mDiscardedEventsTotal->GetValue()); APSARA_TEST_EQUAL_FATAL(uint64_t(count), processor.mOutFailedEventsTotal->GetValue()); } void ProcessorParseApsaraNativeUnittest::TestProcessEventMicrosecondUnmatch() { // make config Json::Value config; config["SourceKey"] = "content"; config["KeepingSourceWhenParseFail"] = true; config["KeepingSourceWhenParseSucceed"] = false; config["CopingRawLog"] = false; config["RenamedSourceKey"] = "rawLog"; // make events auto sourceBuffer = std::make_shared<SourceBuffer>(); PipelineEventGroup eventGroup(sourceBuffer); std::string inJson = R"({ "events" : [ { "contents" : { "content" : "[2023-09-04 13:15:04,862181] [INFO] [385658] /ilogtail/AppConfigBase.cpp:100 AppConfigBase AppConfigBase:success" }, "timestamp" : 12345678901, "type" : 1 }, { "contents" : { "content" : "[2023-09-04 13:16:04] [INFO] [385658] /ilogtail/AppConfigBase.cpp:100 AppConfigBase AppConfigBase:success" }, "timestamp" : 12345678901, "type" : 1 }, { "contents" : { "content" : "[2023-09-04 13:17:04,1] [INFO] [385658] /ilogtail/AppConfigBase.cpp:100 AppConfigBase AppConfigBase:success" }, "timestamp" : 12345678901, "type" : 1 }, { "contents" : { "content" : "[2023-09-04 13:18:04" }, "timestamp" : 12345678901, "type" : 1 } ] })"; eventGroup.FromJsonString(inJson); // run function ProcessorParseApsaraNative& processor = *(new ProcessorParseApsaraNative); ProcessorInstance processorInstance(&processor, getPluginMeta()); APSARA_TEST_TRUE_FATAL(processorInstance.Init(config, mContext)); std::vector<PipelineEventGroup> eventGroupList; eventGroupList.emplace_back(std::move(eventGroup)); processorInstance.Process(eventGroupList); // judge result std::string expectJson = R"({ "events": [ { "contents": { "/ilogtail/AppConfigBase.cpp": "100", "AppConfigBase AppConfigBase": "success", "__LEVEL__": "INFO", "__THREAD__": "385658", "microtime": "1693833304862181" }, "timestamp": 1693833304, "timestampNanosecond": 862181000, "type": 1 }, { "contents": { "/ilogtail/AppConfigBase.cpp": "100", "AppConfigBase AppConfigBase": "success", "__LEVEL__": "INFO", "__THREAD__": "385658", "microtime": "1693833364000000" }, "timestamp": 1693833364, "timestampNanosecond": 0, "type": 1 }, { "contents": { "/ilogtail/AppConfigBase.cpp": "100", "AppConfigBase AppConfigBase": "success", "__LEVEL__": "INFO", "__THREAD__": "385658", "microtime": "1693833424100000" }, "timestamp": 1693833424, "timestampNanosecond": 100000000, "type": 1 }, { "contents": { "rawLog": "[2023-09-04 13:18:04" }, "timestamp": 12345678901, "type": 1 } ] })"; std::string outJson = eventGroupList[0].ToJsonString(); APSARA_TEST_STREQ_FATAL(CompactJson(expectJson).c_str(), CompactJson(outJson).c_str()); // check observablity APSARA_TEST_EQUAL_FATAL(uint64_t(4), processorInstance.mInEventsTotal->GetValue()); APSARA_TEST_EQUAL_FATAL(uint64_t(4), processorInstance.mOutEventsTotal->GetValue()); APSARA_TEST_EQUAL_FATAL(uint64_t(0), processor.mDiscardedEventsTotal->GetValue()); APSARA_TEST_EQUAL_FATAL(uint64_t(1), processor.mOutFailedEventsTotal->GetValue()); } } // namespace logtail UNIT_TEST_MAIN