Skip to content

Commit 438453b

Browse files
committed
Performance improvement in logs
1 parent a16b03e commit 438453b

File tree

2 files changed

+104
-72
lines changed

2 files changed

+104
-72
lines changed

api/logs/+opentelemetry/+logs/Logger.m

Lines changed: 59 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,10 @@ function emitLogRecord(obj, severity, body, trailingnames, trailingvalues)
6565
% severity text
6666
% Support 24 valid severity levels: trace, trace2, trace3,
6767
% trace4, debug, debug2, debug3, ...
68-
severitylist = ["trace", "debug", "info", "warn", "error", "fatal"];
69-
severitylist = reshape(severitylist + [""; "2"; "3"; "4"], 1, []);
68+
severitylist = ["trace" "trace2" "trace3" "trace4" "debug" ...
69+
"debug2" "debug3" "debug4" "info" "info2" "info3" "info4" ...
70+
"warn" "warn2" "warn3" "warn4" "error" "error2" "error3" ...
71+
"error4" "fatal" "fatal2" "fatal3" "fatal4"];
7072
d = dictionary(severitylist, 1:length(severitylist));
7173
try
7274
severity = d(lower(severity));
@@ -81,39 +83,59 @@ function emitLogRecord(obj, severity, body, trailingnames, trailingvalues)
8183
% body
8284
body = convertCharsToStrings(body); % force char rows into strings
8385

84-
% validate the trailing names and values
85-
optionnames = ["Context", "Timestamp", "Attributes"];
86-
87-
% define default values
88-
contextid = intmax("uint64"); % default value which means no context supplied
89-
timestamp = NaN;
90-
attributekeys = string.empty();
91-
attributevalues = {};
92-
93-
% Loop through Name-Value pairs
94-
for i = 1:length(trailingnames)
95-
try
96-
namei = validatestring(trailingnames{i}, optionnames);
97-
catch
98-
% invalid option, ignore
99-
continue
100-
end
101-
if strcmp(namei, "Context")
102-
context = trailingvalues{i};
103-
if isa(context, "opentelemetry.context.Context")
104-
contextid = context.Proxy.ID;
86+
if nargin <= 3
87+
obj.Proxy.emitLogRecord(severity, body);
88+
else
89+
% validate the trailing names and values
90+
optionnames = ["Context", "Timestamp", "Attributes"];
91+
92+
% define default values
93+
contextid = intmax("uint64"); % default value which means no context supplied
94+
timestamp = NaN;
95+
attributekeys = string.empty();
96+
attributevalues = {};
97+
98+
% variables to keep track of which proxy function to call
99+
specifyoptions = false;
100+
specifyattributes = false;
101+
102+
% Loop through Name-Value pairs
103+
for i = 1:length(trailingnames)
104+
try
105+
namei = validatestring(trailingnames{i}, optionnames);
106+
catch
107+
% invalid option, ignore
108+
continue
105109
end
106-
elseif strcmp(namei, "Timestamp")
107-
valuei = trailingvalues{i};
108-
if isdatetime(valuei) && isscalar(valuei) && ~isnat(valuei)
109-
timestamp = posixtime(valuei);
110+
if strcmp(namei, "Context")
111+
context = trailingvalues{i};
112+
if isa(context, "opentelemetry.context.Context")
113+
contextid = context.Proxy.ID;
114+
specifyoptions = true;
115+
end
116+
elseif strcmp(namei, "Timestamp")
117+
valuei = trailingvalues{i};
118+
if isdatetime(valuei) && isscalar(valuei) && ~isnat(valuei)
119+
timestamp = posixtime(valuei);
120+
specifyoptions = true;
121+
end
122+
elseif strcmp(namei, "Attributes")
123+
[attributekeys, attributevalues] = processAttributes(trailingvalues{i}, true);
124+
specifyattributes = true;
110125
end
111-
elseif strcmp(namei, "Attributes")
112-
[attributekeys, attributevalues] = processAttributes(trailingvalues{i}, true);
126+
end
127+
128+
if ~specifyoptions && ~specifyattributes
129+
obj.Proxy.emitLogRecord(severity, body);
130+
elseif specifyoptions && ~specifyattributes
131+
obj.Proxy.emitLogRecord(severity, body, contextid, timestamp);
132+
elseif ~specifyoptions && specifyattributes
133+
obj.Proxy.emitLogRecord(severity, body, attributekeys, attributevalues);
134+
else % specifyoptions && specifyattributes
135+
obj.Proxy.emitLogRecord(severity, body, contextid, timestamp, ...
136+
attributekeys, attributevalues);
113137
end
114138
end
115-
obj.Proxy.emitLogRecord(severity, body, contextid, timestamp, ...
116-
attributekeys, attributevalues);
117139
end
118140

