From 35bcf7f5d4486ab3fc3ce39da9998011bc832429 Mon Sep 17 00:00:00 2001 From: Scott Estabrook Date: Wed, 4 Dec 2024 10:35:52 -0500 Subject: [PATCH 01/12] Updating Testing Branch & adding benchmarking workflow --- .github/workflows/performance_benchmark.yml | 70 +++++++++++++++++++++ test/performance/runPerf.m | 5 ++ 2 files changed, 75 insertions(+) create mode 100644 .github/workflows/performance_benchmark.yml create mode 100644 test/performance/runPerf.m diff --git a/.github/workflows/performance_benchmark.yml b/.github/workflows/performance_benchmark.yml new file mode 100644 index 0000000..00255c2 --- /dev/null +++ b/.github/workflows/performance_benchmark.yml @@ -0,0 +1,70 @@ +# Performance benchmarking workflow +name: "Build and Run Benchmark" +on: + workflow_dispatch: + push: + branches-ignore: + - 'main' + - '[0-9]+.[0-9]+.[0-9]+' +env: + MLM_LICENSE_TOKEN: ${{ secrets.MLM_LICENSE_TOKEN }} +jobs: + get_version: + runs-on: ubuntu-20.04 + outputs: + version: ${{ steps.getversion.outputs.latest_tag }} + steps: + # need fetch-depth:0 to also download the tags + - name: Download OpenTelemetry-Matlab source + uses: actions/checkout@v3 + with: + path: opentelemetry-matlab + fetch-depth: 0 + - name: Get Version + id: getversion + shell: bash + working-directory: opentelemetry-matlab + run: echo "latest_tag=$(sed -re 's/^v?([[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+)?.*/\1/' <<< $(git describe --tags --abbrev=0))" >> $GITHUB_OUTPUT + benchmark-ubuntu: + # Running on ubuntu-latest would use a glibc version that is incompatible when using the built mex files on a Debian 11 + # Instead, run on ubuntu-20.04 + runs-on: ubuntu-20.04 + needs: get_version + env: + OPENTELEMETRY_MATLAB_INSTALL: "${{ github.workspace }}/otel_matlab_install" + SYSTEM_LIBSTDCPP_PATH: "/usr/lib/x86_64-linux-gnu/libstdc++.so.6" + steps: + - name: Download OpenTelemetry-Matlab source + uses: actions/checkout@v3 + with: + path: opentelemetry-matlab + - name: Install ninja-build + run: sudo apt-get install ninja-build + - name: Install MATLAB + uses: matlab-actions/setup-matlab@v2 + with: + products: MATLAB_Compiler MATLAB_Compiler_SDK + - name: Build OpenTelemetry-Matlab + working-directory: opentelemetry-matlab + run: | + cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DWITH_EXAMPLES=ON -DUSE_BATCH_FOR_MCC=ON -DOTEL_MATLAB_VERSION=${{ needs.get_version.outputs.version }} -DCMAKE_INSTALL_PREFIX=${{ env.OPENTELEMETRY_MATLAB_INSTALL }} + cmake --build build --config Release --target install + - name: Run Benchmark + env: + # Add the installation directory to the MATLAB Search Path by + # setting the MATLABPATH environment variable. + MATLABPATH: ${{ env.OPENTELEMETRY_MATLAB_INSTALL }} + uses: matlab-actions/run-command@v2 + with: + command: opentelemetry-matlab/test/performance/runPerf + - name: Download previous benchmark data + uses: actions/cache@v4 + with: + path: ./cache + key: ${{ runner.os }}-benchmark + - name: Store benchmark result + uses: benchmark-action/github-action-benchmark@v1 + with: + tool: 'customSmallerIsBetter' + output-file-path: opentelemetry-matlab/test/performance/Benchmarks/OutputBenchmark.json + external-data-json-path: ./cache/OutputBenchmark.json \ No newline at end of file diff --git a/test/performance/runPerf.m b/test/performance/runPerf.m new file mode 100644 index 0000000..9365721 --- /dev/null +++ b/test/performance/runPerf.m @@ -0,0 +1,5 @@ +T = runperf(); +u(1:size(T.sampleSummary,1)) = "seconds"; +S = struct("name",cellstr(T.sampleSummary.Name),"unit",cellstr(u'),"value",num2cell(T.sampleSummary.Mean)); +mkdir("Benchmarks"); +writestruct(S,"./Benchmarks/OutputBenchmark.json") \ No newline at end of file From ac85bd0dea7b1d85d4d2f29aac9a073bd5d196b9 Mon Sep 17 00:00:00 2001 From: Scott Estabrook Date: Wed, 4 Dec 2024 10:59:07 -0500 Subject: [PATCH 02/12] Update run-command in matlab actions --- .github/workflows/performance_benchmark.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/performance_benchmark.yml b/.github/workflows/performance_benchmark.yml index 00255c2..05c0ace 100644 --- a/.github/workflows/performance_benchmark.yml +++ b/.github/workflows/performance_benchmark.yml @@ -56,7 +56,7 @@ jobs: MATLABPATH: ${{ env.OPENTELEMETRY_MATLAB_INSTALL }} uses: matlab-actions/run-command@v2 with: - command: opentelemetry-matlab/test/performance/runPerf + command: addpath("./test/performance"), runPerf - name: Download previous benchmark data uses: actions/cache@v4 with: From 39ec8f29a89ace5a798547010ad82e475dda540c Mon Sep 17 00:00:00 2001 From: Scott Estabrook Date: Wed, 4 Dec 2024 11:00:59 -0500 Subject: [PATCH 03/12] Update run-command in matlab actions --- .github/workflows/performance_benchmark.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/performance_benchmark.yml b/.github/workflows/performance_benchmark.yml index 05c0ace..40d687f 100644 --- a/.github/workflows/performance_benchmark.yml +++ b/.github/workflows/performance_benchmark.yml @@ -66,5 +66,5 @@ jobs: uses: benchmark-action/github-action-benchmark@v1 with: tool: 'customSmallerIsBetter' - output-file-path: opentelemetry-matlab/test/performance/Benchmarks/OutputBenchmark.json + output-file-path: ./Benchmarks/OutputBenchmark.json external-data-json-path: ./cache/OutputBenchmark.json \ No newline at end of file From 8d181d4f057cd82cd43d2c1b52ecf7bca8faf920 Mon Sep 17 00:00:00 2001 From: Scott Estabrook Date: Wed, 4 Dec 2024 11:34:10 -0500 Subject: [PATCH 04/12] update matlab-actions run command syntax --- .github/workflows/performance_benchmark.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/performance_benchmark.yml b/.github/workflows/performance_benchmark.yml index 40d687f..b48905e 100644 --- a/.github/workflows/performance_benchmark.yml +++ b/.github/workflows/performance_benchmark.yml @@ -56,7 +56,7 @@ jobs: MATLABPATH: ${{ env.OPENTELEMETRY_MATLAB_INSTALL }} uses: matlab-actions/run-command@v2 with: - command: addpath("./test/performance"), runPerf + command: addpath("test/performance"), runPerf - name: Download previous benchmark data uses: actions/cache@v4 with: From f4dde9ac305df2079e52ebd4b82b493953d1dc1c Mon Sep 17 00:00:00 2001 From: Scott Estabrook Date: Fri, 17 Jan 2025 13:40:56 -0500 Subject: [PATCH 05/12] Update workflow so working directory has access to performance files --- .github/workflows/performance_benchmark.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/performance_benchmark.yml b/.github/workflows/performance_benchmark.yml index b48905e..6a61d93 100644 --- a/.github/workflows/performance_benchmark.yml +++ b/.github/workflows/performance_benchmark.yml @@ -50,13 +50,14 @@ jobs: cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DWITH_EXAMPLES=ON -DUSE_BATCH_FOR_MCC=ON -DOTEL_MATLAB_VERSION=${{ needs.get_version.outputs.version }} -DCMAKE_INSTALL_PREFIX=${{ env.OPENTELEMETRY_MATLAB_INSTALL }} cmake --build build --config Release --target install - name: Run Benchmark + working-directory: opentelemetry-matlab env: # Add the installation directory to the MATLAB Search Path by # setting the MATLABPATH environment variable. MATLABPATH: ${{ env.OPENTELEMETRY_MATLAB_INSTALL }} uses: matlab-actions/run-command@v2 with: - command: addpath("test/performance"), runPerf + command: addpath("./test/performance"), runPerf - name: Download previous benchmark data uses: actions/cache@v4 with: From 3961498f9f016ce8f3b024ef0f241592486c5633 Mon Sep 17 00:00:00 2001 From: Scott Estabrook <124709205+MWSestabro@users.noreply.github.com> Date: Fri, 17 Jan 2025 13:46:39 -0500 Subject: [PATCH 06/12] Update performance_benchmark.yml Remove invalid working directory call --- .github/workflows/performance_benchmark.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/performance_benchmark.yml b/.github/workflows/performance_benchmark.yml index 6a61d93..b096061 100644 --- a/.github/workflows/performance_benchmark.yml +++ b/.github/workflows/performance_benchmark.yml @@ -50,7 +50,6 @@ jobs: cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DWITH_EXAMPLES=ON -DUSE_BATCH_FOR_MCC=ON -DOTEL_MATLAB_VERSION=${{ needs.get_version.outputs.version }} -DCMAKE_INSTALL_PREFIX=${{ env.OPENTELEMETRY_MATLAB_INSTALL }} cmake --build build --config Release --target install - name: Run Benchmark - working-directory: opentelemetry-matlab env: # Add the installation directory to the MATLAB Search Path by # setting the MATLABPATH environment variable. @@ -68,4 +67,4 @@ jobs: with: tool: 'customSmallerIsBetter' output-file-path: ./Benchmarks/OutputBenchmark.json - external-data-json-path: ./cache/OutputBenchmark.json \ No newline at end of file + external-data-json-path: ./cache/OutputBenchmark.json From b5739b2f146b8ba7eeb4da14e0a0aa35571a10e0 Mon Sep 17 00:00:00 2001 From: Scott Estabrook <124709205+MWSestabro@users.noreply.github.com> Date: Fri, 17 Jan 2025 14:08:06 -0500 Subject: [PATCH 07/12] Update performance_benchmark.yml Updating performance tests to use matlab-actions run command --- .github/workflows/performance_benchmark.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/performance_benchmark.yml b/.github/workflows/performance_benchmark.yml index b096061..7a1d698 100644 --- a/.github/workflows/performance_benchmark.yml +++ b/.github/workflows/performance_benchmark.yml @@ -56,7 +56,7 @@ jobs: MATLABPATH: ${{ env.OPENTELEMETRY_MATLAB_INSTALL }} uses: matlab-actions/run-command@v2 with: - command: addpath("./test/performance"), runPerf + command: run("test/performance/runperf.m") - name: Download previous benchmark data uses: actions/cache@v4 with: From 48cc3e022139229f30155ffa8010854ce78616de Mon Sep 17 00:00:00 2001 From: Scott Estabrook <124709205+MWSestabro@users.noreply.github.com> Date: Fri, 17 Jan 2025 14:30:43 -0500 Subject: [PATCH 08/12] Update performance_benchmark.yml Updating runperf to use full path --- .github/workflows/performance_benchmark.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/performance_benchmark.yml b/.github/workflows/performance_benchmark.yml index 7a1d698..0b00049 100644 --- a/.github/workflows/performance_benchmark.yml +++ b/.github/workflows/performance_benchmark.yml @@ -56,7 +56,7 @@ jobs: MATLABPATH: ${{ env.OPENTELEMETRY_MATLAB_INSTALL }} uses: matlab-actions/run-command@v2 with: - command: run("test/performance/runperf.m") + command: run("opentelemetry-matlab/test/performance/runperf.m") - name: Download previous benchmark data uses: actions/cache@v4 with: From b4db5ffa46511ee1b82598f62ccbbb11e4e4fe10 Mon Sep 17 00:00:00 2001 From: Scott Estabrook <124709205+MWSestabro@users.noreply.github.com> Date: Fri, 17 Jan 2025 15:42:20 -0500 Subject: [PATCH 09/12] Update performance_benchmark.yml Remove search path change --- .github/workflows/performance_benchmark.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/performance_benchmark.yml b/.github/workflows/performance_benchmark.yml index 0b00049..709481a 100644 --- a/.github/workflows/performance_benchmark.yml +++ b/.github/workflows/performance_benchmark.yml @@ -50,10 +50,6 @@ jobs: cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DWITH_EXAMPLES=ON -DUSE_BATCH_FOR_MCC=ON -DOTEL_MATLAB_VERSION=${{ needs.get_version.outputs.version }} -DCMAKE_INSTALL_PREFIX=${{ env.OPENTELEMETRY_MATLAB_INSTALL }} cmake --build build --config Release --target install - name: Run Benchmark - env: - # Add the installation directory to the MATLAB Search Path by - # setting the MATLABPATH environment variable. - MATLABPATH: ${{ env.OPENTELEMETRY_MATLAB_INSTALL }} uses: matlab-actions/run-command@v2 with: command: run("opentelemetry-matlab/test/performance/runperf.m") From 0267d6283f8372c8cea858cd9f3ad1b313a8d9c6 Mon Sep 17 00:00:00 2001 From: Scott Estabrook Date: Wed, 30 Jul 2025 14:13:17 -0400 Subject: [PATCH 10/12] Added test cases to improve code coverage --- test/callbacks/callbackWithAttributes3.m | 8 ++ test/tformat.m | 147 +++++++++++++++++++++++ test/thttpheaders.m | 147 +++++++++++++++++++++++ test/tjsonbytesmapping.m | 147 +++++++++++++++++++++++ test/tlogs_sdk.m | 26 ++++ test/tmetrics.m | 31 +++++ test/tmetrics_sdk.m | 49 ++++++++ test/ttimeout.m | 147 +++++++++++++++++++++++ test/ttrace_sdk.m | 48 ++++++++ test/tusejsonname.m | 147 +++++++++++++++++++++++ 10 files changed, 897 insertions(+) create mode 100644 test/callbacks/callbackWithAttributes3.m create mode 100644 test/tformat.m create mode 100644 test/thttpheaders.m create mode 100644 test/tjsonbytesmapping.m create mode 100644 test/ttimeout.m create mode 100644 test/tusejsonname.m diff --git a/test/callbacks/callbackWithAttributes3.m b/test/callbacks/callbackWithAttributes3.m new file mode 100644 index 0000000..0756373 --- /dev/null +++ b/test/callbacks/callbackWithAttributes3.m @@ -0,0 +1,8 @@ +function result = callbackWithAttributes3() +% Test callback function for asynchronous instruments that uses attributes +% +% Copyright 2024 The MathWorks, Inc. + +value = 30; +result = opentelemetry.metrics.ObservableResult; +result = result.observe(value, dictionary({"Level1"}, {"D"},{"Level2"},{"E"})); \ No newline at end of file diff --git a/test/tformat.m b/test/tformat.m new file mode 100644 index 0000000..f784e6c --- /dev/null +++ b/test/tformat.m @@ -0,0 +1,147 @@ +classdef tformat < matlab.unittest.TestCase + % tests for setting format in the exporter + + % Copyright 2023-2024 The MathWorks, Inc. + + properties + OtelConfigFile + JsonFile + PidFile + OtelcolName + Otelcol + ListPid + ReadPidList + ExtractPid + Sigint + Sigterm + end + + methods (TestClassSetup) + function setupOnce(testCase) + % add the utils folder to the path + utilsfolder = fullfile(fileparts(mfilename('fullpath')), "utils"); + testCase.applyFixture(matlab.unittest.fixtures.PathFixture(utilsfolder)); + commonSetupOnce(testCase); + end + end + + methods (TestMethodSetup) + function setup(testCase) + config = fullfile(fileparts(mfilename("fullpath")), "config", "otelcol_config.yml"); + commonSetup(testCase, config); + end + end + + methods (TestMethodTeardown) + function teardown(testCase) + commonTeardown(testCase); + end + end + + methods (Test) + function testNondefaultFormat(testCase) + % testNondefaultFormat: using an alternative format + + testCase.assumeTrue(logical(exist("opentelemetry.exporters.otlp.OtlpHttpSpanExporter", "class")), ... + "Otlp HTTP exporter must be installed."); + + tracername = "foo"; + spanname = "bar"; + + exp = opentelemetry.exporters.otlp.OtlpHttpSpanExporter(... + "Format", "binary"); + processor = opentelemetry.sdk.trace.SimpleSpanProcessor(exp); + tp = opentelemetry.sdk.trace.TracerProvider(processor); + tr = getTracer(tp, tracername); + sp = startSpan(tr, spanname); + pause(1); + endSpan(sp); + + % perform test comparisons + results = readJsonResults(testCase); + results = results{1}; + + % check span and tracer names + verifyEqual(testCase, string(results.resourceSpans.scopeSpans.spans.name), spanname); + verifyEqual(testCase, string(results.resourceSpans.scopeSpans.scope.name), tracername); + end + + function testNondefaultGrpcFormat(testCase) + % testNondefaultGrpcFormat: using an alternative format + + testCase.assumeTrue(logical(exist("opentelemetry.exporters.otlp.OtlpGrpcSpanExporter", "class")), ... + "Otlp gRPC exporter must be installed."); + + tracername = "foo"; + spanname = "bar"; + + exp = opentelemetry.exporters.otlp.OtlpGrpcSpanExporter(... + "Format", "binary"); + processor = opentelemetry.sdk.trace.SimpleSpanProcessor(exp); + tp = opentelemetry.sdk.trace.TracerProvider(processor); + tr = getTracer(tp, tracername); + sp = startSpan(tr, spanname); + pause(1); + endSpan(sp); + + % perform test comparisons + results = readJsonResults(testCase); + results = results{1}; + + % check span and tracer names + verifyEqual(testCase, string(results.resourceSpans.scopeSpans.spans.name), spanname); + verifyEqual(testCase, string(results.resourceSpans.scopeSpans.scope.name), tracername); + end + + function NondefaultMetricsFormat(testCase) + % testNondefaultMetricsFormat: using an alternative format + testCase.assumeTrue(logical(exist("opentelemetry.exporters.otlp.OtlpHttpMetricExporter", "class")), ... + "Otlp HTTP exporter must be installed."); + + exp = opentelemetry.exporters.otlp.OtlpHttpMetricExporter(... + "Format", "binary"); + reader = opentelemetry.sdk.metrics.PeriodicExportingMetricReader(... + exp, "Interval", seconds(2), "Timeout", seconds(1)); + p = opentelemetry.sdk.metrics.MeterProvider(reader); + mt = p.getMeter("foo"); + ct = mt.createCounter("bar"); + + val = 4; + ct.add(val); + pause(2.5); + + % fetch result + clear p; + results = readJsonResults(testCase); + + % verify counter value + verifyEqual(testCase, results{end}.resourceMetrics.scopeMetrics.metrics.sum.dataPoints.asDouble, val); + end + + function NondefaultGrpcMetricsFormat(testCase) + % testNondefaultGrpcMetricsFormat: using an alternative format + testCase.assumeTrue(logical(exist("opentelemetry.exporters.otlp.OtlpGrpcMetricExporter", "class")), ... + "Otlp gRPC exporter must be installed."); + + exp = opentelemetry.exporters.otlp.OtlpGrpcMetricExporter(... + "Format", "binary"); + reader = opentelemetry.sdk.metrics.PeriodicExportingMetricReader(... + exp, "Interval", seconds(2), "Timeout", seconds(1)); + p = opentelemetry.sdk.metrics.MeterProvider(reader); + mt = p.getMeter("foo"); + ct = mt.createCounter("bar"); + + val = 8; + ct.add(val); + pause(2.5); + + % fetch result + clear p; + results = readJsonResults(testCase); + + % verify counter value + verifyEqual(testCase, results{end}.resourceMetrics.scopeMetrics.metrics.sum.dataPoints.asDouble, val); + end + + end +end \ No newline at end of file diff --git a/test/thttpheaders.m b/test/thttpheaders.m new file mode 100644 index 0000000..cb99502 --- /dev/null +++ b/test/thttpheaders.m @@ -0,0 +1,147 @@ +classdef thttpheaders < matlab.unittest.TestCase + % tests for setting HTTPHeaders in the exporter + + % Copyright 2023-2024 The MathWorks, Inc. + + properties + OtelConfigFile + JsonFile + PidFile + OtelcolName + Otelcol + ListPid + ReadPidList + ExtractPid + Sigint + Sigterm + end + + methods (TestClassSetup) + function setupOnce(testCase) + % add the utils folder to the path + utilsfolder = fullfile(fileparts(mfilename('fullpath')), "utils"); + testCase.applyFixture(matlab.unittest.fixtures.PathFixture(utilsfolder)); + commonSetupOnce(testCase); + end + end + + methods (TestMethodSetup) + function setup(testCase) + config = fullfile(fileparts(mfilename("fullpath")), "config", "otelcol_config.yml"); + commonSetup(testCase, config); + end + end + + methods (TestMethodTeardown) + function teardown(testCase) + commonTeardown(testCase); + end + end + + methods (Test) + function testNondefaultHTTPHeaders(testCase) + % testNondefaultHTTPHeaders: using an alternative HTTPHeaders + + testCase.assumeTrue(logical(exist("opentelemetry.exporters.otlp.OtlpHttpSpanExporter", "class")), ... + "Otlp HTTP exporter must be installed."); + + tracername = "foo"; + spanname = "bar"; + + exp = opentelemetry.exporters.otlp.OtlpHttpSpanExporter(... + "HTTPHeaders", dictionary("new","header")); + processor = opentelemetry.sdk.trace.SimpleSpanProcessor(exp); + tp = opentelemetry.sdk.trace.TracerProvider(processor); + tr = getTracer(tp, tracername); + sp = startSpan(tr, spanname); + pause(1); + endSpan(sp); + + % perform test comparisons + results = readJsonResults(testCase); + results = results{1}; + + % check span and tracer names + verifyEqual(testCase, string(results.resourceSpans.scopeSpans.spans.name), spanname); + verifyEqual(testCase, string(results.resourceSpans.scopeSpans.scope.name), tracername); + end + + function testNondefaultGrpcHTTPHeaders(testCase) + % testNondefaultGrpcHTTPHeaders: using an alternative HTTPHeaders + + testCase.assumeTrue(logical(exist("opentelemetry.exporters.otlp.OtlpGrpcSpanExporter", "class")), ... + "Otlp gRPC exporter must be installed."); + + tracername = "foo"; + spanname = "bar"; + + exp = opentelemetry.exporters.otlp.OtlpGrpcSpanExporter(... + "HTTPHeaders", dictionary("new","header")); + processor = opentelemetry.sdk.trace.SimpleSpanProcessor(exp); + tp = opentelemetry.sdk.trace.TracerProvider(processor); + tr = getTracer(tp, tracername); + sp = startSpan(tr, spanname); + pause(1); + endSpan(sp); + + % perform test comparisons + results = readJsonResults(testCase); + results = results{1}; + + % check span and tracer names + verifyEqual(testCase, string(results.resourceSpans.scopeSpans.spans.name), spanname); + verifyEqual(testCase, string(results.resourceSpans.scopeSpans.scope.name), tracername); + end + + function NondefaultMetricsHTTPHeaders(testCase) + % testNondefaultMetricsHTTPHeaders: using an alternative HTTPHeaders + testCase.assumeTrue(logical(exist("opentelemetry.exporters.otlp.OtlpHttpMetricExporter", "class")), ... + "Otlp HTTP exporter must be installed."); + + exp = opentelemetry.exporters.otlp.OtlpHttpMetricExporter(... + "HTTPHeaders", dictionary("new","header")); + reader = opentelemetry.sdk.metrics.PeriodicExportingMetricReader(... + exp, "Interval", seconds(2), "Timeout", seconds(1)); + p = opentelemetry.sdk.metrics.MeterProvider(reader); + mt = p.getMeter("foo"); + ct = mt.createCounter("bar"); + + val = 4; + ct.add(val); + pause(2.5); + + % fetch result + clear p; + results = readJsonResults(testCase); + + % verify counter value + verifyEqual(testCase, results{end}.resourceMetrics.scopeMetrics.metrics.sum.dataPoints.asDouble, val); + end + + function NondefaultGrpcMetricsHTTPHeaders(testCase) + % testNondefaultGrpcMetricsHTTPHeaders: using an alternative HTTPHeaders + testCase.assumeTrue(logical(exist("opentelemetry.exporters.otlp.OtlpGrpcMetricExporter", "class")), ... + "Otlp gRPC exporter must be installed."); + + exp = opentelemetry.exporters.otlp.OtlpGrpcMetricExporter(... + "HTTPHeaders", dictionary("new","header")); + reader = opentelemetry.sdk.metrics.PeriodicExportingMetricReader(... + exp, "Interval", seconds(2), "Timeout", seconds(1)); + p = opentelemetry.sdk.metrics.MeterProvider(reader); + mt = p.getMeter("foo"); + ct = mt.createCounter("bar"); + + val = 8; + ct.add(val); + pause(2.5); + + % fetch result + clear p; + results = readJsonResults(testCase); + + % verify counter value + verifyEqual(testCase, results{end}.resourceMetrics.scopeMetrics.metrics.sum.dataPoints.asDouble, val); + end + + end +end \ No newline at end of file diff --git a/test/tjsonbytesmapping.m b/test/tjsonbytesmapping.m new file mode 100644 index 0000000..17ebae6 --- /dev/null +++ b/test/tjsonbytesmapping.m @@ -0,0 +1,147 @@ +classdef tjsonbytesmapping < matlab.unittest.TestCase + % tests for setting JsonBytesMapping in the exporter + + % Copyright 2023-2024 The MathWorks, Inc. + + properties + OtelConfigFile + JsonFile + PidFile + OtelcolName + Otelcol + ListPid + ReadPidList + ExtractPid + Sigint + Sigterm + end + + methods (TestClassSetup) + function setupOnce(testCase) + % add the utils folder to the path + utilsfolder = fullfile(fileparts(mfilename('fullpath')), "utils"); + testCase.applyFixture(matlab.unittest.fixtures.PathFixture(utilsfolder)); + commonSetupOnce(testCase); + end + end + + methods (TestMethodSetup) + function setup(testCase) + config = fullfile(fileparts(mfilename("fullpath")), "config", "otelcol_config.yml"); + commonSetup(testCase, config); + end + end + + methods (TestMethodTeardown) + function teardown(testCase) + commonTeardown(testCase); + end + end + + methods (Test) + function testNondefaultJsonBytesMapping(testCase) + % testNondefaultJsonBytesMapping: using an alternative JsonBytesMapping + + testCase.assumeTrue(logical(exist("opentelemetry.exporters.otlp.OtlpHttpSpanExporter", "class")), ... + "Otlp HTTP exporter must be installed."); + + tracername = "foo"; + spanname = "bar"; + + exp = opentelemetry.exporters.otlp.OtlpHttpSpanExporter(... + "JsonBytesMapping", "base64"); + processor = opentelemetry.sdk.trace.SimpleSpanProcessor(exp); + tp = opentelemetry.sdk.trace.TracerProvider(processor); + tr = getTracer(tp, tracername); + sp = startSpan(tr, spanname); + pause(1); + endSpan(sp); + + % perform test comparisons + results = readJsonResults(testCase); + results = results{1}; + + % check span and tracer names + verifyEqual(testCase, string(results.resourceSpans.scopeSpans.spans.name), spanname); + verifyEqual(testCase, string(results.resourceSpans.scopeSpans.scope.name), tracername); + end + + function testNondefaultGrpcJsonBytesMapping(testCase) + % testNondefaultGrpcJsonBytesMapping: using an alternative JsonBytesMapping + + testCase.assumeTrue(logical(exist("opentelemetry.exporters.otlp.OtlpGrpcSpanExporter", "class")), ... + "Otlp gRPC exporter must be installed."); + + tracername = "foo"; + spanname = "bar"; + + exp = opentelemetry.exporters.otlp.OtlpGrpcSpanExporter(... + "JsonBytesMapping", "base64"); + processor = opentelemetry.sdk.trace.SimpleSpanProcessor(exp); + tp = opentelemetry.sdk.trace.TracerProvider(processor); + tr = getTracer(tp, tracername); + sp = startSpan(tr, spanname); + pause(1); + endSpan(sp); + + % perform test comparisons + results = readJsonResults(testCase); + results = results{1}; + + % check span and tracer names + verifyEqual(testCase, string(results.resourceSpans.scopeSpans.spans.name), spanname); + verifyEqual(testCase, string(results.resourceSpans.scopeSpans.scope.name), tracername); + end + + function NondefaultMetricsJsonBytesMapping(testCase) + % testNondefaultMetricsJsonBytesMapping: using an alternative JsonBytesMapping + testCase.assumeTrue(logical(exist("opentelemetry.exporters.otlp.OtlpHttpMetricExporter", "class")), ... + "Otlp HTTP exporter must be installed."); + + exp = opentelemetry.exporters.otlp.OtlpHttpMetricExporter(... + "JsonBytesMapping", "base64"); + reader = opentelemetry.sdk.metrics.PeriodicExportingMetricReader(... + exp, "Interval", seconds(2), "Timeout", seconds(1)); + p = opentelemetry.sdk.metrics.MeterProvider(reader); + mt = p.getMeter("foo"); + ct = mt.createCounter("bar"); + + val = 4; + ct.add(val); + pause(2.5); + + % fetch result + clear p; + results = readJsonResults(testCase); + + % verify counter value + verifyEqual(testCase, results{end}.resourceMetrics.scopeMetrics.metrics.sum.dataPoints.asDouble, val); + end + + function NondefaultGrpcMetricsJsonBytesMapping(testCase) + % testNondefaultGrpcMetricsJsonBytesMapping: using an alternative JsonBytesMapping + testCase.assumeTrue(logical(exist("opentelemetry.exporters.otlp.OtlpGrpcMetricExporter", "class")), ... + "Otlp gRPC exporter must be installed."); + + exp = opentelemetry.exporters.otlp.OtlpGrpcMetricExporter(... + "JsonBytesMapping", "base64"); + reader = opentelemetry.sdk.metrics.PeriodicExportingMetricReader(... + exp, "Interval", seconds(2), "Timeout", seconds(1)); + p = opentelemetry.sdk.metrics.MeterProvider(reader); + mt = p.getMeter("foo"); + ct = mt.createCounter("bar"); + + val = 8; + ct.add(val); + pause(2.5); + + % fetch result + clear p; + results = readJsonResults(testCase); + + % verify counter value + verifyEqual(testCase, results{end}.resourceMetrics.scopeMetrics.metrics.sum.dataPoints.asDouble, val); + end + + end +end \ No newline at end of file diff --git a/test/tlogs_sdk.m b/test/tlogs_sdk.m index eabe95e..858448d 100644 --- a/test/tlogs_sdk.m +++ b/test/tlogs_sdk.m @@ -76,6 +76,32 @@ function testOtlpFileExporter(testCase) verifyEqual(testCase, string(results.resourceLogs.scopeLogs.logRecords.severityText), upper(logseverity)); verifyEqual(testCase, string(results.resourceLogs.scopeLogs.logRecords.body.stringValue), logmessage); end + + function testHttpExporter(testCase) + testCase.assumeTrue(logical(exist("opentelemetry.exporters.otlp.OtlpHttpLogRecordExporter", "class")), ... + "Otlp HTTP Log record exporter must be installed."); + + processor1 = opentelemetry.sdk.logs.SimpleLogRecordProcessor; + + HttpExporter = processor1.LogRecordExporter; + + HttpExporter.Endpoint = "endpoint"; + HttpExporter.Format = "JSON"; + HttpExporter.JsonBytesMapping = "base64"; + HttpExporter.UseJsonName = 1; + HttpExporter.Timeout = seconds(10); + HttpExporter.HttpHeaders = dictionary("new","header"); + + exp = opentelemetry.exporters.otlp.OtlpHttpLogRecordExporter("Endpoint","endpoint","Format","JSON","JsonBytesMapping","base64","UseJsonName",1,"Timeout",seconds(10),"HttpHeaders",dictionary("new","header")); + + % Validate that set methods create a OtlpHttpLogRecordExporter + % with expected properties + HttpExporter = rmfield(struct(HttpExporter),"Proxy"); + exp = rmfield(struct(exp),"Proxy"); + testCase.verifyEqual(HttpExporter,exp); + + + end function testAddLogRecordProcessor(testCase) % testAddLogRecordProcessor: addLogRecordProcessor method diff --git a/test/tmetrics.m b/test/tmetrics.m index 0b11a93..018c074 100644 --- a/test/tmetrics.m +++ b/test/tmetrics.m @@ -747,6 +747,37 @@ function testAsynchronousInstrumentMultipleCallbacks(testCase, create_async, dat verifyEqual(testCase, string(dp(idxC).attributes.value.stringValue), "C"); end + function testAsynchronousInstrumentDictionaryCallback(testCase, create_async, datapoint_name) + % removeCallback method + %callback = @callbackNoAttributes3; + + p = opentelemetry.sdk.metrics.MeterProvider(testCase.ShortIntervalReader); + mt = p.getMeter("foo"); + ct = create_async(mt, @callbackWithAttributes3, "bar", "", "", testCase.CallbackTimeout); + + % wait for collector response + pause(testCase.WaitTime); + + % fetch result + clear p; + results = readJsonResults(testCase); + + % verify counter name + verifyEqual(testCase, string(results{1}.resourceMetrics.scopeMetrics.metrics.name), "bar"); + + % verify counter values and attributes + dp = results{1}.resourceMetrics.scopeMetrics.metrics.(datapoint_name).dataPoints.attributes; + attrvals = arrayfun(@(x)string(x.value.stringValue),dp); + idxD = (attrvals == "D"); + idxE = (attrvals == "E"); + verifyEqual(testCase, results{1}.resourceMetrics.scopeMetrics.metrics.(datapoint_name).dataPoints.asDouble, 30); + verifyEqual(testCase, string(dp(idxD).key), "Level1"); + verifyEqual(testCase, string(dp(idxD).value.stringValue), "D"); + verifyEqual(testCase, string(dp(idxE).key), "Level2"); + verifyEqual(testCase, string(dp(idxE).value.stringValue), "E"); + + end + function testAsynchronousInstrumentRemoveCallback(testCase, create_async) % removeCallback method callback = @callbackNoAttributes; diff --git a/test/tmetrics_sdk.m b/test/tmetrics_sdk.m index 57901c5..49dd084 100644 --- a/test/tmetrics_sdk.m +++ b/test/tmetrics_sdk.m @@ -229,6 +229,55 @@ function testViewBasic(testCase) verifyEqual(testCase, dp.asDouble, val); end + function testViewProperties(testCase) + % testViewProperties: check view object changes the name and + % description of output metrics when schema, version, and units + view_name = "counter_view"; + view_description = "view_description"; + view = opentelemetry.sdk.metrics.View(Name=view_name, .... + Description=view_description, InstrumentType="Counter",MeterSchema="http://schema.org",MeterVersion="1.0.0",InstrumentUnit="ms"); + mp = opentelemetry.sdk.metrics.MeterProvider(... + testCase.ShortIntervalReader, View=view); + + m = getMeter(mp, "mymeter", "1.0.0", "http://schema.org"); + c = createCounter(m, "mycounter","Counter for meter with view properties","ms"); + + m2 = getMeter(mp, "mymeter2", "2.0.0", "http://schema.org"); + c2 = createCounter(m2, "mycounter","Counter for meter with different version","ms"); + + m3 = getMeter(mp, "mymeter3","1.0.0","http://notmyschema.org"); + c3 = createCounter(m3, "mycounter","Counter for meter with different schema","ms"); + + m4 = getMeter(mp, "mymeter4", "1.0.0", "http://schema.org"); + c4 = createCounter(m4, "mycounter","Counter for meter with view properties different units","s"); + + m4 = getMeter(mp, "mymeter5", "1.0.0", "http://schema.org"); + u = createUpDownCounter(m4, "updowncounter","UpDownCounter for meter with view properties","ms"); + + + + % add value and attributes + val = 10; + c.add(val); + c2.add(val); + c3.add(val); + c4.add(val); + u.add(val); + + pause(testCase.WaitTime); + + clear mp; + results = readJsonResults(testCase); + results = results{end}; + + % verify view name only on meter with matching properties + verifyEqual(testCase, string(results.resourceMetrics.scopeMetrics(1).metrics.name), view_name); + verifyNotEqual(testCase, string(results.resourceMetrics.scopeMetrics(2).metrics.name), view_name); + verifyNotEqual(testCase, string(results.resourceMetrics.scopeMetrics(3).metrics.name), view_name); + verifyNotEqual(testCase, string(results.resourceMetrics.scopeMetrics(4).metrics.name), view_name); + verifyNotEqual(testCase, string(results.resourceMetrics.scopeMetrics(5).metrics.name), view_name); + end + function testViewHistogram(testCase) % testViewHistogram: Change histogram bins mp = opentelemetry.sdk.metrics.MeterProvider(testCase.ShortIntervalReader); diff --git a/test/ttimeout.m b/test/ttimeout.m new file mode 100644 index 0000000..02ac242 --- /dev/null +++ b/test/ttimeout.m @@ -0,0 +1,147 @@ +classdef ttimeout < matlab.unittest.TestCase + % tests for setting Timeout in the exporter + + % Copyright 2023-2024 The MathWorks, Inc. + + properties + OtelConfigFile + JsonFile + PidFile + OtelcolName + Otelcol + ListPid + ReadPidList + ExtractPid + Sigint + Sigterm + end + + methods (TestClassSetup) + function setupOnce(testCase) + % add the utils folder to the path + utilsfolder = fullfile(fileparts(mfilename('fullpath')), "utils"); + testCase.applyFixture(matlab.unittest.fixtures.PathFixture(utilsfolder)); + commonSetupOnce(testCase); + end + end + + methods (TestMethodSetup) + function setup(testCase) + config = fullfile(fileparts(mfilename("fullpath")), "config", "otelcol_config.yml"); + commonSetup(testCase, config); + end + end + + methods (TestMethodTeardown) + function teardown(testCase) + commonTeardown(testCase); + end + end + + methods (Test) + function testNondefaultTimeout(testCase) + % testNondefaultTimeout: using an alternative Timeout + + testCase.assumeTrue(logical(exist("opentelemetry.exporters.otlp.OtlpHttpSpanExporter", "class")), ... + "Otlp HTTP exporter must be installed."); + + tracername = "foo"; + spanname = "bar"; + + exp = opentelemetry.exporters.otlp.OtlpHttpSpanExporter(... + "Timeout", seconds(10)); + processor = opentelemetry.sdk.trace.SimpleSpanProcessor(exp); + tp = opentelemetry.sdk.trace.TracerProvider(processor); + tr = getTracer(tp, tracername); + sp = startSpan(tr, spanname); + pause(1); + endSpan(sp); + + % perform test comparisons + results = readJsonResults(testCase); + results = results{1}; + + % check span and tracer names + verifyEqual(testCase, string(results.resourceSpans.scopeSpans.spans.name), spanname); + verifyEqual(testCase, string(results.resourceSpans.scopeSpans.scope.name), tracername); + end + + function testNondefaultGrpcTimeout(testCase) + % testNondefaultGrpcTimeout: using an alternative Timeout + + testCase.assumeTrue(logical(exist("opentelemetry.exporters.otlp.OtlpGrpcSpanExporter", "class")), ... + "Otlp gRPC exporter must be installed."); + + tracername = "foo"; + spanname = "bar"; + + exp = opentelemetry.exporters.otlp.OtlpGrpcSpanExporter(... + "Timeout", seconds(10)); + processor = opentelemetry.sdk.trace.SimpleSpanProcessor(exp); + tp = opentelemetry.sdk.trace.TracerProvider(processor); + tr = getTracer(tp, tracername); + sp = startSpan(tr, spanname); + pause(1); + endSpan(sp); + + % perform test comparisons + results = readJsonResults(testCase); + results = results{1}; + + % check span and tracer names + verifyEqual(testCase, string(results.resourceSpans.scopeSpans.spans.name), spanname); + verifyEqual(testCase, string(results.resourceSpans.scopeSpans.scope.name), tracername); + end + + function NondefaultMetricsTimeout(testCase) + % testNondefaultMetricsTimeout: using an alternative Timeout + testCase.assumeTrue(logical(exist("opentelemetry.exporters.otlp.OtlpHttpMetricExporter", "class")), ... + "Otlp HTTP exporter must be installed."); + + exp = opentelemetry.exporters.otlp.OtlpHttpMetricExporter(... + "Timeout", seconds(10)); + reader = opentelemetry.sdk.metrics.PeriodicExportingMetricReader(... + exp, "Interval", seconds(2), "Timeout", seconds(1)); + p = opentelemetry.sdk.metrics.MeterProvider(reader); + mt = p.getMeter("foo"); + ct = mt.createCounter("bar"); + + val = 4; + ct.add(val); + pause(2.5); + + % fetch result + clear p; + results = readJsonResults(testCase); + + % verify counter value + verifyEqual(testCase, results{end}.resourceMetrics.scopeMetrics.metrics.sum.dataPoints.asDouble, val); + end + + function NondefaultGrpcMetricsTimeout(testCase) + % testNondefaultGrpcMetricsTimeout: using an alternative Timeout + testCase.assumeTrue(logical(exist("opentelemetry.exporters.otlp.OtlpGrpcMetricExporter", "class")), ... + "Otlp gRPC exporter must be installed."); + + exp = opentelemetry.exporters.otlp.OtlpGrpcMetricExporter(... + "Timeout", seconds(10)); + reader = opentelemetry.sdk.metrics.PeriodicExportingMetricReader(... + exp, "Interval", seconds(2), "Timeout", seconds(1)); + p = opentelemetry.sdk.metrics.MeterProvider(reader); + mt = p.getMeter("foo"); + ct = mt.createCounter("bar"); + + val = 8; + ct.add(val); + pause(2.5); + + % fetch result + clear p; + results = readJsonResults(testCase); + + % verify counter value + verifyEqual(testCase, results{end}.resourceMetrics.scopeMetrics.metrics.sum.dataPoints.asDouble, val); + end + + end +end \ No newline at end of file diff --git a/test/ttrace_sdk.m b/test/ttrace_sdk.m index 2634a62..4ee110c 100644 --- a/test/ttrace_sdk.m +++ b/test/ttrace_sdk.m @@ -111,6 +111,54 @@ function testAlwaysOnSampler(testCase) verifyEqual(testCase, string(results.resourceSpans.scopeSpans.scope.name), tracername); end + function testParentBasedSampler(testCase) + % testAlwaysOnSampler: should produce all spans + tracername = "tracer - AlwaysOnSampler"; + spanname = "span - AlwaysOnSampler"; + + tp = opentelemetry.sdk.trace.TracerProvider( ... + "Sampler", opentelemetry.sdk.trace.ParentBasedSampler(opentelemetry.sdk.trace.AlwaysOnSampler)); + tr = getTracer(tp, tracername); + sp = startSpan(tr, spanname); + pause(1); + endSpan(sp); + + tracername1 = "tracer - AlwaysOffSampler"; + spanname1 = "span - AlwaysOffSampler"; + tp = opentelemetry.sdk.trace.TracerProvider( ... + "Sampler", opentelemetry.sdk.trace.ParentBasedSampler(opentelemetry.sdk.trace.AlwaysOffSampler)); + tr = getTracer(tp, tracername1); + sp = startSpan(tr, spanname1); + pause(1); + endSpan(sp); + + tracername2 = "tracer - TraceIdRatioBasedSampler"; + spanname2 = "span - TraceIdRatioBasedSampler"; + tp = opentelemetry.sdk.trace.TracerProvider( ... + "Sampler", opentelemetry.sdk.trace.ParentBasedSampler(opentelemetry.sdk.trace.TraceIdRatioBasedSampler(1))); + tr = getTracer(tp, tracername2); + sp = startSpan(tr, spanname2); + pause(1); + endSpan(sp); + + % perform test comparisons + results = readJsonResults(testCase); + + % check span and tracer names of an AlwaysOnSampler + verifyEqual(testCase, string(results{1}.resourceSpans.scopeSpans.spans.name), spanname); + verifyEqual(testCase, string(results{1}.resourceSpans.scopeSpans.scope.name), tracername); + + % AlwaysOffSampler should return no results + + % check span and tracer names of an TraceIdRatioBasedSampler + verifyEqual(testCase, string(results{2}.resourceSpans.scopeSpans.spans.name), spanname2); + verifyEqual(testCase, string(results{2}.resourceSpans.scopeSpans.scope.name), tracername2); + + % check ParentBasedSampler doesn't accept other inputs + verifyError(testCase, @() opentelemetry.sdk.trace.TracerProvider( ... + "Sampler", opentelemetry.sdk.trace.ParentBasedSampler(opentelemetry.sdk.trace.ParentBasedSampler("not a sampler"))), "MATLAB:validators:mustBeA"); + end + function testTraceIdRatioBasedSampler(testCase) % testTraceIdRatioBasedSampler: filter spans based on a ratio s = opentelemetry.sdk.trace.TraceIdRatioBasedSampler(0); % equivalent to always off diff --git a/test/tusejsonname.m b/test/tusejsonname.m new file mode 100644 index 0000000..015179b --- /dev/null +++ b/test/tusejsonname.m @@ -0,0 +1,147 @@ +classdef tusejsonname < matlab.unittest.TestCase + % tests for setting UseJsonName in the exporter + + % Copyright 2023-2024 The MathWorks, Inc. + + properties + OtelConfigFile + JsonFile + PidFile + OtelcolName + Otelcol + ListPid + ReadPidList + ExtractPid + Sigint + Sigterm + end + + methods (TestClassSetup) + function setupOnce(testCase) + % add the utils folder to the path + utilsfolder = fullfile(fileparts(mfilename('fullpath')), "utils"); + testCase.applyFixture(matlab.unittest.fixtures.PathFixture(utilsfolder)); + commonSetupOnce(testCase); + end + end + + methods (TestMethodSetup) + function setup(testCase) + config = fullfile(fileparts(mfilename("fullpath")), "config", "otelcol_config.yml"); + commonSetup(testCase, config); + end + end + + methods (TestMethodTeardown) + function teardown(testCase) + commonTeardown(testCase); + end + end + + methods (Test) + function testNondefaultUseJsonName(testCase) + % testNondefaultUseJsonName: using an alternative UseJsonName + + testCase.assumeTrue(logical(exist("opentelemetry.exporters.otlp.OtlpHttpSpanExporter", "class")), ... + "Otlp HTTP exporter must be installed."); + + tracername = "foo"; + spanname = "bar"; + + exp = opentelemetry.exporters.otlp.OtlpHttpSpanExporter(... + "UseJsonName", true); + processor = opentelemetry.sdk.trace.SimpleSpanProcessor(exp); + tp = opentelemetry.sdk.trace.TracerProvider(processor); + tr = getTracer(tp, tracername); + sp = startSpan(tr, spanname); + pause(1); + endSpan(sp); + + % perform test comparisons + results = readJsonResults(testCase); + results = results{1}; + + % check span and tracer names + verifyEqual(testCase, string(results.resourceSpans.scopeSpans.spans.name), spanname); + verifyEqual(testCase, string(results.resourceSpans.scopeSpans.scope.name), tracername); + end + + function testNondefaultGrpcUseJsonName(testCase) + % testNondefaultGrpcUseJsonName: using an alternative UseJsonName + + testCase.assumeTrue(logical(exist("opentelemetry.exporters.otlp.OtlpGrpcSpanExporter", "class")), ... + "Otlp gRPC exporter must be installed."); + + tracername = "foo"; + spanname = "bar"; + + exp = opentelemetry.exporters.otlp.OtlpGrpcSpanExporter(... + "UseJsonName", true); + processor = opentelemetry.sdk.trace.SimpleSpanProcessor(exp); + tp = opentelemetry.sdk.trace.TracerProvider(processor); + tr = getTracer(tp, tracername); + sp = startSpan(tr, spanname); + pause(1); + endSpan(sp); + + % perform test comparisons + results = readJsonResults(testCase); + results = results{1}; + + % check span and tracer names + verifyEqual(testCase, string(results.resourceSpans.scopeSpans.spans.name), spanname); + verifyEqual(testCase, string(results.resourceSpans.scopeSpans.scope.name), tracername); + end + + function NondefaultMetricsUseJsonName(testCase) + % testNondefaultMetricsUseJsonName: using an alternative UseJsonName + testCase.assumeTrue(logical(exist("opentelemetry.exporters.otlp.OtlpHttpMetricExporter", "class")), ... + "Otlp HTTP exporter must be installed."); + + exp = opentelemetry.exporters.otlp.OtlpHttpMetricExporter(... + "UseJsonName", true); + reader = opentelemetry.sdk.metrics.PeriodicExportingMetricReader(... + exp, "Interval", seconds(2), "Timeout", seconds(1)); + p = opentelemetry.sdk.metrics.MeterProvider(reader); + mt = p.getMeter("foo"); + ct = mt.createCounter("bar"); + + val = 4; + ct.add(val); + pause(2.5); + + % fetch result + clear p; + results = readJsonResults(testCase); + + % verify counter value + verifyEqual(testCase, results{end}.resourceMetrics.scopeMetrics.metrics.sum.dataPoints.asDouble, val); + end + + function NondefaultGrpcMetricsUseJsonName(testCase) + % testNondefaultGrpcMetricsUseJsonName: using an alternative UseJsonName + testCase.assumeTrue(logical(exist("opentelemetry.exporters.otlp.OtlpGrpcMetricExporter", "class")), ... + "Otlp gRPC exporter must be installed."); + + exp = opentelemetry.exporters.otlp.OtlpGrpcMetricExporter(... + "UseJsonName", true); + reader = opentelemetry.sdk.metrics.PeriodicExportingMetricReader(... + exp, "Interval", seconds(2), "Timeout", seconds(1)); + p = opentelemetry.sdk.metrics.MeterProvider(reader); + mt = p.getMeter("foo"); + ct = mt.createCounter("bar"); + + val = 8; + ct.add(val); + pause(2.5); + + % fetch result + clear p; + results = readJsonResults(testCase); + + % verify counter value + verifyEqual(testCase, results{end}.resourceMetrics.scopeMetrics.metrics.sum.dataPoints.asDouble, val); + end + + end +end \ No newline at end of file From e491073c79a0c28739c3e2dbb3569885d395d7f7 Mon Sep 17 00:00:00 2001 From: Scott Estabrook Date: Thu, 28 Aug 2025 14:34:30 -0400 Subject: [PATCH 11/12] Update testing branch to only contain code coverage changes --- .github/workflows/performance_benchmark.yml | 66 --------------------- test/performance/runPerf.m | 5 -- 2 files changed, 71 deletions(-) delete mode 100644 .github/workflows/performance_benchmark.yml delete mode 100644 test/performance/runPerf.m diff --git a/.github/workflows/performance_benchmark.yml b/.github/workflows/performance_benchmark.yml deleted file mode 100644 index 709481a..0000000 --- a/.github/workflows/performance_benchmark.yml +++ /dev/null @@ -1,66 +0,0 @@ -# Performance benchmarking workflow -name: "Build and Run Benchmark" -on: - workflow_dispatch: - push: - branches-ignore: - - 'main' - - '[0-9]+.[0-9]+.[0-9]+' -env: - MLM_LICENSE_TOKEN: ${{ secrets.MLM_LICENSE_TOKEN }} -jobs: - get_version: - runs-on: ubuntu-20.04 - outputs: - version: ${{ steps.getversion.outputs.latest_tag }} - steps: - # need fetch-depth:0 to also download the tags - - name: Download OpenTelemetry-Matlab source - uses: actions/checkout@v3 - with: - path: opentelemetry-matlab - fetch-depth: 0 - - name: Get Version - id: getversion - shell: bash - working-directory: opentelemetry-matlab - run: echo "latest_tag=$(sed -re 's/^v?([[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+)?.*/\1/' <<< $(git describe --tags --abbrev=0))" >> $GITHUB_OUTPUT - benchmark-ubuntu: - # Running on ubuntu-latest would use a glibc version that is incompatible when using the built mex files on a Debian 11 - # Instead, run on ubuntu-20.04 - runs-on: ubuntu-20.04 - needs: get_version - env: - OPENTELEMETRY_MATLAB_INSTALL: "${{ github.workspace }}/otel_matlab_install" - SYSTEM_LIBSTDCPP_PATH: "/usr/lib/x86_64-linux-gnu/libstdc++.so.6" - steps: - - name: Download OpenTelemetry-Matlab source - uses: actions/checkout@v3 - with: - path: opentelemetry-matlab - - name: Install ninja-build - run: sudo apt-get install ninja-build - - name: Install MATLAB - uses: matlab-actions/setup-matlab@v2 - with: - products: MATLAB_Compiler MATLAB_Compiler_SDK - - name: Build OpenTelemetry-Matlab - working-directory: opentelemetry-matlab - run: | - cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DWITH_EXAMPLES=ON -DUSE_BATCH_FOR_MCC=ON -DOTEL_MATLAB_VERSION=${{ needs.get_version.outputs.version }} -DCMAKE_INSTALL_PREFIX=${{ env.OPENTELEMETRY_MATLAB_INSTALL }} - cmake --build build --config Release --target install - - name: Run Benchmark - uses: matlab-actions/run-command@v2 - with: - command: run("opentelemetry-matlab/test/performance/runperf.m") - - name: Download previous benchmark data - uses: actions/cache@v4 - with: - path: ./cache - key: ${{ runner.os }}-benchmark - - name: Store benchmark result - uses: benchmark-action/github-action-benchmark@v1 - with: - tool: 'customSmallerIsBetter' - output-file-path: ./Benchmarks/OutputBenchmark.json - external-data-json-path: ./cache/OutputBenchmark.json diff --git a/test/performance/runPerf.m b/test/performance/runPerf.m deleted file mode 100644 index 9365721..0000000 --- a/test/performance/runPerf.m +++ /dev/null @@ -1,5 +0,0 @@ -T = runperf(); -u(1:size(T.sampleSummary,1)) = "seconds"; -S = struct("name",cellstr(T.sampleSummary.Name),"unit",cellstr(u'),"value",num2cell(T.sampleSummary.Mean)); -mkdir("Benchmarks"); -writestruct(S,"./Benchmarks/OutputBenchmark.json") \ No newline at end of file From 10183609ec27b0b3e2b9d639557f90747bdaa929 Mon Sep 17 00:00:00 2001 From: Scott Estabrook <124709205+MWSestabro@users.noreply.github.com> Date: Fri, 12 Sep 2025 14:47:45 -0400 Subject: [PATCH 12/12] Update CMakeLists.txt Update CMakeLists to point to new libmexclass version to handle mac errors --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2147f62..cfab06a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -121,7 +121,7 @@ set(LIBMEXCLASS_FETCH_CONTENT_NAME libmexclass) set(LIBMEXCLASS_FETCH_CONTENT_GIT_REPOSITORY "https://github.com/mathworks/libmexclass.git") -set(LIBMEXCLASS_FETCH_CONTENT_GIT_TAG "bc2b9f2") +set(LIBMEXCLASS_FETCH_CONTENT_GIT_TAG "3a3b581") set(LIBMEXCLASS_FETCH_CONTENT_SOURCE_SUBDIR "libmexclass/cpp") @@ -546,3 +546,4 @@ install(FILES ${OPENTELEMETRY_PROXY_RUNTIME_LIBRARIES} DESTINATION ${LIBMEXCLASS if(WITH_EXAMPLES) add_subdirectory(examples) endif() +