Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 34 additions & 4 deletions sdk/metrics/+opentelemetry/+sdk/+metrics/MeterProvider.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@

properties (Access=public)
MetricReader
Resource
end

methods
function obj = MeterProvider(reader)
% SDK implementation of tracer provider
function obj = MeterProvider(reader, optionnames, optionvalues)
% SDK implementation of meter provider
% MP = OPENTELEMETRY.SDK.METRICS.METERPROVIDER creates a meter
% provider that uses a periodic exporting metric reader and default configurations.
%
Expand All @@ -38,6 +39,11 @@
opentelemetry.sdk.metrics.PeriodicExportingMetricReader()
end

arguments (Repeating)
optionnames (1,:) {mustBeTextScalar}
optionvalues
end

% explicit call to superclass constructor to make it a no-op
obj@opentelemetry.metrics.MeterProvider("skip");

Expand All @@ -49,13 +55,37 @@
assert(mpproxy.Name == "libmexclass.opentelemetry.MeterProviderProxy");
obj.Proxy = libmexclass.proxy.Proxy("Name", ...
"libmexclass.opentelemetry.sdk.MeterProviderProxy", ...
"ConstructorArguments", {mpproxy.ID, true});
"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", ...
"Resource 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, false});
"ConstructorArguments", {reader.Proxy.ID, resourcekeys, resourcevalues});
obj.MetricReader = reader;
obj.Resource = resource;
end
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,14 @@
#include "opentelemetry/sdk/metrics/meter_provider.h"
#include "opentelemetry/sdk/metrics/meter_provider_factory.h"
#include "opentelemetry/sdk/metrics/push_metric_exporter.h"
#include "opentelemetry/sdk/resource/resource.h"
#include "opentelemetry/sdk/metrics/view/view_registry.h"
#include "opentelemetry/sdk/metrics/view/view_registry_factory.h"


#include "opentelemetry-matlab/metrics/MeterProxy.h"
#include "opentelemetry-matlab/metrics/MeterProviderProxy.h"
#include "opentelemetry-matlab/sdk/common/resource.h"

namespace metrics_api = opentelemetry::metrics;
namespace nostd = opentelemetry::nostd;
Expand Down
17 changes: 12 additions & 5 deletions sdk/metrics/src/MeterProviderProxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@ namespace libmexclass::opentelemetry::sdk {
libmexclass::proxy::MakeResult MeterProviderProxy::make(const libmexclass::proxy::FunctionArguments& constructor_arguments) {

libmexclass::proxy::MakeResult out;
matlab::data::TypedArray<bool> is_api = constructor_arguments[1];
if (is_api[0]) {
// if argument is 1, assume it is an API Meter Provider to support type conversion
if (constructor_arguments.getNumberOfElements() == 1) {
// if only one input, assume it is an API Meter 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>(
Expand All @@ -29,12 +28,20 @@ libmexclass::proxy::MakeResult MeterProviderProxy::make(const libmexclass::proxy
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();

auto view = metrics_sdk::ViewRegistryFactory::Create();
auto p = metrics_sdk::MeterProviderFactory::Create(std::move(view), resource_custom);
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);
}
Expand Down
69 changes: 69 additions & 0 deletions test/tmetrics_sdk.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
classdef tmetrics_sdk < matlab.unittest.TestCase
% tests for metrics SDK

% Copyright 2023 The MathWorks, Inc.

properties
OtelConfigFile
JsonFile
PidFile
OtelcolName
Otelcol
ListPid
ReadPidList
ExtractPid
Sigint
Sigterm
end

methods (TestClassSetup)
function setupOnce(testCase)
commonSetupOnce(testCase);
end
end

methods (TestMethodTeardown)
function teardown(testCase)
commonTeardown(testCase);
end
end

methods (Test)
function testCustomResource(testCase)
% testCustomResource: check custom resources are included in
% emitted metrics
commonSetup(testCase)

customkeys = ["foo" "bar"];
customvalues = [1 5];
exporter = opentelemetry.exporters.otlp.OtlpHttpMetricExporter();
reader = opentelemetry.sdk.metrics.PeriodicExportingMetricReader(exporter, ...
"Interval", seconds(2), "Timeout", seconds(1));
mp = opentelemetry.sdk.metrics.MeterProvider(reader, ...
"Resource", dictionary(customkeys, customvalues));

m = getMeter(mp, "mymeter");
c = createCounter(m, "mycounter");

% create testing value
val = 10;

% add value and attributes
c.add(val);

pause(2.5);

% perform test comparisons
results = readJsonResults(testCase);
results = results{1};

resourcekeys = string({results.resourceMetrics.resource.attributes.key});
for i = length(customkeys)
idx = find(resourcekeys == customkeys(i));
verifyNotEmpty(testCase, idx);
verifyEqual(testCase, results.resourceMetrics.resource.attributes(idx).value.doubleValue, customvalues(i));
end
end

end
end