Skip to content

Commit b7bb9cf

Browse files
authored
Merge pull request #48 from mathworks/meter_provider_resource
Adding Resource Property to MeterProvider
2 parents 2628bd7 + ac97746 commit b7bb9cf

File tree

4 files changed

+120
-9
lines changed

4 files changed

+120
-9
lines changed

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

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@
1010

1111
properties (Access=public)
1212
MetricReader
13+
Resource
1314
end
1415

1516
methods
16-
function obj = MeterProvider(reader)
17-
% SDK implementation of tracer provider
17+
function obj = MeterProvider(reader, optionnames, optionvalues)
18+
% SDK implementation of meter provider
1819
% MP = OPENTELEMETRY.SDK.METRICS.METERPROVIDER creates a meter
1920
% provider that uses a periodic exporting metric reader and default configurations.
2021
%
@@ -38,6 +39,11 @@
3839
opentelemetry.sdk.metrics.PeriodicExportingMetricReader()
3940
end
4041

42+
arguments (Repeating)
43+
optionnames (1,:) {mustBeTextScalar}
44+
optionvalues
45+
end
46+
4147
% explicit call to superclass constructor to make it a no-op
4248
4349

@@ -49,13 +55,37 @@
4955
assert(mpproxy.Name == "libmexclass.opentelemetry.MeterProviderProxy");
5056
obj.Proxy = libmexclass.proxy.Proxy("Name", ...
5157
"libmexclass.opentelemetry.sdk.MeterProviderProxy", ...
52-
"ConstructorArguments", {mpproxy.ID, true});
58+
"ConstructorArguments", {mpproxy.ID});
5359
% leave other properties unassigned, they won't be used
5460
else
61+
validnames = ["Resource"];
62+
resourcekeys = string.empty();
63+
resourcevalues = {};
64+
resource = dictionary(resourcekeys, resourcevalues);
65+
for i = 1:length(optionnames)
66+
namei = validatestring(optionnames{i}, validnames);
67+
valuei = optionvalues{i};
68+
if strcmp(namei, "Resource")
69+
if ~isa(valuei, "dictionary")
70+
error("opentelemetry:sdk:metrics:MeterProvider:InvalidResourceType", ...
71+
"Resource input must be a dictionary.");
72+
end
73+
resource = valuei;
74+
resourcekeys = keys(valuei);
75+
resourcevalues = values(valuei,"cell");
76+
% collapse one level of cells, as this may be due to
77+
% a behavior of dictionary.values
78+
if all(cellfun(@iscell, resourcevalues))
79+
resourcevalues = [resourcevalues{:}];
80+
end
81+
end
82+
end
83+
5584
obj.Proxy = libmexclass.proxy.Proxy("Name", ...
5685
"libmexclass.opentelemetry.sdk.MeterProviderProxy", ...
57-
"ConstructorArguments", {reader.Proxy.ID, false});
86+
"ConstructorArguments", {reader.Proxy.ID, resourcekeys, resourcevalues});
5887
obj.MetricReader = reader;
88+
obj.Resource = resource;
5989
end
6090
end
6191

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,14 @@
2121
#include "opentelemetry/sdk/metrics/meter_provider.h"
2222
#include "opentelemetry/sdk/metrics/meter_provider_factory.h"
2323
#include "opentelemetry/sdk/metrics/push_metric_exporter.h"
24+
#include "opentelemetry/sdk/resource/resource.h"
25+
#include "opentelemetry/sdk/metrics/view/view_registry.h"
26+
#include "opentelemetry/sdk/metrics/view/view_registry_factory.h"
27+
2428

2529
#include "opentelemetry-matlab/metrics/MeterProxy.h"
2630
#include "opentelemetry-matlab/metrics/MeterProviderProxy.h"
31+
#include "opentelemetry-matlab/sdk/common/resource.h"
2732

2833
namespace metrics_api = opentelemetry::metrics;
2934
namespace nostd = opentelemetry::nostd;

sdk/metrics/src/MeterProviderProxy.cpp

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