119141
function trace(obj, body, varargin)
@@ -134,7 +156,7 @@ function trace(obj, body, varargin)
134156
% OPENTELEMETRY.LOGS.INFO, OPENTELEMETRY.LOGS.WARN,
135157
% OPENTELEMETRY.LOGS.ERROR, OPENTELEMETRY.LOGS.FATAL,
136158
% OPENTELEMETRY.LOGS.EMITLOGRECORD
137-
emitLogRecord(obj, "trace", body, varargin{:});
159+
emitLogRecord(obj, 1, body, varargin{:});
138160
end
139161

140162
function debug(obj, body, varargin)
@@ -155,7 +177,7 @@ function debug(obj, body, varargin)
155177
% OPENTELEMETRY.LOGS.INFO, OPENTELEMETRY.LOGS.WARN,
156178
% OPENTELEMETRY.LOGS.ERROR, OPENTELEMETRY.LOGS.FATAL,
157179
% OPENTELEMETRY.LOGS.EMITLOGRECORD
158-
emitLogRecord(obj, "debug", body, varargin{:});
180+
emitLogRecord(obj, 5, body, varargin{:});
159181
end
160182

161183
function info(obj, body, varargin)
@@ -176,7 +198,7 @@ function info(obj, body, varargin)
176198
% OPENTELEMETRY.LOGS.DEBUG, OPENTELEMETRY.LOGS.WARN,
177199
% OPENTELEMETRY.LOGS.ERROR, OPENTELEMETRY.LOGS.FATAL,
178200
% OPENTELEMETRY.LOGS.EMITLOGRECORD
179-
emitLogRecord(obj, "info", body, varargin{:});
201+
emitLogRecord(obj, 9, body, varargin{:});
180202
end
181203

182204
function warn(obj, body, varargin)
@@ -197,7 +219,7 @@ function warn(obj, body, varargin)
197219
% OPENTELEMETRY.LOGS.DEBUG, OPENTELEMETRY.LOGS.INFO,
198220
% OPENTELEMETRY.LOGS.ERROR, OPENTELEMETRY.LOGS.FATAL,
199221
% OPENTELEMETRY.LOGS.EMITLOGRECORD
200-
emitLogRecord(obj, "warn", body, varargin{:});
222+
emitLogRecord(obj, 13, body, varargin{:});
201223
end
202224

203225
function error(obj, body, varargin)
@@ -218,7 +240,7 @@ function error(obj, body, varargin)
218240
% OPENTELEMETRY.LOGS.DEBUG, OPENTELEMETRY.LOGS.INFO,
219241
% OPENTELEMETRY.LOGS.WARN, OPENTELEMETRY.LOGS.FATAL,
220242
% OPENTELEMETRY.LOGS.EMITLOGRECORD
221-
emitLogRecord(obj, "error", body, varargin{:});
243+
emitLogRecord(obj, 17, body, varargin{:});
222244
end
223245

224246
function fatal(obj, body, varargin)
@@ -239,7 +261,7 @@ function fatal(obj, body, varargin)
239261
% OPENTELEMETRY.LOGS.DEBUG, OPENTELEMETRY.LOGS.INFO,
240262
% OPENTELEMETRY.LOGS.WARN, OPENTELEMETRY.LOGS.ERROR,
241263
% OPENTELEMETRY.LOGS.EMITLOGRECORD
242-
emitLogRecord(obj, "fatal", body, varargin{:});
264+
emitLogRecord(obj, 21, body, varargin{:});
243265
end
244266
end
245267

api/logs/src/LoggerProxy.cpp

Lines changed: 45 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,10 @@ namespace nostd = opentelemetry::nostd;
2020

