core/models/LogEvent.cpp (152 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 "models/LogEvent.h"
using namespace std;
namespace logtail {
LogEvent::LogEvent(PipelineEventGroup* ptr) : PipelineEvent(Type::LOG, ptr) {
}
unique_ptr<PipelineEvent> LogEvent::Copy() const {
return make_unique<LogEvent>(*this);
}
void LogEvent::Reset() {
PipelineEvent::Reset();
mContents.clear();
mIndex.clear();
mAllocatedContentSize = 0;
mFileOffset = 0;
mRawSize = 0;
}
StringView LogEvent::GetContent(StringView key) const {
auto it = mIndex.find(key);
if (it != mIndex.end()) {
return mContents[it->second].first.second;
}
return gEmptyStringView;
}
bool LogEvent::HasContent(StringView key) const {
return mIndex.find(key) != mIndex.end();
}
void LogEvent::SetContent(StringView key, StringView val) {
SetContentNoCopy(GetSourceBuffer()->CopyString(key), GetSourceBuffer()->CopyString(val));
}
void LogEvent::SetContent(const string& key, const string& val) {
SetContentNoCopy(GetSourceBuffer()->CopyString(key), GetSourceBuffer()->CopyString(val));
}
void LogEvent::SetContent(const StringBuffer& key, StringView val) {
SetContentNoCopy(key, GetSourceBuffer()->CopyString(val));
}
void LogEvent::SetContentNoCopy(const StringBuffer& key, const StringBuffer& val) {
SetContentNoCopy(StringView(key.data, key.size), StringView(val.data, val.size));
}
void LogEvent::SetContentNoCopy(StringView key, StringView val) {
auto rst = mIndex.insert(make_pair(key, mContents.size()));
if (!rst.second) {
auto& it = rst.first;
auto& field = mContents[it->second].first;
mAllocatedContentSize += key.size() + val.size() - field.first.size() - field.second.size();
field = make_pair(key, val);
} else {
mAllocatedContentSize += key.size() + val.size();
mContents.emplace_back(make_pair(key, val), true);
}
}
void LogEvent::DelContent(StringView key) {
auto it = mIndex.find(key);
if (it != mIndex.end()) {
auto& field = mContents[it->second].first;
mAllocatedContentSize -= field.first.size() + field.second.size();
mContents[it->second].second = false;
mIndex.erase(it);
}
}
void LogEvent::SetLevel(const std::string& level) {
const StringBuffer& b = GetSourceBuffer()->CopyString(level);
mLevel = StringView(b.data, b.size);
}
LogEvent::ContentIterator LogEvent::FindContent(StringView key) {
auto it = mIndex.find(key);
if (it != mIndex.end()) {
return ContentIterator(mContents.begin() + it->second, mContents);
}
return ContentIterator(mContents.end(), mContents);
}
LogEvent::ConstContentIterator LogEvent::FindContent(StringView key) const {
auto it = mIndex.find(key);
if (it != mIndex.end()) {
return ConstContentIterator(mContents.begin() + it->second, mContents);
}
return ConstContentIterator(mContents.end(), mContents);
}
LogEvent::ContentIterator LogEvent::begin() {
auto it = mContents.begin();
while (it != mContents.end() && !it->second) {
++it;
}
return ContentIterator(it, mContents);
}
LogEvent::ContentIterator LogEvent::end() {
mContents.end() == mContents.end();
return ContentIterator(mContents.end(), mContents);
}
LogEvent::ConstContentIterator LogEvent::begin() const {
return cbegin();
}
LogEvent::ConstContentIterator LogEvent::end() const {
return cend();
}
LogEvent::ConstContentIterator LogEvent::cbegin() const {
auto it = mContents.cbegin();
while (it != mContents.cend() && !it->second) {
++it;
}
return ConstContentIterator(it, mContents);
}
LogEvent::ConstContentIterator LogEvent::cend() const {
return ConstContentIterator(mContents.cend(), mContents);
}
void LogEvent::AppendContentNoCopy(StringView key, StringView val) {
mAllocatedContentSize += key.size() + val.size();
mContents.emplace_back(make_pair(key, val), true);
mIndex[key] = mContents.size() - 1;
}
size_t LogEvent::DataSize() const {
return PipelineEvent::DataSize() + sizeof(decltype(mContents)) + mAllocatedContentSize;
}
#ifdef APSARA_UNIT_TEST_MAIN
Json::Value LogEvent::ToJson(bool enableEventMeta) const {
Json::Value root;
root["type"] = static_cast<int>(GetType());
root["timestamp"] = GetTimestamp();
if (GetTimestampNanosecond()) {
root["timestampNanosecond"] = static_cast<int32_t>(GetTimestampNanosecond().value());
}
if (enableEventMeta) {
root["fileOffset"] = GetPosition().first;
root["rawSize"] = GetPosition().second;
}
if (!Empty()) {
Json::Value contents;
for (const auto& content : *this) {
contents[content.first.to_string()] = content.second.to_string();
}
root["contents"] = std::move(contents);
}
return root;
}
bool LogEvent::FromJson(const Json::Value& root) {
if (root.isMember("timestampNanosecond")) {
SetTimestamp(root["timestamp"].asInt64(), root["timestampNanosecond"].asInt64());
} else {
SetTimestamp(root["timestamp"].asInt64());
}
if (root.isMember("fileOffset") && root.isMember("rawSize")) {
SetPosition(root["fileOffset"].asUInt64(), root["rawSize"].asUInt64());
}
if (root.isMember("contents")) {
Json::Value contents = root["contents"];
for (const auto& key : contents.getMemberNames()) {
// 单测需要,每个key需要独立的内存空间
SetContent(GetSourceBuffer()->CopyString(key), contents[key].asString());
}
}
return true;
}
#endif
} // namespace logtail