Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
82 commits
Select commit Hold shift + click to select a range
f6a1c55
feat: metric_exporter, metric_reader
ricktu-mw Sep 25, 2023
0984062
update 1
ricktu-mw Sep 27, 2023
98bd3a6
v2
ricktu-mw Sep 28, 2023
4d8b990
v2
ricktu-mw Sep 28, 2023
081f16e
v2
ricktu-mw Sep 28, 2023
dd8e0e9
v3
ricktu-mw Oct 2, 2023
cc9cf8f
v4
ricktu-mw Oct 2, 2023
883f261
v5
ricktu-mw Oct 2, 2023
137fed8
v6
ricktu-mw Oct 3, 2023
ba013e1
Merge pull request #25 from mathworks/changes_after_v_1_3_0
duncanpo Oct 3, 2023
1b833de
v7
ricktu-mw Oct 3, 2023
6380ae1
v8: addMetricReader
ricktu-mw Oct 4, 2023
300445c
v9: update comments
ricktu-mw Oct 4, 2023
2636072
Merge pull request #26 from mathworks/metrics_reader
duncanpo Oct 5, 2023
40ecc12
Creating MeterProvider API
dnarula-mw Oct 5, 2023
68a0985
fix: invalid instrument names with spaces
ricktu-mw Oct 6, 2023
1773af8
Finishing and cleaning up MeterProvider api
dnarula-mw Oct 6, 2023
e995d79
fix: comments
ricktu-mw Oct 6, 2023
9af0a3d
Merge pull request #29 from mathworks/metrics_reader
duncanpo Oct 6, 2023
6e11722
Merge pull request #38 from mathworks/changes_after_v_1_3_0
duncanpo Oct 10, 2023
ac793c5
Adding test for get and set meter
dnarula-mw Oct 11, 2023
a0777dd
Resolving merge conflicts
dnarula-mw Oct 11, 2023
ec00310
Fixing error from merge
dnarula-mw Oct 11, 2023
3af790a
Removing .vs folder
dnarula-mw Oct 11, 2023
8c3a10c
Add resource property
dnarula-mw Oct 12, 2023
8268a15
Lowering reader interval for test
dnarula-mw Oct 12, 2023
f9b7c45
clearning meter provider in test
dnarula-mw Oct 12, 2023
39e01fa
fixing typo
dnarula-mw Oct 12, 2023
a630aa7
Addressing PR comments
dnarula-mw Oct 12, 2023
fd75583
Fixing crash and comment out test
dnarula-mw Oct 12, 2023
cf7f8ec
Merge pull request #39 from mathworks/meter_provider_api
duncanpo Oct 12, 2023
ff030ae
Adding shutdown and forceflush to fix getsetmeterprovider test
dnarula-mw Oct 26, 2023
e1c58c4
Clean up code and finish shutdown
dnarula-mw Oct 30, 2023
e245e2e
Removing unnecessary change in tests
dnarula-mw Oct 30, 2023
caab36b
Addressing pull request comments
dnarula-mw Oct 31, 2023
60acf06
Merge pull request #42 from mathworks/meter_provider_api
dnarula-mw Oct 31, 2023
f21e7c6
Fixing merge conflicts
dnarula-mw Oct 31, 2023
f3884c3
Make metric reader and exporter properties editable
duncanpo Nov 2, 2023
66b73f2
Merge pull request #46 from mathworks/metrics_readonly_props
duncanpo Nov 2, 2023
58392ca
Finishing add resource property to metrics
dnarula-mw Nov 2, 2023
3e9a03f
Merge branch 'metrics' into meter_provider_resource
dnarula-mw Nov 2, 2023
b90544a
add a test about issue #34
duncanpo Nov 2, 2023
ee27f2b
Cleaning up code
dnarula-mw Nov 2, 2023
2628bd7
Merge pull request #47 from mathworks/metrics_readonly_props
duncanpo Nov 2, 2023
ac97746
Change error message
dnarula-mw Nov 2, 2023
b7bb9cf
Merge pull request #48 from mathworks/meter_provider_resource
dnarula-mw Nov 2, 2023
2bff102
Correctly clearing meter providers
dnarula-mw Nov 3, 2023
4a12e67
add a SynchronousInstrument base class
duncanpo Nov 3, 2023
b6e18f9
Merge pull request #50 from mathworks/fixing_tests
duncanpo Nov 3, 2023
af1a71c
Merge pull request #49 from mathworks/sync_instrument
duncanpo Nov 3, 2023
adb6cd3
enable Cleanup class to work for SDK objects
duncanpo Nov 8, 2023
ccacea4
Merge pull request #51 from mathworks/metrics_cleanup
duncanpo Nov 8, 2023
9f9fbc7
Complex number handling and more code sharing between metric instruments
duncanpo Nov 9, 2023
123f9f9
Merge pull request #54 from mathworks/metrics_cleanup
duncanpo Nov 9, 2023
94b9293
back out a change to replace spaces in instrument names with underscore
duncanpo Nov 9, 2023
6d492c9
Merge pull request #55 from mathworks/metrics_cleanup
duncanpo Nov 9, 2023
bfe1c50
Adding View Class in metrics sdk and add view method to meter provider
dnarula-mw Nov 10, 2023
0e46adf
Merge branch 'metrics' into metrics_view
duncanpo Nov 13, 2023
f3e7a37
Merge pull request #56 from mathworks/metrics_view
duncanpo Nov 13, 2023
1e33556
prepare for merging metrics branch into main
duncanpo Nov 13, 2023
613e99e
fix merge issues
duncanpo Nov 13, 2023
dd0d28a
fix merge issues
duncanpo Nov 13, 2023
10b014c
Merge pull request #58 from mathworks/metrics_merge
duncanpo Nov 13, 2023
9222d37
Add shutdown tests to ttrace_sdk
duncanpo Nov 14, 2023
9185f37
Merge pull request #59 from mathworks/metrics_merge
duncanpo Nov 14, 2023
1e27933
refactor exporter code to enable more code sharing and remove duplica…
duncanpo Nov 16, 2023
65c04b4
Merge pull request #61 from mathworks/metrics_merge
duncanpo Nov 16, 2023
9f33853
separate nondefault endpoint tests into their own test file
duncanpo Nov 17, 2023
489c56e
Merge pull request #63 from mathworks/metrics_merge
duncanpo Nov 17, 2023
61b93aa
Changes to view sdk
dnarula-mw Nov 28, 2023
3f7ee56
Refactor MeterProxy to use a factory class and reduce code duplication
duncanpo Dec 1, 2023
3a6b77f
Merge pull request #65 from mathworks/metrics_factory
duncanpo Dec 1, 2023
74f9d38
Updating view, changing name and histogram edges is working
dnarula-mw Dec 6, 2023
f035171
Finishing view
dnarula-mw Dec 7, 2023
5df8f72
Minor changes for PR
dnarula-mw Dec 7, 2023
c10af76
Addressing PR comments
dnarula-mw Dec 8, 2023
99f23be
Merge pull request #67 from mathworks/metrics_view_sdk
duncanpo Dec 8, 2023
97754c9
Add help texts for metrics
duncanpo Dec 12, 2023
6684a7d
Refactor view class
duncanpo Dec 14, 2023
4c7af79
Bump up libmexclass #72
duncanpo Dec 14, 2023
c9503f1
Add a metrics example
duncanpo Dec 14, 2023
2dab550
Merge pull request #73 from mathworks/metrics_release
duncanpo Dec 14, 2023
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion api/metrics/+opentelemetry/+metrics/MeterProvider.m
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