2121
namespace libmexclass::opentelemetry {
2222
void LoggerProxy::emitLogRecord(libmexclass::proxy::method::Context& context) {
23+
const size_t ninputs = context.inputs.getNumberOfElements();
2324
matlab::data::TypedArray<double> severity_mda = context.inputs[0];
2425
int severity = static_cast<int>(severity_mda[0]);
2526
matlab::data::Array body_mda = context.inputs[1];
26-
matlab::data::TypedArray<uint64_t> contextid_mda = context.inputs[2];
27-
libmexclass::proxy::ID contextid = contextid_mda[0];
28-
libmexclass::proxy::ID nocontextid(-1); // wrap around to intmax
29-
matlab::data::TypedArray<double> timestamp_mda = context.inputs[3];
30-
double timestamp = timestamp_mda[0]; // number of seconds since 1/1/1970 (i.e. POSIX time)
31-
matlab::data::StringArray attrnames_mda = context.inputs[4];
32-
size_t nattrs = attrnames_mda.getNumberOfElements();
33-
matlab::data::CellArray attrvalues_mda = context.inputs[5];
3427

3528
// log body
3629
ProcessedAttributes bodyattrs;
@@ -47,39 +40,56 @@ void LoggerProxy::emitLogRecord(libmexclass::proxy::method::Context& context) {
4740

4841
nostd::unique_ptr<logs_api::LogRecord> rec = CppLogger->CreateLogRecord();
4942

50-
// context
51-
if (contextid != nocontextid) {
52-
context_api::Context supplied_context = std::static_pointer_cast<ContextProxy>(
53-
libmexclass::proxy::ProxyManager::getProxy(contextid))->getInstance();
54-
trace_api::SpanContext sc = trace_api::GetSpan(supplied_context)->GetContext();
55-
rec->SetTraceId(sc.trace_id());
56-
rec->SetSpanId(sc.span_id());
57-
rec->SetTraceFlags(sc.trace_flags());
43+
// Add size attribute if body is nonscalar
44+
if (array_body) {
45+
rec->SetAttribute(bodyattrs.Attributes.back().first, bodyattrs.Attributes.back().second);
5846
}
5947

60-
// timestamp
61-
if (timestamp == timestamp) { // not NaN. NaN means not specified
62-
rec->SetTimestamp(common::SystemTimestamp{std::chrono::duration<double>(timestamp)});
63-
}
48+
if (ninputs > 2) {
49+
size_t curridx = 2;
50+
matlab::data::Array firstoption = context.inputs[curridx]; // check third input type whether it's a proxy ID
51+
bool first_option_is_id = (firstoption.getType() == matlab::data::ArrayType::UINT64);
52+
if (first_option_is_id) {
53+
// context
54+
matlab::data::TypedArray<uint64_t> contextid_mda = context.inputs[curridx++];
55+
libmexclass::proxy::ID contextid = contextid_mda[0];
56+
const libmexclass::proxy::ID nocontextid = -1; // wrap around to intmax
57+
if (contextid != nocontextid) {
58+
context_api::Context supplied_context = std::static_pointer_cast<ContextProxy>(
59+
libmexclass::proxy::ProxyManager::getProxy(contextid))->getInstance();
60+
trace_api::SpanContext sc = trace_api::GetSpan(supplied_context)->GetContext();
61+
rec->SetTraceId(sc.trace_id());
62+
rec->SetSpanId(sc.span_id());
63+
rec->SetTraceFlags(sc.trace_flags());
64+
}
6465

65-
// attributes
66-
ProcessedAttributes attrs;
67-
if (nattrs > 0) {
68-
for (size_t i = 0; i < nattrs; ++i) {
69-
std::string attrname = static_cast<std::string>(attrnames_mda[i]);
70-
matlab::data::Array attrvalue = attrvalues_mda[i];
66+
// timestamp
67+
matlab::data::TypedArray<double> timestamp_mda = context.inputs[curridx++];
68+
double timestamp = timestamp_mda[0]; // number of seconds since 1/1/1970 (i.e. POSIX time)
69+
if (timestamp == timestamp) { // not NaN. NaN means not specified
70+
rec->SetTimestamp(common::SystemTimestamp{std::chrono::duration<double>(timestamp)});
71+
}
72+
}
73+
74+
if (!first_option_is_id || ninputs > 4) {
75+
// attributes
76+
matlab::data::StringArray attrnames_mda = context.inputs[curridx++];
77+
size_t nattrs = attrnames_mda.getNumberOfElements();
78+
matlab::data::CellArray attrvalues_mda = context.inputs[curridx];
79+
ProcessedAttributes attrs;
80+
if (nattrs > 0) {
81+
for (size_t i = 0; i < nattrs; ++i) {
82+
std::string attrname = static_cast<std::string>(attrnames_mda[i]);
83+
matlab::data::Array attrvalue = attrvalues_mda[i];
7184

72-
processAttribute(attrname, attrvalue, attrs);
85+
processAttribute(attrname, attrvalue, attrs);
86+
}
87+
auto record_attribute = [&](const std::pair<std::string, common::AttributeValue> attr)
88+
{rec->SetAttribute(attr.first, attr.second);};
89+
std::for_each(attrs.Attributes.cbegin(), attrs.Attributes.cend(), record_attribute);
90+
}
7391
}
74-
auto record_attribute = [&](const std::pair<std::string, common::AttributeValue> attr)
75-
{rec->SetAttribute(attr.first, attr.second);};
76-
std::for_each(attrs.Attributes.cbegin(), attrs.Attributes.cend(), record_attribute);
77-
}
78-
// Add size attribute if body is nonscalar
79-
if (array_body) {
80-
rec->SetAttribute(bodyattrs.Attributes.back().first, bodyattrs.Attributes.back().second);
8192
}
82-
8393
CppLogger->EmitLogRecord(std::move(rec), static_cast<logs_api::Severity>(severity), log_body);
8494
}
8595
} // namespace libmexclass::opentelemetry

0 commit comments

Comments
 (0)