Skip to content

Commit f21e7c6

Browse files
committed
Fixing merge conflicts
2 parents 8c3a10c + 60acf06 commit f21e7c6

File tree

8 files changed

+238
-67
lines changed

8 files changed

+238
-67
lines changed

api/metrics/+opentelemetry/+metrics/MeterProvider.m

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
% Copyright 2023 The MathWorks, Inc.
66

7-
properties (Access={?opentelemetry.sdk.metrics.MeterProvider})
7+
properties (Access={?opentelemetry.sdk.metrics.MeterProvider, ?opentelemetry.sdk.metrics.Cleanup})
88
Proxy % Proxy object to interface C++ code
99
end
1010

@@ -59,4 +59,11 @@ function setMeterProvider(obj)
5959
obj.Proxy.setMeterProvider();
6060
end
6161
end
62+
63+
methods(Access=?opentelemetry.sdk.metrics.Cleanup)
64+
function postShutdown(obj)
65+
% POSTSHUTDOWN Handle post-shutdown tasks
66+
obj.Proxy.postShutdown();
67+
end
68+
end
6269
end
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
function meter = getMeter(mname, varargin)
2+
% Create a meter from the global meter provider instance
3+
% M = OPENTELEMETRY.METRICS.GETMETER(NAME) returns a meter with the
4+
% specified name created from the global meter provider instance.
5+
%
6+
% M = OPENTELEMETRY.METRICS.GETMETER(NAME, VERSION, SCHEMA) also
7+
% specifies the meter version and the URL that documents the schema
8+
% of the generated metrics.
9+
%
10+
% See also OPENTELEMETRY.SDK.METRICS.METERPROVIDER,
11+
% OPENTELEMETRY.METRICS.METER,
12+
% OPENTELEMETRY.METRICS.PROVIDER.SETMETERPROVIDER
13+
14+
% Copyright 2023 The MathWorks, Inc.
15+
16+
provider = opentelemetry.metrics.Provider.getMeterProvider();
17+
meter = getMeter(provider, mname, varargin{:});

api/metrics/include/opentelemetry-matlab/metrics/MeterProviderProxy.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,15 @@
1313
#include "opentelemetry/metrics/noop.h"
1414

1515
namespace metrics_api = opentelemetry::metrics;
16-
namespace metrics_sdk = opentelemetry::sdk::metrics;
17-
namespace metrics_exporter = opentelemetry::exporter::otlp;
1816
namespace nostd = opentelemetry::nostd;
19-
namespace resource = opentelemetry::sdk::resource;
2017