% Copyright 2023 The MathWorks, Inc.

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

Expand Down Expand Up @@ -59,4 +59,11 @@ function setMeterProvider(obj)
obj.Proxy.setMeterProvider();
end
end

methods(Access=?opentelemetry.sdk.metrics.Cleanup)
function postShutdown(obj)
% POSTSHUTDOWN Handle post-shutdown tasks
obj.Proxy.postShutdown();
end
end
end
17 changes: 17 additions & 0 deletions api/metrics/+opentelemetry/+metrics/getMeter.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
function meter = getMeter(mname, varargin)
% Create a meter from the global meter provider instance
% M = OPENTELEMETRY.METRICS.GETMETER(NAME) returns a meter with the
% specified name created from the global meter provider instance.
%
% M = OPENTELEMETRY.METRICS.GETMETER(NAME, VERSION, SCHEMA) also
% specifies the meter version and the URL that documents the schema
% of the generated metrics.
%
% See also OPENTELEMETRY.SDK.METRICS.METERPROVIDER,
% OPENTELEMETRY.METRICS.METER,
% OPENTELEMETRY.METRICS.PROVIDER.SETMETERPROVIDER

% Copyright 2023 The MathWorks, Inc.

provider = opentelemetry.metrics.Provider.getMeterProvider();
meter = getMeter(provider, mname, varargin{:});
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,15 @@
#include "opentelemetry/metrics/noop.h"

