Skip to content

Commit 2dab550

Browse files
authored
Merge pull request #73 from mathworks/metrics_release
Metrics release
2 parents 99f23be + c9503f1 commit 2dab550

File tree

16 files changed

+518
-162
lines changed

16 files changed

+518
-162
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ set(LIBMEXCLASS_FETCH_CONTENT_NAME libmexclass)
9898

9999
set(LIBMEXCLASS_FETCH_CONTENT_GIT_REPOSITORY "https://github.com/mathworks/libmexclass.git")
100100

101-
set(LIBMEXCLASS_FETCH_CONTENT_GIT_TAG "77f3d72")
101+
set(LIBMEXCLASS_FETCH_CONTENT_GIT_TAG "bf16a65")
102102

103103
set(LIBMEXCLASS_FETCH_CONTENT_SOURCE_SUBDIR "libmexclass/cpp")
104104

README.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
MATLAB® interface to [OpenTelemetry™](https://opentelemetry.io/), based on the [OpenTelemetry Specification](https://opentelemetry.io/docs/reference/specification/). OpenTelemetry is an observability framework for creating and managing telemetry data, such as traces, metrics, and logs. This data can then be sent to an observability back-end for monitoring, alerts, and analysis.
55

66
### Status
7-
- Currently only tracing is supported. Metrics and logs will be in the future.
7+
- Currently only tracing and metrics (synchronous instruments) are supported. Asynchronous metrics instruments and logs will be in the future.
8+
- View class in metrics is only partially supported. The properties **Aggregation** and **AllowedAttributes** are not yet supported.
89
- This package is supported and has been tested on Windows®, Linux®, and macOS.
910

1011
### MathWorks Products (https://www.mathworks.com)
@@ -43,6 +44,7 @@ otelcol --config <otelcol-config-yaml>
4344
>> addpath <OpenTelemetry MATLAB installdir>
4445
```
4546
## Examples
47+
### Tracing
4648
1. Create a default tracer provider and save it.
4749
```
4850
>> p = opentelemetry.sdk.trace.TracerProvider();
@@ -58,6 +60,22 @@ otelcol --config <otelcol-config-yaml>
5860
>> sp.endSpan();
5961
```
6062
4. If your collector is configured to display the data, you should see your span displayed.
63+
### Metrics
64+
1. Create a default meter provider and save it.
65+
```
66+
>> p = opentelemetry.sdk.metrics.MeterProvider();
67+
>> setMeterProvider(p);
68+
```
69+
2. Create a counter
70+
```
71+
>> m = opentelemetry.metrics.getMeter("First Meter");
72+
>> c = m.createCounter("FirstCounter");
73+
```
74+
3. Increment the counter
75+
```
76+
>> c.add(10);
77+
```
78+
4. If your collector is configured to display the data, you should see your counter displayed after 1 minute.
6179

6280
For more examples, see the "examples" folder.
6381

api/metrics/+opentelemetry/+metrics/Counter.m

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,16 @@
1414

1515
methods
1616
function add(obj, value, varargin)
17+
% ADD Add to counter value
18+
% ADD(C, VALUE) adds a nonnegative scalar numeric value to
19+
% the counter.
20+
%
21+
% ADD(C, VALUE, ATTRIBUTES) also specifies attributes as a
22+
% dictionary
23+
%
24+
% ADD(C, VALUE, ATTRNAME1, ATTRVALUE1, ATTRNAME2,
25+
% ATTRVALUE2, ...) specifies attributes as trailing
26+
% name-value pairs.
1727
obj.processValue(value, varargin{:});
1828
end
1929
end

api/metrics/+opentelemetry/+metrics/Histogram.m

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,16 @@
1313

1414
methods
1515
function record(obj, value, varargin)
16+
% RECORD Aggregate a value into a histogram bin
17+
% RECORD(H, VALUE) determine which bin VALUE falls into and
18+
% increment that bin by 1.
19+
%
20+
% RECORD(H, VALUE, ATTRIBUTES) also specifies attributes as a
21+
% dictionary
22+
%
23+
% RECORD(H, VALUE, ATTRNAME1, ATTRVALUE1, ATTRNAME2,
24+
% ATTRVALUE2, ...) specifies attributes as trailing
25+
% name-value pairs.
1626
obj.processValue(value, varargin{:});
1727
end
1828
end

api/metrics/+opentelemetry/+metrics/Meter.m

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,15 @@
3030
methods
3131

3232
function counter = createCounter(obj, ctname, ctdescription, ctunit)
33+
% CREATECOUNTER Create a counter
34+
% C = CREATECOUNTER(M, NAME) creates a counter with the specified
35+
% name. A counter's value can only increase but not
36+
% decrease.
37+
%
38+
% C = CREATECOUNTER(M, NAME, DESCRIPTION, UNIT) also
39+
% specifies a description and a unit.
40+
%
41+
% See also CREATEUPDOWNCOUNTER, CREATEHISTOGRAM
3342
arguments
3443
obj
3544
ctname
@@ -38,8 +47,6 @@
3847
end
3948
import opentelemetry.common.mustBeScalarString
4049
ctname = mustBeScalarString(ctname);
41-
% cpp-opentelemetry end does not allow string input with spaces,
42-
% replace any spaces with underscores as a temporary fix
4350
ctdescription = mustBeScalarString(ctdescription);
4451
ctunit = mustBeScalarString(ctunit);
4552
id = obj.Proxy.createCounter(ctname, ctdescription, ctunit);
@@ -50,6 +57,15 @@
5057

5158

5259
function updowncounter = createUpDownCounter(obj, ctname, ctdescription, ctunit)
60+
% CREATEUPDOWNCOUNTER Create an UpDownCounter
61+
% C = CREATEUPDOWNCOUNTER(M, NAME) creates an UpDownCounter
62+
% with the specified name. An UpDownCounter's value can
63+
% increase or decrease.
64+
%
65+
% C = CREATEUPDOWNCOUNTER(M, NAME, DESCRIPTION, UNIT) also
66+
% specifies a description and a unit.
67+
%
68+
% See also CREATECOUNTER, CREATEHISTOGRAM
5369
arguments
5470
obj
5571
ctname
@@ -59,8 +75,6 @@
5975

6076
import opentelemetry.common.mustBeScalarString
6177
ctname = mustBeScalarString(ctname);
62-
% cpp-opentelemetry end does not allow string input with spaces,
63-
% replace any spaces with underscores as a temporary fix
6478
ctdescription = mustBeScalarString(ctdescription);
6579
ctunit = mustBeScalarString(ctunit);
6680
id = obj.Proxy.createUpDownCounter(ctname, ctdescription, ctunit);
@@ -71,6 +85,16 @@
7185

7286

7387
function histogram = createHistogram(obj, hiname, hidescription, hiunit)
88+
% CREATEHISTOGRAM Create a histogram
89+
% H = CREATEHISTOGRAM(M, NAME) creates a histogram with the specified
90+
% name. A histogram aggregates values into bins. Bins can be
91+
% customized using a View object.
92+
%
93+
% H = CREATEHISTOGRAM(M, NAME, DESCRIPTION, UNIT) also
94+
% specifies a description and a unit.
95+
%
96+
% See also CREATECOUNTER, CREATEUPDOWNCOUNTER,
97+
% OPENTELEMETRY.SDK.METRICS.VIEW
7498
arguments
7599
obj
76100
hiname
@@ -80,8 +104,6 @@
80104

81105
import opentelemetry.common.mustBeScalarString
82106
hiname = mustBeScalarString(hiname);
83-
% cpp-opentelemetry end does not allow string input with spaces,
84-
% replace any spaces with underscores as a temporary fix
85107
hidescription = mustBeScalarString(hidescription);
86108
hiunit = mustBeScalarString(hiunit);
87109
id = obj.Proxy.createHistogram(hiname, hidescription, hiunit);

api/metrics/+opentelemetry/+metrics/UpDownCounter.m

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,16 @@
1313

1414
methods
1515
function add(obj, value, varargin)
16+
% ADD Add to UpDownCounter value
17+
% ADD(C, VALUE) adds scalar numeric value to the
18+
% UpDownCounter. VALUE can be positive or negative.
19+
%
20+
% ADD(C, VALUE, ATTRIBUTES) also specifies attributes as a
21+
% dictionary
22+
%
23+
% ADD(C, VALUE, ATTRNAME1, ATTRVALUE1, ATTRNAME2,
24+
% ATTRVALUE2, ...) specifies attributes as trailing
25+
% name-value pairs.
1626
obj.processValue(value, varargin{:});
1727
end
1828
end

examples/metrics/README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Metrics Example
2+
This example shows how to emit OpenTelemetry metrics from MATLAB. It uses all 3 synchronous instruments counter, updowncounter, and histogram.
3+
* At the beginning of the first run, initialization is necessary to create and store a global meter provider.
4+
* The example then enters a loop and at each iteration updates all 3 instruments. The metrics will then be exported periodically at a fixed time interval.
5+
6+
## Running the Example
7+
1. Start an instance of [OpenTelemetry Collector](https://github.com/open-telemetry/opentelemetry-collector).
8+
2. Start MATLAB.
9+
3. Ensure the installation directory of OpenTelemetry-matlab is on the MATLAB path.
10+
4. Run metrics_example.

examples/metrics/metrics_example.m

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
function metrics_example
2+
% This example creates 3 metric instruments including a counter, an
3+
% updowncounter, and a histogram. It then enters a loop and updates the
4+
% value of the instruments at each iteration.
5+
6+
% Copyright 2023 The MathWorks, Inc.
7+
8+
% initialize meter provider during first run
9+
runOnce(@initMetrics);
10+
11+
% create meter and instruments
12+
m = opentelemetry.metrics.getMeter("metrics_example");
13+
c = createCounter(m, "counter");
14+
u = createUpDownCounter(m, "updowncounter");
15+
h = createHistogram(m, "histogram");
16+
iterations = 20; % number of iterations
17+
18+
for i = 1:iterations
19+
c.add(randi(10));
20+
u.add(randi([-10 10]));
21+
h.record(50 + 15*randn); % normal distribution with mean 50 and std 15
22+
pause(5);
23+
end
24+
end
25+
26+
27+
function initMetrics
28+
% set up global MeterProvider
29+
exp = opentelemetry.exporters.otlp.defaultMetricExporter();
30+
reader = opentelemetry.sdk.metrics.PeriodicExportingMetricReader(exp, ...
31+
"Interval", seconds(5), "Timeout", seconds(2.5)); % exports every 5 seconds
32+
% Use custom histogram bins
33+
v = opentelemetry.sdk.metrics.View(InstrumentType="histogram", HistogramBinEdges=0:10:100);
34+
mp = opentelemetry.sdk.metrics.MeterProvider(reader, View=v);
35+
setMeterProvider(mp);
36+
end
37+
38+
% This helper ensures the input function is only run once
39+
function runOnce(fh)
40+
persistent hasrun
41+
if isempty(hasrun)
42+
feval(fh);
43+
hasrun = 1;
44+
end
45+
end

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

Lines changed: 43 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,23 @@
88
isShutdown (1,1) logical = false
99
end
1010

11-
properties (Access=public)
12-
MetricReader
13-
View
14-
Resource
11+
properties (SetAccess=private)
12+
MetricReader % Metric reader controls how often metrics are exported
13+
View % View object used to customize collected metrics
14+
Resource % Attributes attached to all metrics
1515
end
1616

1717
methods
1818
function obj = MeterProvider(reader, optionnames, optionvalues)
1919
% SDK implementation of meter provider
20-
% MP = OPENTELEMETRY.SDK.METRICS.METERPROVIDER creates a meter
20+
% MP = OPENTELEMETRY.SDK.METRICS.METERPROVIDER creates a meter
2121
% provider that uses a periodic exporting metric reader and default configurations.
2222
%
2323
% MP = OPENTELEMETRY.SDK.METRICS.METERPROVIDER(R) uses metric
24-
% reader R. Currently, the only supported metric reader is the periodic
25-
% exporting metric reader.
24+
% reader R. Currently, the only supported metric reader is the periodic
25+
% exporting metric reader.
2626
%
27-
% TP = OPENTELEMETRY.SDK.METRICS.METERPROVIDER(R, PARAM1, VALUE1,
27+
% TP = OPENTELEMETRY.SDK.METRICS.METERPROVIDER(R, PARAM1, VALUE1,
2828
% PARAM2, VALUE2, ...) specifies optional parameter name/value pairs.
2929
% Parameters are:
3030
% "View" - View object used to customize collected metrics.
@@ -59,10 +59,12 @@
5959
"ConstructorArguments", {mpproxy.ID});
6060
% leave other properties unassigned, they won't be used
6161
else
62-
validnames = ["Resource"];
62+
validnames = ["Resource", "View"];
6363
resourcekeys = string.empty();
6464
resourcevalues = {};
6565
resource = dictionary(resourcekeys, resourcevalues);
66+
suppliedview = false;
67+
viewid = 0;
6668
for i = 1:length(optionnames)
6769
namei = validatestring(optionnames{i}, validnames);
6870
valuei = optionvalues{i};
@@ -79,31 +81,53 @@
7981
if all(cellfun(@iscell, resourcevalues))
8082
resourcevalues = [resourcevalues{:}];
8183
end
84+
elseif strcmp(namei, "View")
85+
suppliedview = true;
86+
view = valuei;
87+
if ~isa(view, "opentelemetry.sdk.metrics.View")
88+
error("opentelemetry:sdk:metrics:MeterProvider:InvalidViewType", ...
89+
"View input must be a opentelemetry.sdk.metrics.View object.");
90+
end
91+
viewid = view.Proxy.ID;
8292
end
8393
end
8494

8595
obj.Proxy = libmexclass.proxy.Proxy("Name", ...
8696
"libmexclass.opentelemetry.sdk.MeterProviderProxy", ...
87-
"ConstructorArguments", {reader.Proxy.ID, resourcekeys, resourcevalues});
97+
"ConstructorArguments", {reader.Proxy.ID, resourcekeys, ...
98+
resourcevalues, suppliedview, viewid});
8899
obj.MetricReader = reader;
89100
obj.Resource = resource;
101+
if suppliedview
102+
obj.View = view;
103+
end
90104
end
91105
end
92-
106+
93107
function addMetricReader(obj, reader)
94-
arguments
95-
obj
96-
reader (1,1) {mustBeA(reader, "opentelemetry.sdk.metrics.PeriodicExportingMetricReader")}
97-
end
108+
% ADDMETRICREADER Add an additional metric reader
109+
% ADDMETRICREADER(MP, R) adds an additional metric reader
110+
% R to the list of metric readers used by meter provider
111+
% MP.
112+
%
113+
% See also ADDVIEW, OPENTELEMETRY.SDK.METRICS.PERIODICEXPORTINGMETRICREADER
114+
arguments
115+
obj
116+
reader (1,1) {mustBeA(reader, "opentelemetry.sdk.metrics.PeriodicExportingMetricReader")}
117+
end
98118
obj.Proxy.addMetricReader(reader.Proxy.ID);
99119
obj.MetricReader = [obj.MetricReader, reader];
100120
end
101121

102122
function addView(obj, view)
103-
arguments
104-
obj
105-
view (1,1) {mustBeA(view, "opentelemetry.sdk.metrics.View")}
106-
end
123+
% ADDVIEW Add an additional view
124+
% ADDVIEW(MP, V) adds an additional view V.
125+
%
126+
% See also ADDMETRICREADER, OPENTELEMETRY.SDK.METRICS.VIEW
127+
arguments
128+
obj
129+
view (1,1) {mustBeA(view, "opentelemetry.sdk.metrics.View")}
130+
end
107131
obj.Proxy.addView(view.Proxy.ID);
108132
obj.View = [obj.View, view];
109133
end

sdk/metrics/+opentelemetry/+sdk/+metrics/MetricExporter.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
methods
2525
function obj = set.PreferredAggregationTemporality(obj, temporality)
2626
temporality = validatestring(temporality, ["cumulative", "delta"]);
27-
obj.Proxy.setTemporality(temporality);
27+
obj.Proxy.setTemporality(temporality); %#ok<MCSUP>
2828
obj.PreferredAggregationTemporality = temporality;
2929
end
3030

0 commit comments

Comments
 (0)