2118
namespace libmexclass::opentelemetry {
2219
class MeterProviderProxy : public libmexclass::proxy::Proxy {
2320
public:
2421
MeterProviderProxy(nostd::shared_ptr<metrics_api::MeterProvider> mp) : CppMeterProvider(mp) {
2522
REGISTER_METHOD(MeterProviderProxy, getMeter);
2623
REGISTER_METHOD(MeterProviderProxy, setMeterProvider);
24+
REGISTER_METHOD(MeterProviderProxy, postShutdown);
2725
}
2826

2927
// Static make method should only be used by getMeterProvider. It gets the global instance
@@ -39,6 +37,12 @@ class MeterProviderProxy : public libmexclass::proxy::Proxy {
3937
nostd::shared_ptr<metrics_api::MeterProvider> getInstance() {
4038
return CppMeterProvider;
4139
}
40+
41+
void postShutdown(libmexclass::proxy::method::Context& context) {
42+
// Replace meter provider with a no-op instance. Subsequent metrics won't be recorded
43+
nostd::shared_ptr<metrics_api::MeterProvider> noop(new metrics_api::NoopMeterProvider);
44+
CppMeterProvider.swap(noop);
45+
}
4246

4347
protected:
4448
nostd::shared_ptr<metrics_api::MeterProvider> CppMeterProvider;
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
classdef Cleanup
2+
% Clean up methods for MeterProvider in the API
3+
4+
% Copyright 2023 The MathWorks, Inc.
5+
6+
methods (Static)
7+
function success = shutdown(mp)
8+
% SHUTDOWN Shutdown
9+
% SUCCESS = SHUTDOWN(MP) shuts down all metric readers associated with
10+
% API meter provider MP and return a logical that indicates
11+
% whether shutdown was successful.
12+
%
13+
% See also FORCEFLUSH
14+
15+
% return false if input is not the right type
16+
if isa(mp, "opentelemetry.metrics.MeterProvider")
17+
% convert to MeterProvider class in sdk
18+
try
19+
mpsdk = opentelemetry.sdk.metrics.MeterProvider(mp.Proxy);
20+
catch
21+
success = false;
22+
return
23+
end
24+
success = mpsdk.shutdown;
25+
postShutdown(mp);
26+
else
27+
success = false;
28+
end
29+
end
30+
31+
function success = forceFlush(mp, timeout)
32+
% FORCEFLUSH Force flush
33+
% SUCCESS = FORCEFLUSH(MP) immediately exports all metrics
34+
% that have not yet been exported. Returns a logical that
35+
% indicates whether force flush was successful.
36+
%
37+
% SUCCESS = FORCEFLUSH(MP, TIMEOUT) specifies a TIMEOUT
38+
% duration. Force flush must be completed within this time,
39+
% or else it will fail.
40+
%
41+
% See also SHUTDOWN
42+
43+
% return false if input is not the right type
44+
if isa(mp, "opentelemetry.metrics.MeterProvider")
45+
% convert to MeterProvider class in sdk
46+
try
47+
mpsdk = opentelemetry.sdk.metrics.MeterProvider(mp.Proxy);
48+
catch
49+
success = false;
50+
return
51+
end
52+
if nargin < 2 || ~isa(timeout, "duration")
53+
success = mpsdk.forceFlush;
54+
else
55+
success = mpsdk.forceFlush(timeout);
56+
end
57+
else
58+
success = false;
59+
end
60+
end
61+
end
62+
63+
end

sdk/metrics/+opentelemetry/+sdk/+metrics/MeterProvider.m

Lines changed: 67 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,10 @@
44

55
% Copyright 2023 The MathWorks, Inc.
66

7-
properties (Access=private)
7+
properties(Access=private)
88
isShutdown (1,1) logical = false
99
end
1010

11-
1211
properties (Access=public)
1312
MetricReader
1413
end
@@ -48,34 +47,49 @@
4847
optionvalues
4948
end
5049

51-
validnames = ["Resource"];
52-
resourcekeys = string.empty();
53-
resourcevalues = {};
54-
resource = dictionary(resourcekeys, resourcevalues);
55-
for i = 1:length(optionnames)
56-
namei = validatestring(optionnames{i}, validnames);
57-
valuei = optionvalues{i};
58-
if strcmp(namei, "Resource")
59-
if ~isa(valuei, "dictionary")
60-
error("opentelemetry:sdk:metrics:MeterProvider:InvalidResourceType", ...
61-
"Attibutes input must be a dictionary.");
62-
end
63-
resource = valuei;
64-
resourcekeys = keys(valuei);
65-
resourcevalues = values(valuei,"cell");
66-
% collapse one level of cells, as this may be due to
67-
% a behavior of dictionary.values
68-
if all(cellfun(@iscell, resourcevalues))
69-
resourcevalues = [resourcevalues{:}];
50+
% explicit call to superclass constructor to make it a no-op
51+
52+
53+
if isa(reader, "libmexclass.proxy.Proxy")
54+
% This code branch is used to support conversion from API
55+
% MeterProvider to SDK equivalent, needed internally by
56+
% opentelemetry.sdk.metrics.Cleanup
57+
mpproxy = reader; % rename the variable
58+
assert(mpproxy.Name == "libmexclass.opentelemetry.MeterProviderProxy");
59+
obj.Proxy = libmexclass.proxy.Proxy("Name", ...
60+
"libmexclass.opentelemetry.sdk.MeterProviderProxy", ...
61+
"ConstructorArguments", {mpproxy.ID});
62+
% leave other properties unassigned, they won't be used
63+
else
64+
validnames = ["Resource"];
65+
resourcekeys = string.empty();
66+
resourcevalues = {};
67+
resource = dictionary(resourcekeys, resourcevalues);
68+
for i = 1:length(optionnames)
69+
namei = validatestring(optionnames{i}, validnames);
70+
valuei = optionvalues{i};
71+
if strcmp(namei, "Resource")
72+
if ~isa(valuei, "dictionary")
73+
error("opentelemetry:sdk:metrics:MeterProvider:InvalidResourceType", ...
74+
"Attibutes input must be a dictionary.");
75+
end
76+
resource = valuei;
77+
resourcekeys = keys(valuei);
78+
resourcevalues = values(valuei,"cell");
79+
% collapse one level of cells, as this may be due to
80+
% a behavior of dictionary.values
81+
if all(cellfun(@iscell, resourcevalues))
82+
resourcevalues = [resourcevalues{:}];
83+
end
7084
end
7185
end
86+
87+
obj.Proxy = libmexclass.proxy.Proxy("Name", ...
88+
"libmexclass.opentelemetry.sdk.MeterProviderProxy", ...
89+
"ConstructorArguments", {reader.Proxy.ID, resourcekeys, resourcevalues});
90+
obj.MetricReader = reader;
91+
obj.Resource = resource;
7292
end
73-
74-
obj.Proxy = libmexclass.proxy.Proxy("Name", ...
75-
"libmexclass.opentelemetry.sdk.MeterProviderProxy", ...
76-
"ConstructorArguments", {reader.Proxy.ID, resourcekeys, resourcevalues});
77-
obj.MetricReader = reader;
78-
obj.Resource = resource;
7993
end
8094

8195
function addMetricReader(obj, reader)
@@ -86,8 +100,13 @@ function addMetricReader(obj, reader)
86100
obj.Proxy.addMetricReader(reader.Proxy.ID);
87101
obj.MetricReader = [obj.MetricReader, reader];
88102
end
89-
103+
90104
function success = shutdown(obj)
105+
% SHUTDOWN Shutdown
106+
% SUCCESS = SHUTDOWN(MP) shuts down all metric readers associated with meter provider MP
107+
% and return a logical that indicates whether shutdown was successful.
108+
%
109+
% See also FORCEFLUSH
91110
if ~obj.isShutdown
92111
success = obj.Proxy.shutdown();
93112
obj.isShutdown = success;
@@ -96,5 +115,25 @@ function addMetricReader(obj, reader)
96115
end
97116
end
98117

118+
function success = forceFlush(obj, timeout)
119+
% FORCEFLUSH Force flush
120+
% SUCCESS = FORCEFLUSH(MP) immediately exports all metrics
121+
% that have not yet been exported. Returns a logical that
122+
% indicates whether force flush was successful.
123+
%
124+
% SUCCESS = FORCEFLUSH(MP, TIMEOUT) specifies a TIMEOUT
125+
% duration. Force flush must be completed within this time,
126+
% or else it will fail.
127+
%
128+
% See also SHUTDOWN
129+
if obj.isShutdown
130+
success = false;
131+
elseif nargin < 2 || ~isa(timeout, "duration") % ignore timeout if not a duration
132+
success = obj.Proxy.forceFlush();
133+
else
134+
success = obj.Proxy.forceFlush(milliseconds(timeout)*1000); % convert to microseconds
135+
end
136+
end
137+
99138
end
100139
end

sdk/metrics/include/opentelemetry-matlab/sdk/metrics/MeterProviderProxy.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,18 @@ namespace resource = opentelemetry::sdk::resource;
3939
namespace libmexclass::opentelemetry::sdk {
4040
class MeterProviderProxy : public libmexclass::opentelemetry::MeterProviderProxy {
4141
public:
42-
MeterProviderProxy(nostd::shared_ptr<metrics_api::MeterProvider> mp) : libmexclass::opentelemetry::MeterProviderProxy(mp), CppMeterProvider(mp) {
42+
MeterProviderProxy(nostd::shared_ptr<metrics_api::MeterProvider> mp) : libmexclass::opentelemetry::MeterProviderProxy(mp) {
4343
REGISTER_METHOD(MeterProviderProxy, addMetricReader);
44+
REGISTER_METHOD(MeterProviderProxy, shutdown);
45+
REGISTER_METHOD(MeterProviderProxy, forceFlush);
4446
}
4547

4648
static libmexclass::proxy::MakeResult make(const libmexclass::proxy::FunctionArguments& constructor_arguments);
4749

4850
void addMetricReader(libmexclass::proxy::method::Context& context);
4951

50-
protected:
51-
nostd::shared_ptr<metrics_api::MeterProvider> CppMeterProvider;
52+
void shutdown(libmexclass::proxy::method::Context& context);
53+
54+
void forceFlush(libmexclass::proxy::method::Context& context);
5255
};
5356
} // namespace libmexclass::opentelemetry

sdk/metrics/src/MeterProviderProxy.cpp

Lines changed: 50 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,26 +11,38 @@ namespace libmexclass::opentelemetry::sdk {
1111
libmexclass::proxy::MakeResult MeterProviderProxy::make(const libmexclass::proxy::FunctionArguments& constructor_arguments) {
1212

1313
libmexclass::proxy::MakeResult out;
14-
15-
matlab::data::TypedArray<uint64_t> readerid_mda = constructor_arguments[0];
16-
libmexclass::proxy::ID readerid = readerid_mda[0];
17-
18-
matlab::data::StringArray resourcenames_mda = constructor_arguments[1];
19-
size_t nresourceattrs = resourcenames_mda.getNumberOfElements();
20-
matlab::data::CellArray resourcevalues_mda = constructor_arguments[2];
21-
22-
auto resource_custom = createResource(resourcenames_mda, resourcevalues_mda);
23-
24-
auto reader = std::static_pointer_cast<PeriodicExportingMetricReaderProxy>(
25-
libmexclass::proxy::ProxyManager::getProxy(readerid))->getInstance();
26-
auto p = metrics_sdk::MeterProviderFactory::Create(NULL, std::move(resource_custom));
27-
auto *p_sdk = static_cast<metrics_sdk::MeterProvider *>(p.get());
28-
p_sdk->AddMetricReader(std::move(reader));
14+
if (constructor_arguments.getNumberOfElements() == 1) {
15+
// if only one input, assume it is an API Tracer Provider to support type conversion
16+
matlab::data::TypedArray<uint64_t> mpid_mda = constructor_arguments[0];
17+
libmexclass::proxy::ID mpid = mpid_mda[0];
18+
auto mp = std::static_pointer_cast<libmexclass::opentelemetry::MeterProviderProxy>(
19+
libmexclass::proxy::ProxyManager::getProxy(mpid))->getInstance();
20+
// check if input can be cast to an SDK Meter Provider
21+
auto mpsdk = dynamic_cast<metrics_sdk::MeterProvider*>(mp.get());
22+
if (mpsdk == nullptr) {
23+
return libmexclass::error::Error{"opentelemetry:sdk:metrics:Cleanup:UnsetGlobalInstance",
24+
"Clean up operations are not supported if global MeterProvider instance is not set."};
25+
}
26+
out = std::make_shared<MeterProviderProxy>(nostd::shared_ptr<metrics_api::MeterProvider>(mp));
27+
} else {
28+
matlab::data::TypedArray<uint64_t> readerid_mda = constructor_arguments[0];
29+
libmexclass::proxy::ID readerid = readerid_mda[0];
30+
31+
matlab::data::StringArray resourcenames_mda = constructor_arguments[1];
32+
size_t nresourceattrs = resourcenames_mda.getNumberOfElements();
33+
matlab::data::CellArray resourcevalues_mda = constructor_arguments[2];
2934

30-
auto p_out = nostd::shared_ptr<metrics_api::MeterProvider>(std::move(p));
31-
32-
out = std::make_shared<MeterProviderProxy>(p_out);
35+
auto resource_custom = createResource(resourcenames_mda, resourcevalues_mda);
3336

37+
auto reader = std::static_pointer_cast<PeriodicExportingMetricReaderProxy>(
38+
libmexclass::proxy::ProxyManager::getProxy(readerid))->getInstance();
39+
auto p = metrics_sdk::MeterProviderFactory::Create();
40+
auto *p_sdk = static_cast<metrics_sdk::MeterProvider *>(p.get());
41+
p_sdk->AddMetricReader(std::move(reader));
42+
43+
auto p_out = nostd::shared_ptr<metrics_api::MeterProvider>(std::move(p));
44+
out = std::make_shared<MeterProviderProxy>(p_out);
45+
}
3446
return out;
3547
}
3648

@@ -44,5 +56,25 @@ void MeterProviderProxy::addMetricReader(libmexclass::proxy::method::Context& co
4456
return;
4557
}
4658

59+
void MeterProviderProxy::shutdown(libmexclass::proxy::method::Context& context) {
60+
matlab::data::ArrayFactory factory;
61+
auto result_mda = factory.createScalar(static_cast<metrics_sdk::MeterProvider&>(*CppMeterProvider).Shutdown());
62+
context.outputs[0] = result_mda;
63+
nostd::shared_ptr<metrics_api::MeterProvider> noop(new metrics_api::NoopMeterProvider);
64+
CppMeterProvider.swap(noop);
65+
}
66+
67+
void MeterProviderProxy::forceFlush(libmexclass::proxy::method::Context& context) {
68+
matlab::data::ArrayFactory factory;
69+
70+
if (context.inputs.getNumberOfElements() == 0) {
71+
context.outputs[0] = factory.createScalar(static_cast<metrics_sdk::MeterProvider&>(*CppMeterProvider).ForceFlush());
72+
} else { // number of inputs > 0
73+
matlab::data::TypedArray<double> timeout_mda = context.inputs[0];
74+
auto timeout = std::chrono::microseconds(timeout_mda[0]);
75+
context.outputs[0] = factory.createScalar(static_cast<metrics_sdk::MeterProvider&>(*CppMeterProvider).ForceFlush(timeout));
76+
}
77+
}
78+
4779

4880
} // namespace libmexclass::opentelemetry

0 commit comments

Comments
 (0)