Skip to content

Commit

Permalink
enable specifying folders in AutoTrace options, closes #163
Browse files Browse the repository at this point in the history
  • Loading branch information
duncanpo committed Oct 26, 2024
1 parent e81c793 commit 1b9ff8a
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 15 deletions.
53 changes: 38 additions & 15 deletions auto-instrumentation/+opentelemetry/+autoinstrument/AutoTrace.m
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,15 @@
options.AdditionalFiles {mustBeText}
options.AutoDetectFiles (1,1) {mustBeNumericOrLogical} = true
end
% check for anonymous function
fs = functions(startfun);
if fs.type == "anonymous"
error("opentelemetry:autoinstrument:AutoTrace:AnonymousFunction", ...
"Anonymous functions are not supported.");
end
obj.StartFunction = startfun;
startfunname = func2str(startfun);
processFileInput(startfunname); % validate startfun
startfunname = processFileInput(startfunname); % validate startfun
if options.AutoDetectFiles
if isdeployed
% matlab.codetools.requiredFilesAndProducts is not
Expand All @@ -76,15 +82,16 @@
end
else
% only include the input file, not its dependencies
files = string(which(startfunname));
files = startfunname;
end
% add extra files, this is intended for files
% matlab.codetools.requiredFilesAndProducts somehow missed
if isfield(options, "AdditionalFiles")
incfiles = string(options.AdditionalFiles);
for i = 1:numel(incfiles)
incfiles(i) = which(incfiles(i)); % get the full path
processFileInput(incfiles(i)); % validate additional file
incinput = string(options.AdditionalFiles);
incfiles = [];
for i = 1:numel(incinput)
% validate additional file
incfiles = [incfiles; processFileOrFolderInput(incinput(i))]; %#ok<AGROW>
end
files = union(files, incfiles);
end
Expand All @@ -94,9 +101,11 @@

% filter out excluded files
if isfield(options, "ExcludeFiles")
excfiles = string(options.ExcludeFiles);
for i = 1:numel(excfiles)
excfiles(i) = which(excfiles(i)); % get the full path
excinput = string(options.ExcludeFiles);
excfiles = [];
for i = 1:numel(excinput)
% validate exclude file
excfiles = [excfiles; processFileOrFolderInput(excinput(i))]; %#ok<AGROW>
end
files = setdiff(files, excfiles);
end
Expand Down Expand Up @@ -155,15 +164,13 @@ function handleError(obj, ME)
end