1313
libmexclass::proxy::MakeResult out;
14-
matlab::data::TypedArray<bool> is_api = constructor_arguments[1];
15-
if (is_api[0]) {
16-
// if argument is 1, assume it is an API Meter Provider to support type conversion
14+
if (constructor_arguments.getNumberOfElements() == 1) {
15+
// if only one input, assume it is an API Meter Provider to support type conversion
1716
matlab::data::TypedArray<uint64_t> mpid_mda = constructor_arguments[0];
1817
libmexclass::proxy::ID mpid = mpid_mda[0];
1918
auto mp = std::static_pointer_cast<libmexclass::opentelemetry::MeterProviderProxy>(
@@ -29,12 +28,20 @@ libmexclass::proxy::MakeResult MeterProviderProxy::make(const libmexclass::proxy
2928
matlab::data::TypedArray<uint64_t> readerid_mda = constructor_arguments[0];
3029
libmexclass::proxy::ID readerid = readerid_mda[0];
3130

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];
34+
35+
auto resource_custom = createResource(resourcenames_mda, resourcevalues_mda);
36+
3237
auto reader = std::static_pointer_cast<PeriodicExportingMetricReaderProxy>(
3338
libmexclass::proxy::ProxyManager::getProxy(readerid))->getInstance();
34-
auto p = metrics_sdk::MeterProviderFactory::Create();
39+
40+
auto view = metrics_sdk::ViewRegistryFactory::Create();
41+
auto p = metrics_sdk::MeterProviderFactory::Create(std::move(view), resource_custom);
3542
auto *p_sdk = static_cast<metrics_sdk::MeterProvider *>(p.get());
3643
p_sdk->AddMetricReader(std::move(reader));
37-
44+
3845
auto p_out = nostd::shared_ptr<metrics_api::MeterProvider>(std::move(p));
3946
out = std::make_shared<MeterProviderProxy>(p_out);
4047
}

test/tmetrics_sdk.m

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
classdef tmetrics_sdk < matlab.unittest.TestCase
2+
% tests for metrics SDK
3+
4+
% Copyright 2023 The MathWorks, Inc.
5+
6+
properties
7+
OtelConfigFile
8+
JsonFile
9+
PidFile
10+
OtelcolName
11+
Otelcol
12+
ListPid
13+
ReadPidList
14+
ExtractPid
15+
Sigint
16+
Sigterm
17+
end
18+
19+
methods (TestClassSetup)
20+
function setupOnce(testCase)
21+
commonSetupOnce(testCase);
22+
end
23+
end
24+
25+
methods (TestMethodTeardown)
26+
function teardown(testCase)
27+
commonTeardown(testCase);
28+
end
29+
end
30+
31+
methods (Test)
32+
function testCustomResource(testCase)
33+
% testCustomResource: check custom resources are included in
34+
% emitted metrics
35+
commonSetup(testCase)
36+
37+
customkeys = ["foo" "bar"];
38+
customvalues = [1 5];
39+
exporter = opentelemetry.exporters.otlp.OtlpHttpMetricExporter();
40+
reader = opentelemetry.sdk.metrics.PeriodicExportingMetricReader(exporter, ...
41+
"Interval", seconds(2), "Timeout", seconds(1));
42+
mp = opentelemetry.sdk.metrics.MeterProvider(reader, ...
43+
"Resource", dictionary(customkeys, customvalues));
44+
45+
m = getMeter(mp, "mymeter");
46+
c = createCounter(m, "mycounter");
47+
48+
% create testing value
49+
val = 10;
50+
51+
% add value and attributes
52+
c.add(val);
53+
54+
pause(2.5);
55+
56+
% perform test comparisons
57+
results = readJsonResults(testCase);
58+
results = results{1};
59+
60+
resourcekeys = string({results.resourceMetrics.resource.attributes.key});
61+
for i = length(customkeys)
62+
idx = find(resourcekeys == customkeys(i));
63+
verifyNotEmpty(testCase, idx);
64+
verifyEqual(testCase, results.resourceMetrics.resource.attributes(idx).value.doubleValue, customvalues(i));
65+
end
66+
end
67+
68+
end
69+
end

0 commit comments

Comments
 (0)