Skip to content

Commit f4f2933

Browse files
authored
Merge pull request #236 from mathworks/mbt-plugin
Initial MBT plugin draft
2 parents 0ef3d29 + 865d1e0 commit f4f2933

File tree

6 files changed

+689
-3
lines changed

6 files changed

+689
-3
lines changed

.github/workflows/build_and_test_full.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ on:
55
push:
66
branches:
77
- main
8+
- mbt-plugin
89
env:
910
MLM_LICENSE_TOKEN: ${{ secrets.MLM_LICENSE_TOKEN }}
1011
jobs:
@@ -40,7 +41,7 @@ jobs:
4041
- name: Install MATLAB
4142
uses: matlab-actions/setup-matlab@v2
4243
with:
43-
release: R2025a
44+
release: latest-including-prerelease
4445
products: MATLAB_Compiler MATLAB_Compiler_SDK
4546
- name: Build OpenTelemetry-Matlab
4647
working-directory: opentelemetry-matlab
@@ -71,7 +72,7 @@ jobs:
7172
- name: Install MATLAB
7273
uses: matlab-actions/setup-matlab@v2
7374
with:
74-
release: R2025a
75+
release: latest-including-prerelease
7576
products: MATLAB_Compiler MATLAB_Compiler_SDK
7677
- name: Build OpenTelemetry-Matlab
7778
working-directory: opentelemetry-matlab

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,7 @@ set(METRICS_SDK_MATLAB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/sdk/metrics/+opentele
591591
set(LOGS_SDK_MATLAB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/sdk/logs/+opentelemetry)
592592
set(COMMON_SDK_MATLAB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/sdk/common/+opentelemetry)
593593
set(AUTO_INSTRUMENTATION_MATLAB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/auto-instrumentation/+opentelemetry)
594+
set(INSTRUMENTATION_MBT_MATLAB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/instrumentation/buildtool/+matlab)
594595
set(EXPORTER_MATLAB_SOURCES
595596
${CMAKE_CURRENT_SOURCE_DIR}/exporters/otlp/+opentelemetry/+exporters/+otlp/defaultSpanExporter.m
596597
${CMAKE_CURRENT_SOURCE_DIR}/exporters/otlp/+opentelemetry/+exporters/+otlp/defaultMetricExporter.m
@@ -626,6 +627,7 @@ install(DIRECTORY ${METRICS_SDK_MATLAB_SOURCES} DESTINATION .)
626627
install(DIRECTORY ${LOGS_SDK_MATLAB_SOURCES} DESTINATION .)
627628
install(DIRECTORY ${COMMON_SDK_MATLAB_SOURCES} DESTINATION .)
628629
install(DIRECTORY ${AUTO_INSTRUMENTATION_MATLAB_SOURCES} DESTINATION .)
630+
install(DIRECTORY ${INSTRUMENTATION_MBT_MATLAB_SOURCES} DESTINATION .)
629631
install(FILES ${EXPORTER_MATLAB_SOURCES} DESTINATION ${OTLP_EXPORTERS_DIR})
630632
if(WITH_OTLP_HTTP)
631633
install(FILES ${OTLP_HTTP_EXPORTER_MATLAB_SOURCES} DESTINATION ${OTLP_EXPORTERS_DIR})

codecov.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,5 @@ fixes:
1111
- "\\+opentelemetry/\\+baggage/::api/baggage/+opentelemetry/+baggage/"
1212
- "\\+opentelemetry/\\+exporters/\\+otlp/::exporters/otlp/+opentelemetry/+exporters/+otlp/"
1313
- "\\+opentelemetry/\\+sdk/\\+logs::sdk/logs/+opentelemetry/+sdk/+logs/"
14-
- "\\+opentelemetry/\\+logs/::api/logs/+opentelemetry/+logs/"
14+
- "\\+opentelemetry/\\+logs/::api/logs/+opentelemetry/+logs/"
15+
- "\\+matlab/\\+buildtool/::instrumentation/buildtool/+matlab/+buildtool/"
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
classdef OpenTelemetryPluginService < matlab.buildtool.internal.services.plugins.BuildRunnerPluginService
2+
% This class is unsupported and might change or be removed without notice
3+
% in a future version.
4+
5+
% Copyright 2026 The MathWorks, Inc.
6+
7+
methods
8+
function plugins = providePlugins(~, ~)
9+
plugins = matlab.buildtool.plugins.BuildRunnerPlugin.empty(1,0);
10+
if ~isMATLABReleaseOlderThan("R2026a")
11+
plugins = matlab.buildtool.plugins.OpenTelemetryPlugin();
12+
end
13+
end
14+
end
15+
end
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
classdef OpenTelemetryPlugin < matlab.buildtool.plugins.BuildRunnerPlugin
2+
3+
% Copyright 2026 The MathWorks, Inc.
4+
5+
methods(Access = protected)
6+
function runBuild(plugin, pluginData)
7+
% Configure by attaching to span if passed in via environment
8+
% variable, and propagating baggage
9+
configureOTel();
10+
11+
tr = opentelemetry.trace.getTracer("buildtool");
12+
sp = tr.startSpan("buildtool");
13+
scope = makeCurrent(sp); %#ok<NASGU>
14+
15+
% Run build
16+
runBuild@matlab.buildtool.plugins.BuildRunnerPlugin(plugin, pluginData);
17+
18+
% Update status
19+
if pluginData.BuildResult.Failed
20+
sp.setStatus("Error", "Build completed, results not successful");
21+
else
22+
sp.setStatus("Ok");
23+
end
24+
25+
% Results-based attributes
26+
taskResults = pluginData.BuildResult.TaskResults;
27+
successful = [taskResults([taskResults.Successful]).Name];
28+
failed = [taskResults([taskResults.Failed]).Name];
29+
skipped = [taskResults([taskResults.Skipped]).Name];
30+
31+
sp.setAttributes( ...
32+
"buildtool.tasks", numel(pluginData.BuildResult.TaskResults), ...
33+
"buildtool.tasks.successful", successful, ...
34+
"buildtool.tasks.failed", failed, ...
35+
"buildtool.tasks.skipped", skipped, ...
36+
"buildtool.build.successes", numel(successful), ...
37+
"buildtool.build.failures", numel(failed), ...
38+
"buildtool.build.skips", numel(skipped) ...
39+
);
40+
41+
% Update metrics
42+
meter = opentelemetry.metrics.getMeter("buildtool");
43+
successes = meter.createCounter("buildtool.tasks.successful");
44+
failures = meter.createCounter("buildtool.tasks.failed");
45+
skips = meter.createCounter("buildtool.tasks.skipped");
46+
buildSuccesses = meter.createCounter("buildtool.build.successes");
47+
buildFailures = meter.createCounter("buildtool.build.failures");
48+
49+
successes.add(numel(successful));
50+
failures.add(numel(failed));
51+
skips.add(numel(skipped));
52+
buildSuccesses.add(double(~pluginData.BuildResult.Failed));
53+
buildFailures.add(double(pluginData.BuildResult.Failed));
54+
55+
cleanupOTel(sp);
56+
end
57+
58+
function runTask(plugin, pluginData)
59+
% TODO:
60+
% - buildtool.task.outputs
61+
% - buildtool.task.inputs
62+
63+
% Definitions
64+
task = pluginData.TaskGraph.Tasks;
65+
taskName = pluginData.Name;
66+
taskDescription = task.Description;
67+
68+
% Attributes
69+
otelAttributes = dictionary( ...
70+
[ ...
71+
"buildtool.task.name", ...
72+
"buildtool.task.description", ...
73+
], ...
74+
[ ...
75+
taskName, ...
76+
taskDescription ...
77+
] ...
78+
);
79+
80+
tr = opentelemetry.trace.getTracer(taskName);
81+
sp = tr.startSpan(taskName, Attributes=otelAttributes);
82+
scope = makeCurrent(sp); %#ok<NASGU>
83+
84+
% Run task
85+
runTask@matlab.buildtool.plugins.BuildRunnerPlugin(plugin, pluginData);
86+
87+
% Set results-based attributes
88+
resultAttributes = dictionary( ...
89+
[ ...
90+
"buildtool.task.successful", ...
91+
"buildtool.task.failed", ...
92+
"buildtool.task.skipped" ...
93+
], ...
94+
[ ...
95+
pluginData.TaskResults.Successful, ...
96+
pluginData.TaskResults.Failed, ...
97+
pluginData.TaskResults.Skipped ...
98+
] ...
99+
);
100+
sp.setAttributes(resultAttributes);
101+
102+
% Update span status
103+
if pluginData.TaskResults.Successful
104+
sp.setStatus("Ok");
105+
else
106+
sp.setStatus("Error", "Task completed, results not successful");
107+
end
108+
109+
sp.endSpan();
110+
end
111+
end
112+
end
113+
114+
% Use the same configuration as PADV
115+
function extcontextscope = configureOTel()
116+
117+
% Skip configuration if NO_MBT_OTEL_CONFIG set
118+
if (getenv("NO_MBT_OTEL_CONFIG"))
119+
return;
120+
end
121+
122+
% populate resource attributes
123+
otelservicename = "buildtool";
124+
otelresource = dictionary("service.name", otelservicename);
125+
126+
% baggage propagation
127+
otelbaggage = getenv("BAGGAGE");
128+
if ~isempty(otelbaggage)
129+
otelbaggage = split(split(string(otelbaggage),','), "=");
130+
otelresource = insert(otelresource, otelbaggage(:,1), otelbaggage(:,2));
131+
end
132+
133+
% check for passed in external context
134+
extcontextscope = [];
135+
traceid = getenv("TRACE_ID");
136+
spanid = getenv("SPAN_ID");
137+
if ~isempty(traceid) && ~isempty(spanid)
138+
spcontext = opentelemetry.trace.SpanContext(traceid, spanid);
139+
extcontextscope = makeCurrent(spcontext);
140+
end
141+
142+
% tracer provider
143+
otelspexp = opentelemetry.exporters.otlp.OtlpGrpcSpanExporter; % use gRPC because Otel plugin for Jenkins only use gRPC
144+
otelspproc = opentelemetry.sdk.trace.BatchSpanProcessor(otelspexp);
145+
oteltp = opentelemetry.sdk.trace.TracerProvider(otelspproc, Resource=otelresource);
146+
setTracerProvider(oteltp);
147+
148+
% meter provider
149+
otelmexp = opentelemetry.exporters.otlp.OtlpGrpcMetricExporter; % use gRPC because Otel plugin for Jenkins only use gRPC
150+
otelmread = opentelemetry.sdk.metrics.PeriodicExportingMetricReader(otelmexp);
151+
otelmp = opentelemetry.sdk.metrics.MeterProvider(otelmread, Resource=otelresource);
152+
setMeterProvider(otelmp);
153+
154+
% logger provider
155+
otellgexp = opentelemetry.exporters.otlp.OtlpGrpcLogRecordExporter; % use gRPC because Otel plugin for Jenkins only use gRPC
156+
otellgproc = opentelemetry.sdk.logs.BatchLogRecordProcessor(otellgexp);
157+
otellp = opentelemetry.sdk.logs.LoggerProvider(otellgproc, Resource=otelresource);
158+
setLoggerProvider(otellp);
159+
end
160+
161+
% Use the same cleanup as PADV
162+
function cleanupOTel(span)
163+
164+
% Skip cleanup if NO_MBT_OTEL_CONFIG set
165+
if (getenv("NO_MBT_OTEL_CONFIG"))
166+
return;
167+
end
168+
169+
timeout = 5;
170+
171+
% end the input span before cleaning up
172+
if nargin > 0
173+
endSpan(span);
174+
end
175+
176+
% tracer provider
177+
oteltp = opentelemetry.trace.Provider.getTracerProvider;
178+
opentelemetry.sdk.common.Cleanup.forceFlush(oteltp, timeout);
179+
opentelemetry.sdk.common.Cleanup.shutdown(oteltp);
180+
181+
% meter provider
182+
otelmp = opentelemetry.metrics.Provider.getMeterProvider;
183+
opentelemetry.sdk.common.Cleanup.forceFlush(otelmp, timeout);
184+
opentelemetry.sdk.common.Cleanup.shutdown(otelmp);
185+
186+
% logger provider
187+
otellp = opentelemetry.logs.Provider.getLoggerProvider;
188+
opentelemetry.sdk.common.Cleanup.forceFlush(otellp, timeout);
189+
opentelemetry.sdk.common.Cleanup.shutdown(otellp);
190+
end

0 commit comments

Comments
 (0)