% check input file is valid
function processFileInput(f)
function f = processFileInput(f)
f = string(f); % force into a string
if startsWith(f, '@') % check for anonymous function
error("opentelemetry:autoinstrument:AutoTrace:AnonymousFunction", ...
replace(f, "\", "\\") + " is an anonymous function and is not supported.");
end
[~,~,fext] = fileparts(f); % check file extension
filetype = exist(f, "file"); % check file type
if ~(filetype == 2 && ismember(fext, ["" ".m" ".mlx"]))
if filetype == 2 && ismember(fext, ["" ".m" ".mlx"])
f = string(which(f));
else
if exist(f, "builtin")
error("opentelemetry:autoinstrument:AutoTrace:BuiltinFunction", ...
replace(f, "\", "\\") + " is a builtin function and is not supported.");
Expand All @@ -172,4 +179,20 @@ function processFileInput(f)
replace(f, "\", "\\") + " is not found or is not a valid MATLAB file with a .m or .mlx extension.");
end
end
end

% check input file or folder is valid
function f = processFileOrFolderInput(f)
f = string(f); % force into a string
if isfolder(f)
% expand the directory
mfileinfo = dir(fullfile(f, "*.m"));
mfiles = fullfile(string({mfileinfo.folder}), string({mfileinfo.name}));
mlxfileinfo = dir(fullfile(f, "*.mlx"));
mlxfiles = fullfile(string({mlxfileinfo.folder}), string({mlxfileinfo.name}));
f = [mfiles; mlxfiles];
else
% file
f = processFileInput(f);
end
end
9 changes: 9 additions & 0 deletions test/autotrace_examples/example2/example2.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
function x = example2
% example code for testing auto instrumentation.

% Copyright 2024 The MathWorks, Inc.

x = 10;
x = ex2helper1(x);
x = ex2helper2(x);

6 changes: 6 additions & 0 deletions test/autotrace_examples/example2/helpers/ex2helper1.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
function x = ex2helper1(x)
% example code for testing auto instrumentation

% Copyright 2024 The MathWorks, Inc.

x = x * 2;
6 changes: 6 additions & 0 deletions test/autotrace_examples/example2/helpers/ex2helper2.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
function x = ex2helper2(x)
% example code for testing auto instrumentation

% Copyright 2024 The MathWorks, Inc.

x = x * 3;
52 changes: 52 additions & 0 deletions test/tautotrace.m
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ function setupOnce(testCase)
% add the example folders to the path
example1folder = fullfile(fileparts(mfilename('fullpath')), "autotrace_examples", "example1");
testCase.applyFixture(matlab.unittest.fixtures.PathFixture(example1folder));
example2folder = fullfile(fileparts(mfilename('fullpath')), "autotrace_examples", "example2");
testCase.applyFixture(matlab.unittest.fixtures.PathFixture(example2folder));
example2helpersfolder = fullfile(fileparts(mfilename('fullpath')), "autotrace_examples", "example2", "helpers");
testCase.applyFixture(matlab.unittest.fixtures.PathFixture(example2helpersfolder));
commonSetupOnce(testCase);

% configure the global tracer provider
Expand Down Expand Up @@ -115,6 +119,54 @@ function testDisableFileDetection(testCase)
verifyEqual(testCase, string(results{1}.resourceSpans.scopeSpans.spans.name), "example1");
end

function testIncludeFolder(testCase)
% testIncludeFolder: specify a folder in AdditionalFiles

% set up AutoTrace
example2helpers = fullfile(fileparts(mfilename('fullpath')), ...
"autotrace_examples", "example2", "helpers");
% turn off automatic detection and specify dependencies using
% their folder name
at = opentelemetry.autoinstrument.AutoTrace(@example2, ...
"AutoDetectFiles", false, "AdditionalFiles", example2helpers);

% run the example
[~] = beginTrace(at);

% perform test comparisons
results = readJsonResults(testCase);
verifyNumElements(testCase, results, 3);

% check span names
verifyEqual(testCase, string(results{1}.resourceSpans.scopeSpans.spans.name), "ex2helper1");
verifyEqual(testCase, string(results{2}.resourceSpans.scopeSpans.spans.name), "ex2helper2");
verifyEqual(testCase, string(results{3}.resourceSpans.scopeSpans.spans.name), "example2");

% check parent children relationship
verifyEqual(testCase, results{1}.resourceSpans.scopeSpans.spans.parentSpanId, results{3}.resourceSpans.scopeSpans.spans.spanId);
verifyEqual(testCase, results{2}.resourceSpans.scopeSpans.spans.parentSpanId, results{3}.resourceSpans.scopeSpans.spans.spanId);
end

function testExcludeFolder(testCase)
% testExcludeFolder: specify a folder in ExcludeFiles

% set up AutoTrace
example2helpers = fullfile(fileparts(mfilename('fullpath')), ...
"autotrace_examples", "example2", "helpers");
at = opentelemetry.autoinstrument.AutoTrace(@example2, ...
"ExcludeFiles", example2helpers);

% run the example
[~] = beginTrace(at);

% perform test comparisons
results = readJsonResults(testCase);
verifyNumElements(testCase, results, 1);

% check span names
verifyEqual(testCase, string(results{1}.resourceSpans.scopeSpans.spans.name), "example2");
end

function testNonFileOptions(testCase)
% testNonFileOptions: other options not related to files,
% "TracerName", "TracerVersion", "TracerSchema", "Attributes",
Expand Down

0 comments on commit 1b9ff8a

Please sign in to comment.