-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathevent_generation.cpp
More file actions
163 lines (144 loc) · 5.64 KB
/
Copy pathevent_generation.cpp
File metadata and controls
163 lines (144 loc) · 5.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
// Unless explicitly stated otherwise all files in this repository are licensed
// under the Apache License Version 2.0.
//
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2025-Present Datadog, Inc.
#include "datadog/impl/logging/event_generation.hpp"
#include <string_view>
#include "datadog/impl/core/feature_message.hpp"
#include "datadog/impl/core/feature_types/logging.hpp"
#include "datadog/impl/core/platform/system_info.hpp"
#include "datadog/impl/core/upload_util.hpp"
#include "datadog/impl/core/util/assert.hpp"
#include "datadog/impl/core/util/json.hpp"
#include "datadog/impl/logging/data.hpp"
namespace datadog::impl {
void ContextThread_GenerateLogEvent(
const LoggerConfigDetails& logger,
LogCallDetails call,
const CoreContext& ctx,
const EventWriter& event_writer,
std::vector<uint8_t>& encode_buf,
const MessagePublisher& publisher
) {
// Use the overridden service name configured for this Logger if we have one;
// otherwise fall back to the service name from SDK config
std::string_view service_name = logger.service_override;
if (service_name.empty()) {
service_name = ctx.service;
}
// If the logger has no service override and no custom tags, we can use the immutable
// ddtags value provided via CoreContext
std::string_view ddtags = ctx.per_event_ddtags;
// Otherwise, we need to build a fresh ddtags string that incorporates all the
// relevant details from `CoreContext`, plus any service override or additional tags
// configured for this logger
std::string override_ddtags;
if (!logger.service_override.empty() || !call.logger_tags.empty()) {
override_ddtags = BuildDdTags(
logger.service_override.empty() ? ctx.service : logger.service_override,
ctx.application_version,
ctx.env,
ctx.sdk_version,
ctx.variant,
call.logger_tags
);
ddtags = override_ddtags;
}
// Construct a LogEvent with all required values, moving our original copy of the
// application-provided message into the event struct
LogEvent ev{
call.level,
service_name,
call.timestamp,
std::move(call.message),
ddtags,
logger.name,
ctx.sdk_version
};
// If configured to do so, add RUM IDs for any active session/view/action
if (logger.enrich_with_rum_context && ctx.rum.has_value()) {
// These fields are OmitIfZero<UUID>, so if no session/view/action is currently
// active, the corresponding field will be omitted from the event as intended
ev.rum_application_id = ctx.rum->application_id;
ev.rum_session_id = ctx.rum->session_id;
ev.rum_view_id = ctx.rum->view_id;
ev.rum_action_id = ctx.rum->action_id;
}
// If the SDK has been given valid user info, add it to 'usr'
if (!ctx.user_info.IsEmpty()) {
LogUserInfo& usr = ev.usr.value.emplace();
usr.id = ctx.user_info.id;
usr.name = ctx.user_info.name;
usr.email = ctx.user_info.email;
usr.extra = ctx.user_info.extra;
}
// If the SDK has been given valid account info, add it to 'account'
if (!ctx.account_info.IsEmpty()) {
LogAccountInfo& account = ev.account.value.emplace();
account.id = ctx.account_info.id;
account.name = ctx.account_info.name;
account.extra = ctx.account_info.extra;
}
// Add 'os' properties from OsInfo
if (ctx.os) {
RumOSProperties& os =
ev.os.value.emplace(ctx.os->name, ctx.os->version, ctx.os->version_major);
if (!ctx.os->build.empty()) {
os.build = ctx.os->build;
}
}
// Add 'device' properties from DeviceInfo
if (ctx.device) {
RumDeviceProperties& device = ev.device.value.emplace();
if (!ctx.device->type.empty()) {
// Currently, ISystemInfo only produces a value of "desktop"; if it uses other
// values we'll need to actually parse to RumDeviceType here (or use an enum in
// DeviceInfo)
DATADOG_ASSERT(
ctx.device->type == "desktop",
"DeviceInfo specifies non-desktop platform; log event serialization code "
"must be updated"
);
device.type = RumDeviceType::Desktop;
}
device.name = ctx.device->name;
device.model = ctx.device->model;
device.brand = ctx.device->brand;
device.architecture = ctx.device->architecture;
device.locale = ctx.device->locale;
device.time_zone = ctx.device->time_zone;
}
// Add any error details provided with this call
ev.error_message = std::move(call.error_message);
ev.error_kind = std::move(call.error_kind);
ev.error_stack = std::move(call.error_stack);
// Add extra user attributes, to be merged into the event payload as top-level JSON
// properties
ev.user_attributes = std::move(call.merged_attributes);
// Encode to the shared buffer (accessed only on context thread)
EncodeJson(encode_buf, ev);
std::string_view data{
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
reinterpret_cast<const char*>(encode_buf.data()),
encode_buf.size()
};
// Enqueue the event for storage
const bool bypass_tracking_consent = false;
event_writer(data, {}, bypass_tracking_consent);
// After writing the log event, forward it to RUM as an error event: LogEvent owns
// strings and attributes that will simply go out of scope after this call, so we can
// transfer ownership of those values into the message
if (call.level >= LogLevel::Error) {
publisher(
LogErrorGeneratedMessage{
call.timestamp,
std::move(ev.error_message.value),
std::move(ev.error_kind.value),
std::move(ev.error_stack.value),
std::move(ev.user_attributes),
}
);
}
}
} // namespace datadog::impl