namespace metrics_api = opentelemetry::metrics;
namespace metrics_sdk = opentelemetry::sdk::metrics;
namespace metrics_exporter = opentelemetry::exporter::otlp;
namespace nostd = opentelemetry::nostd;
namespace resource = opentelemetry::sdk::resource;

namespace libmexclass::opentelemetry {
class MeterProviderProxy : public libmexclass::proxy::Proxy {
public:
MeterProviderProxy(nostd::shared_ptr<metrics_api::MeterProvider> mp) : CppMeterProvider(mp) {
REGISTER_METHOD(MeterProviderProxy, getMeter);
REGISTER_METHOD(MeterProviderProxy, setMeterProvider);
REGISTER_METHOD(MeterProviderProxy, postShutdown);
}

// Static make method should only be used by getMeterProvider. It gets the global instance
Expand All @@ -39,6 +37,12 @@ class MeterProviderProxy : public libmexclass::proxy::Proxy {
nostd::shared_ptr<metrics_api::MeterProvider> getInstance() {
return CppMeterProvider;
}

void postShutdown(libmexclass::proxy::method::Context& context) {
// Replace meter provider with a no-op instance. Subsequent metrics won't be recorded
nostd::shared_ptr<metrics_api::MeterProvider> noop(new metrics_api::NoopMeterProvider);
CppMeterProvider.swap(noop);
}

protected:
nostd::shared_ptr<metrics_api::MeterProvider> CppMeterProvider;
Expand Down
63 changes: 63 additions & 0 deletions sdk/metrics/+opentelemetry/+sdk/+metrics/Cleanup.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
classdef Cleanup
% Clean up methods for MeterProvider in the API

% Copyright 2023 The MathWorks, Inc.

methods (Static)
function success = shutdown(mp)
% SHUTDOWN Shutdown
% SUCCESS = SHUTDOWN(MP) shuts down all metric readers associated with
% API meter provider MP and return a logical that indicates
% whether shutdown was successful.
%
% See also FORCEFLUSH

% return false if input is not the right type
if isa(mp, "opentelemetry.metrics.MeterProvider")
% convert to MeterProvider class in sdk
try
mpsdk = opentelemetry.sdk.metrics.MeterProvider(mp.Proxy);
catch
success = false;
return
end
success = mpsdk.shutdown;
postShutdown(mp);
else
success = false;
end
end

function success = forceFlush(mp, timeout)
% FORCEFLUSH Force flush
% SUCCESS = FORCEFLUSH(MP) immediately exports all metrics
% that have not yet been exported. Returns a logical that
% indicates whether force flush was successful.
%
% SUCCESS = FORCEFLUSH(MP, TIMEOUT) specifies a TIMEOUT
% duration. Force flush must be completed within this time,
% or else it will fail.
%
% See also SHUTDOWN

% return false if input is not the right type
if isa(mp, "opentelemetry.metrics.MeterProvider")
% convert to MeterProvider class in sdk
try
mpsdk = opentelemetry.sdk.metrics.MeterProvider(mp.Proxy);
catch
success = false;
return
end
if nargin < 2 || ~isa(timeout, "duration")
success = mpsdk.forceFlush;
else
success = mpsdk.forceFlush(timeout);
end
else
success = false;
end
end
end

end
95 changes: 67 additions & 28 deletions sdk/metrics/+opentelemetry/+sdk/+metrics/MeterProvider.m
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@

% Copyright 2023 The MathWorks, Inc.

properties (Access=private)
properties(Access=private)
isShutdown (1,1) logical = false
end


properties (Access=public)
MetricReader
end
Expand Down Expand Up @@ -48,34 +47,49 @@
optionvalues
end

validnames = ["Resource"];
resourcekeys = string.empty();
resourcevalues = {};
resource = dictionary(resourcekeys, resourcevalues);
for i = 1:length(optionnames)
namei = validatestring(optionnames{i}, validnames);
valuei = optionvalues{i};
if strcmp(namei, "Resource")
if ~isa(valuei, "dictionary")
error("opentelemetry:sdk:metrics:MeterProvider:InvalidResourceType", ...
"Attibutes input must be a dictionary.");
end
resource = valuei;
resourcekeys = keys(valuei);
resourcevalues = values(valuei,"cell");
% collapse one level of cells, as this may be due to
% a behavior of dictionary.values
if all(cellfun(@iscell, resourcevalues))
resourcevalues = [resourcevalues{:}];
% explicit call to superclass constructor to make it a no-op
[email protected]("skip");

if isa(reader, "libmexclass.proxy.Proxy")
% This code branch is used to support conversion from API
% MeterProvider to SDK equivalent, needed internally by
% opentelemetry.sdk.metrics.Cleanup
mpproxy = reader; % rename the variable
assert(mpproxy.Name == "libmexclass.opentelemetry.MeterProviderProxy");
obj.Proxy = libmexclass.proxy.Proxy("Name", ...
"libmexclass.opentelemetry.sdk.MeterProviderProxy", ...
"ConstructorArguments", {mpproxy.ID});
% leave other properties unassigned, they won't be used
else
validnames = ["Resource"];
resourcekeys = string.empty();
resourcevalues = {};
resource = dictionary(resourcekeys, resourcevalues);
for i = 1:length(optionnames)
namei = validatestring(optionnames{i}, validnames);
valuei = optionvalues{i};
if strcmp(namei, "Resource")
if ~isa(valuei, "dictionary")
error("opentelemetry:sdk:metrics:MeterProvider:InvalidResourceType", ...
"Attibutes input must be a dictionary.");
end
resource = valuei;
resourcekeys = keys(valuei);
resourcevalues = values(valuei,"cell");
% collapse one level of cells, as this may be due to
% a behavior of dictionary.values
if all(cellfun(@iscell, resourcevalues))
resourcevalues = [resourcevalues{:}];
end
end
end

obj.Proxy = libmexclass.proxy.Proxy("Name", ...
"libmexclass.opentelemetry.sdk.MeterProviderProxy", ...
"ConstructorArguments", {reader.Proxy.ID, resourcekeys, resourcevalues});
obj.MetricReader = reader;
obj.Resource = resource;
end

obj.Proxy = libmexclass.proxy.Proxy("Name", ...
"libmexclass.opentelemetry.sdk.MeterProviderProxy", ...
"ConstructorArguments", {reader.Proxy.ID, resourcekeys, resourcevalues});
obj.MetricReader = reader;
obj.Resource = resource;
end

function addMetricReader(obj, reader)
Expand All @@ -86,8 +100,13 @@ function addMetricReader(obj, reader)
obj.Proxy.addMetricReader(reader.Proxy.ID);
obj.MetricReader = [obj.MetricReader, reader];
end

function success = shutdown(obj)
% SHUTDOWN Shutdown
% SUCCESS = SHUTDOWN(MP) shuts down all metric readers associated with meter provider MP
% and return a logical that indicates whether shutdown was successful.
%
% See also FORCEFLUSH
if ~obj.isShutdown
success = obj.Proxy.shutdown();
obj.isShutdown = success;
Expand All @@ -96,5 +115,25 @@ function addMetricReader(obj, reader)
end
end

function success = forceFlush(obj, timeout)
% FORCEFLUSH Force flush
% SUCCESS = FORCEFLUSH(MP) immediately exports all metrics
% that have not yet been exported. Returns a logical that
% indicates whether force flush was successful.
%
% SUCCESS = FORCEFLUSH(MP, TIMEOUT) specifies a TIMEOUT
% duration. Force flush must be completed within this time,
% or else it will fail.
%
% See also SHUTDOWN
if obj.isShutdown
success = false;
elseif nargin < 2 || ~isa(timeout, "duration") % ignore timeout if not a duration
success = obj.Proxy.forceFlush();
else
success = obj.Proxy.forceFlush(milliseconds(timeout)*1000); % convert to microseconds
end
end

end
end
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,18 @@ namespace resource = opentelemetry::sdk::resource;
namespace libmexclass::opentelemetry::sdk {
class MeterProviderProxy : public libmexclass::opentelemetry::MeterProviderProxy {
public:
MeterProviderProxy(nostd::shared_ptr<metrics_api::MeterProvider> mp) : libmexclass::opentelemetry::MeterProviderProxy(mp), CppMeterProvider(mp) {
MeterProviderProxy(nostd::shared_ptr<metrics_api::MeterProvider> mp) : libmexclass::opentelemetry::MeterProviderProxy(mp) {
REGISTER_METHOD(MeterProviderProxy, addMetricReader);
REGISTER_METHOD(MeterProviderProxy, shutdown);
REGISTER_METHOD(MeterProviderProxy, forceFlush);
}

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

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

protected:
nostd::shared_ptr<metrics_api::MeterProvider> CppMeterProvider;
void shutdown(libmexclass::proxy::method::Context& context);

void forceFlush(libmexclass::proxy::method::Context& context);
};
} // namespace libmexclass::opentelemetry
68 changes: 50 additions & 18 deletions sdk/metrics/src/MeterProviderProxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,38 @@ namespace libmexclass::opentelemetry::sdk {
libmexclass::proxy::MakeResult MeterProviderProxy::make(const libmexclass::proxy::FunctionArguments& constructor_arguments) {

libmexclass::proxy::MakeResult out;

matlab::data::TypedArray<uint64_t> readerid_mda = constructor_arguments[0];
libmexclass::proxy::ID readerid = readerid_mda[0];

matlab::data::StringArray resourcenames_mda = constructor_arguments[1];
size_t nresourceattrs = resourcenames_mda.getNumberOfElements();
matlab::data::CellArray resourcevalues_mda = constructor_arguments[2];

auto resource_custom = createResource(resourcenames_mda, resourcevalues_mda);

auto reader = std::static_pointer_cast<PeriodicExportingMetricReaderProxy>(
libmexclass::proxy::ProxyManager::getProxy(readerid))->getInstance();
auto p = metrics_sdk::MeterProviderFactory::Create(NULL, std::move(resource_custom));
auto *p_sdk = static_cast<metrics_sdk::MeterProvider *>(p.get());
p_sdk->AddMetricReader(std::move(reader));
if (constructor_arguments.getNumberOfElements() == 1) {
// if only one input, assume it is an API Tracer Provider to support type conversion
matlab::data::TypedArray<uint64_t> mpid_mda = constructor_arguments[0];
libmexclass::proxy::ID mpid = mpid_mda[0];
auto mp = std::static_pointer_cast<libmexclass::opentelemetry::MeterProviderProxy>(
libmexclass::proxy::ProxyManager::getProxy(mpid))->getInstance();
// check if input can be cast to an SDK Meter Provider
auto mpsdk = dynamic_cast<metrics_sdk::MeterProvider*>(mp.get());
if (mpsdk == nullptr) {
return libmexclass::error::Error{"opentelemetry:sdk:metrics:Cleanup:UnsetGlobalInstance",
"Clean up operations are not supported if global MeterProvider instance is not set."};
}
out = std::make_shared<MeterProviderProxy>(nostd::shared_ptr<metrics_api::MeterProvider>(mp));
} else {
matlab::data::TypedArray<uint64_t> readerid_mda = constructor_arguments[0];
libmexclass::proxy::ID readerid = readerid_mda[0];

matlab::data::StringArray resourcenames_mda = constructor_arguments[1];
size_t nresourceattrs = resourcenames_mda.getNumberOfElements();
matlab::data::CellArray resourcevalues_mda = constructor_arguments[2];

auto p_out = nostd::shared_ptr<metrics_api::MeterProvider>(std::move(p));

out = std::make_shared<MeterProviderProxy>(p_out);
auto resource_custom = createResource(resourcenames_mda, resourcevalues_mda);

auto reader = std::static_pointer_cast<PeriodicExportingMetricReaderProxy>(
libmexclass::proxy::ProxyManager::getProxy(readerid))->getInstance();
auto p = metrics_sdk::MeterProviderFactory::Create();
auto *p_sdk = static_cast<metrics_sdk::MeterProvider *>(p.get());
p_sdk->AddMetricReader(std::move(reader));

auto p_out = nostd::shared_ptr<metrics_api::MeterProvider>(std::move(p));
out = std::make_shared<MeterProviderProxy>(p_out);
}
return out;
}

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

void MeterProviderProxy::shutdown(libmexclass::proxy::method::Context& context) {
matlab::data::ArrayFactory factory;
auto result_mda = factory.createScalar(static_cast<metrics_sdk::MeterProvider&>(*CppMeterProvider).Shutdown());
context.outputs[0] = result_mda;
nostd::shared_ptr<metrics_api::MeterProvider> noop(new metrics_api::NoopMeterProvider);
CppMeterProvider.swap(noop);
}

void MeterProviderProxy::forceFlush(libmexclass::proxy::method::Context& context) {
matlab::data::ArrayFactory factory;

if (context.inputs.getNumberOfElements() == 0) {
context.outputs[0] = factory.createScalar(static_cast<metrics_sdk::MeterProvider&>(*CppMeterProvider).ForceFlush());
} else { // number of inputs > 0
matlab::data::TypedArray<double> timeout_mda = context.inputs[0];
auto timeout = std::chrono::microseconds(timeout_mda[0]);
context.outputs[0] = factory.createScalar(static_cast<metrics_sdk::MeterProvider&>(*CppMeterProvider).ForceFlush(timeout));
}
}


} // namespace libmexclass::opentelemetry
Loading