From 89df507cb7157a01914dd1c8f88693aa002f44cf Mon Sep 17 00:00:00 2001 From: duncanpo Date: Fri, 28 Jul 2023 16:10:05 -0400 Subject: [PATCH 01/17] Initial submit of metrics --- CMakeLists.txt | 9 +++-- OtelMatlabProxyFactory.cpp | 4 +++ .../+sdk/+metrics/MeterProvider.m | 36 +++++++++++++++++++ .../sdk/metrics/MeterProviderProxy.h | 24 +++++++++++++ sdk/metrics/src/MeterProviderProxy.cpp | 19 ++++++++++ 5 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 sdk/metrics/+opentelemetry/+sdk/+metrics/MeterProvider.m create mode 100644 sdk/metrics/include/opentelemetry-matlab/sdk/metrics/MeterProviderProxy.h create mode 100644 sdk/metrics/src/MeterProviderProxy.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index da4e649..bf853b6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -74,8 +74,9 @@ set(TRACE_API_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/api/trace/include) set(CONTEXT_API_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/api/context/include) set(BAGGAGE_API_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/api/baggage/include) set(TRACE_SDK_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/sdk/trace/include) +set(METRICS_SDK_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/sdk/metrics/include) set(OTLP_EXPORTER_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/exporters/otlp/include) -set(OPENTELEMETRY_PROXY_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} ${TRACE_API_INCLUDE_DIR} ${CONTEXT_API_INCLUDE_DIR} ${BAGGAGE_API_INCLUDE_DIR} ${TRACE_SDK_INCLUDE_DIR} ${OTLP_EXPORTER_INCLUDE_DIR} ${OPENTELEMETRY_CPP_INCLUDE_DIRS}) +set(OPENTELEMETRY_PROXY_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} ${TRACE_API_INCLUDE_DIR} ${CONTEXT_API_INCLUDE_DIR} ${BAGGAGE_API_INCLUDE_DIR} ${TRACE_SDK_INCLUDE_DIR} ${METRICS_SDK_INCLUDE_DIR} ${OTLP_EXPORTER_INCLUDE_DIR} ${OPENTELEMETRY_CPP_INCLUDE_DIRS}) set(OPENTELEMETRY_PROXY_FACTORY_CLASS_NAME OtelMatlabProxyFactory) set(OPENTELEMETRY_PROXY_FACTORY_SOURCES_DIR ${CMAKE_CURRENT_SOURCE_DIR}) @@ -83,6 +84,7 @@ set(TRACE_API_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/api/trace/src) set(CONTEXT_API_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/api/context/src) set(BAGGAGE_API_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/api/baggage/src) set(TRACE_SDK_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/sdk/trace/src) +set(METRICS_SDK_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/sdk/metrics/src) set(OTLP_EXPORTER_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/exporters/otlp/src) set(OPENTELEMETRY_PROXY_SOURCES ${OPENTELEMETRY_PROXY_FACTORY_SOURCES_DIR}/${OPENTELEMETRY_PROXY_FACTORY_CLASS_NAME}.cpp @@ -99,7 +101,8 @@ set(OPENTELEMETRY_PROXY_SOURCES ${TRACE_SDK_SOURCE_DIR}/TracerProviderProxy.cpp ${TRACE_SDK_SOURCE_DIR}/SimpleSpanProcessorProxy.cpp ${TRACE_SDK_SOURCE_DIR}/BatchSpanProcessorProxy.cpp - ${TRACE_SDK_SOURCE_DIR}/ParentBasedSamplerProxy.cpp) + ${TRACE_SDK_SOURCE_DIR}/ParentBasedSamplerProxy.cpp + ${METRICS_SDK_SOURCE_DIR}/MeterProviderProxy.cpp) if(WITH_OTLP_HTTP) set(OPENTELEMETRY_PROXY_SOURCES ${OPENTELEMETRY_PROXY_SOURCES} ${OTLP_EXPORTER_SOURCE_DIR}/OtlpHttpSpanExporterProxy.cpp) @@ -217,6 +220,7 @@ set(CONTEXT_API_MATLAB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/api/context/+opentele set(BAGGAGE_API_MATLAB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/api/baggage/+opentelemetry) set(UTILS_API_MATLAB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/api/utils/+opentelemetry) set(TRACE_SDK_MATLAB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/sdk/trace/+opentelemetry) +set(METRICS_SDK_MATLAB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/sdk/metrics/+opentelemetry) set(DEFAULT_EXPORTER_MATLAB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/exporters/otlp/+opentelemetry/+exporters/+otlp/defaultSpanExporter.m) set(OTLP_HTTP_EXPORTER_MATLAB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpHttpSpanExporter.m) set(OTLP_GRPC_EXPORTER_MATLAB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpGrpcSpanExporter.m) @@ -228,6 +232,7 @@ install(DIRECTORY ${CONTEXT_API_MATLAB_SOURCES} DESTINATION .) install(DIRECTORY ${BAGGAGE_API_MATLAB_SOURCES} DESTINATION .) install(DIRECTORY ${UTILS_API_MATLAB_SOURCES} DESTINATION .) install(DIRECTORY ${TRACE_SDK_MATLAB_SOURCES} DESTINATION .) +install(DIRECTORY ${METRICS_SDK_MATLAB_SOURCES} DESTINATION .) install(FILES ${DEFAULT_EXPORTER_MATLAB_SOURCES} DESTINATION ${OTLP_EXPORTERS_DIR}) if(WITH_OTLP_HTTP) install(FILES ${OTLP_HTTP_EXPORTER_MATLAB_SOURCES} DESTINATION ${OTLP_EXPORTERS_DIR}) diff --git a/OtelMatlabProxyFactory.cpp b/OtelMatlabProxyFactory.cpp index a2f1315..925094d 100644 --- a/OtelMatlabProxyFactory.cpp +++ b/OtelMatlabProxyFactory.cpp @@ -22,6 +22,7 @@ #include "opentelemetry-matlab/sdk/trace/AlwaysOffSamplerProxy.h" #include "opentelemetry-matlab/sdk/trace/TraceIdRatioBasedSamplerProxy.h" #include "opentelemetry-matlab/sdk/trace/ParentBasedSamplerProxy.h" +#include "opentelemetry-matlab/sdk/metrics/MeterProviderProxy.h" #ifdef WITH_OTLP_HTTP #include "opentelemetry-matlab/exporters/otlp/OtlpHttpSpanExporterProxy.h" #endif @@ -54,6 +55,9 @@ OtelMatlabProxyFactory::make_proxy(const libmexclass::proxy::ClassName& class_na REGISTER_PROXY(libmexclass.opentelemetry.sdk.AlwaysOffSamplerProxy, libmexclass::opentelemetry::sdk::AlwaysOffSamplerProxy); REGISTER_PROXY(libmexclass.opentelemetry.sdk.TraceIdRatioBasedSamplerProxy, libmexclass::opentelemetry::sdk::TraceIdRatioBasedSamplerProxy); REGISTER_PROXY(libmexclass.opentelemetry.sdk.ParentBasedSamplerProxy, libmexclass::opentelemetry::sdk::ParentBasedSamplerProxy); + + REGISTER_PROXY(libmexclass.opentelemetry.sdk.MeterProviderProxy, libmexclass::opentelemetry::sdk::MeterProviderProxy); + #ifdef WITH_OTLP_HTTP REGISTER_PROXY(libmexclass.opentelemetry.exporters.OtlpHttpSpanExporterProxy, libmexclass::opentelemetry::exporters::OtlpHttpSpanExporterProxy); #endif diff --git a/sdk/metrics/+opentelemetry/+sdk/+metrics/MeterProvider.m b/sdk/metrics/+opentelemetry/+sdk/+metrics/MeterProvider.m new file mode 100644 index 0000000..e475131 --- /dev/null +++ b/sdk/metrics/+opentelemetry/+sdk/+metrics/MeterProvider.m @@ -0,0 +1,36 @@ +classdef MeterProvider < handle + % An SDK implementation of meter provider, which stores a set of configurations used + % in a metrics system. + + % Copyright 2023 The MathWorks, Inc. + + properties (Access=private) + Proxy + end + + methods + function obj = MeterProvider() + % SDK implementation of tracer provider + % MP = OPENTELEMETRY.SDK.METRICS.METERPROVIDER creates a meter + % provider that uses a periodic exporting metric reader and default configurations. + % + % MP = OPENTELEMETRY.SDK.METRICS.METERPROVIDER(R) uses metric + % reader R. Currently, the only supported metric reader is the periodic + % exporting metric reader. + % + % TP = OPENTELEMETRY.SDK.METRICS.METERPROVIDER(R, PARAM1, VALUE1, + % PARAM2, VALUE2, ...) specifies optional parameter name/value pairs. + % Parameters are: + % "View" - View object used to customize collected metrics. + % "Resource" - Additional resource attributes. + % Specified as a dictionary. + % + % See also OPENTELEMETRY.SDK.METRICS.PERIODICEXPORTINGMETRICREADER + % OPENTELEMETRY.SDK.METRICS.VIEW + + obj.Proxy = libmexclass.proxy.Proxy("Name", ... + "libmexclass.opentelemetry.sdk.MeterProviderProxy", ... + "ConstructorArguments", {}); + end + end +end diff --git a/sdk/metrics/include/opentelemetry-matlab/sdk/metrics/MeterProviderProxy.h b/sdk/metrics/include/opentelemetry-matlab/sdk/metrics/MeterProviderProxy.h new file mode 100644 index 0000000..af34198 --- /dev/null +++ b/sdk/metrics/include/opentelemetry-matlab/sdk/metrics/MeterProviderProxy.h @@ -0,0 +1,24 @@ +// Copyright 2023 The MathWorks, Inc. + +#pragma once + +#include "libmexclass/proxy/Proxy.h" +#include "libmexclass/proxy/method/Context.h" + +#include "opentelemetry/metrics/meter_provider.h" + +namespace metrics_api = opentelemetry::metrics; +namespace nostd = opentelemetry::nostd; + +namespace libmexclass::opentelemetry::sdk { +class MeterProviderProxy : public libmexclass::proxy::Proxy { + public: + MeterProviderProxy(nostd::shared_ptr mp) : CppMeterProvider(mp) { + } + + static libmexclass::proxy::MakeResult make(const libmexclass::proxy::FunctionArguments& constructor_arguments); + + protected: + nostd::shared_ptr CppMeterProvider; +}; +} // namespace libmexclass::opentelemetry diff --git a/sdk/metrics/src/MeterProviderProxy.cpp b/sdk/metrics/src/MeterProviderProxy.cpp new file mode 100644 index 0000000..d2f8f55 --- /dev/null +++ b/sdk/metrics/src/MeterProviderProxy.cpp @@ -0,0 +1,19 @@ +// Copyright 2023 The MathWorks, Inc. + +#include "opentelemetry-matlab/sdk/metrics/MeterProviderProxy.h" + +#include "libmexclass/proxy/ProxyManager.h" + +#include "opentelemetry/sdk/metrics/meter_provider_factory.h" + +namespace metrics_sdk = opentelemetry::sdk::metrics; + +namespace libmexclass::opentelemetry::sdk { +libmexclass::proxy::MakeResult MeterProviderProxy::make(const libmexclass::proxy::FunctionArguments& constructor_arguments) { + libmexclass::proxy::MakeResult out; + out = std::make_shared(nostd::shared_ptr( + std::move(metrics_sdk::MeterProviderFactory::Create()))); + return out; +} + +} // namespace libmexclass::opentelemetry From 9533d736ca6ae9a4e82f0d93f47be2f3bfbaeb21 Mon Sep 17 00:00:00 2001 From: duncanpo Date: Fri, 28 Jul 2023 23:39:55 -0400 Subject: [PATCH 02/17] Update build.yml to use latest version of opentelemetry-cpp --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 310c7d5..a06f075 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -20,7 +20,7 @@ jobs: with: repository: open-telemetry/opentelemetry-cpp path: opentelemetry-cpp - ref: v1.9.0 + ref: v1.10.0 - name: Download vcpkg uses: actions/checkout@v3 with: From c1cc7d1930cd6a9ec9c7aab452f6a746af3e12a9 Mon Sep 17 00:00:00 2001 From: duncanpo Date: Sun, 30 Jul 2023 09:01:57 -0400 Subject: [PATCH 03/17] Update build.yml to use latest version of opentelemetry-cpp --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a06f075..68b8c09 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -41,7 +41,7 @@ jobs: - name: Build OpenTelemetry-cpp run: | cd opentelemetry-cpp - cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_CXX_STANDARD=20 -DWITH_OTLP=ON -DWITH_OTLP_HTTP=ON -DWITH_OTLP_GRPC=OFF -DBUILD_TESTING=OFF -DWITH_BENCHMARK=OFF -DOPENTELEMETRY_INSTALL=ON -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake + cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_CXX_STANDARD=20 -DWITH_OTLP_HTTP=ON -DWITH_OTLP_GRPC=OFF -DBUILD_TESTING=OFF -DWITH_BENCHMARK=OFF -DOPENTELEMETRY_INSTALL=ON -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake cmake --build build --config Release --target all cmake --install build --prefix ${{ env.OPENTELEMETRY_CPP_INSTALL }} - name: Build OpenTelemetry-Matlab From cc208df35e77d7d06492d31e67c68bd35779f3e4 Mon Sep 17 00:00:00 2001 From: Rick Tu Date: Fri, 11 Aug 2023 10:18:46 -0400 Subject: [PATCH 04/17] doubleCounter 1. meterProvider->cgetMeter 2. meter->createDoubleCounter 3. counter->add --- CMakeLists.txt | 8 ++- api/metrics/+opentelemetry/+metrics/Counter.m | 40 +++++++++++++++ api/metrics/+opentelemetry/+metrics/Meter.m | 50 ++++++++++++++++++ .../metrics/CounterProxy.h | 32 ++++++++++++ .../opentelemetry-matlab/metrics/MeterProxy.h | 26 ++++++++++ api/metrics/src/CounterProxy.cpp | 25 +++++++++ api/metrics/src/MeterProxy.cpp | 35 +++++++++++++ .../+sdk/+metrics/MeterProvider.m | 20 ++++++++ .../sdk/metrics/MeterProviderProxy.h | 28 ++++++++++ sdk/metrics/src/MeterProviderProxy.cpp | 51 +++++++++++++++++-- 10 files changed, 309 insertions(+), 6 deletions(-) create mode 100644 api/metrics/+opentelemetry/+metrics/Counter.m create mode 100644 api/metrics/+opentelemetry/+metrics/Meter.m create mode 100644 api/metrics/include/opentelemetry-matlab/metrics/CounterProxy.h create mode 100644 api/metrics/include/opentelemetry-matlab/metrics/MeterProxy.h create mode 100644 api/metrics/src/CounterProxy.cpp create mode 100644 api/metrics/src/MeterProxy.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index bf853b6..461228d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,16 +71,18 @@ if(WITH_OTLP_GRPC) endif() set(TRACE_API_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/api/trace/include) +set(METRICS_API_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/api/metrics/include) set(CONTEXT_API_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/api/context/include) set(BAGGAGE_API_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/api/baggage/include) set(TRACE_SDK_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/sdk/trace/include) set(METRICS_SDK_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/sdk/metrics/include) set(OTLP_EXPORTER_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/exporters/otlp/include) -set(OPENTELEMETRY_PROXY_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} ${TRACE_API_INCLUDE_DIR} ${CONTEXT_API_INCLUDE_DIR} ${BAGGAGE_API_INCLUDE_DIR} ${TRACE_SDK_INCLUDE_DIR} ${METRICS_SDK_INCLUDE_DIR} ${OTLP_EXPORTER_INCLUDE_DIR} ${OPENTELEMETRY_CPP_INCLUDE_DIRS}) +set(OPENTELEMETRY_PROXY_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} ${TRACE_API_INCLUDE_DIR} ${METRICS_API_INCLUDE_DIR} ${CONTEXT_API_INCLUDE_DIR} ${BAGGAGE_API_INCLUDE_DIR} ${TRACE_SDK_INCLUDE_DIR} ${METRICS_SDK_INCLUDE_DIR} ${OTLP_EXPORTER_INCLUDE_DIR} ${OPENTELEMETRY_CPP_INCLUDE_DIRS}) set(OPENTELEMETRY_PROXY_FACTORY_CLASS_NAME OtelMatlabProxyFactory) set(OPENTELEMETRY_PROXY_FACTORY_SOURCES_DIR ${CMAKE_CURRENT_SOURCE_DIR}) set(TRACE_API_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/api/trace/src) +set(METRICS_API_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/api/metrics/src) set(CONTEXT_API_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/api/context/src) set(BAGGAGE_API_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/api/baggage/src) set(TRACE_SDK_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/sdk/trace/src) @@ -93,6 +95,8 @@ set(OPENTELEMETRY_PROXY_SOURCES ${TRACE_API_SOURCE_DIR}/SpanProxy.cpp ${TRACE_API_SOURCE_DIR}/SpanContextProxy.cpp ${TRACE_API_SOURCE_DIR}/attribute.cpp + ${METRICS_API_SOURCE_DIR}/MeterProxy.cpp + ${METRICS_API_SOURCE_DIR}/CounterProxy.cpp ${CONTEXT_API_SOURCE_DIR}/TextMapPropagatorProxy.cpp ${CONTEXT_API_SOURCE_DIR}/CompositePropagatorProxy.cpp ${CONTEXT_API_SOURCE_DIR}/TextMapCarrierProxy.cpp @@ -216,6 +220,7 @@ libmexclass_client_install( # Install M files set(TRACE_API_MATLAB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/api/trace/+opentelemetry) +set(METRICS_API_MATLAB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/api/metrics/+opentelemetry) set(CONTEXT_API_MATLAB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/api/context/+opentelemetry) set(BAGGAGE_API_MATLAB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/api/baggage/+opentelemetry) set(UTILS_API_MATLAB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/api/utils/+opentelemetry) @@ -228,6 +233,7 @@ set(OTLP_GRPC_EXPORTER_MATLAB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/exporters/otlp set(OTLP_EXPORTERS_DIR +opentelemetry/+exporters/+otlp) install(DIRECTORY ${TRACE_API_MATLAB_SOURCES} DESTINATION .) +install(DIRECTORY ${METRICS_API_MATLAB_SOURCES} DESTINATION .) install(DIRECTORY ${CONTEXT_API_MATLAB_SOURCES} DESTINATION .) install(DIRECTORY ${BAGGAGE_API_MATLAB_SOURCES} DESTINATION .) install(DIRECTORY ${UTILS_API_MATLAB_SOURCES} DESTINATION .) diff --git a/api/metrics/+opentelemetry/+metrics/Counter.m b/api/metrics/+opentelemetry/+metrics/Counter.m new file mode 100644 index 0000000..f96d4b4 --- /dev/null +++ b/api/metrics/+opentelemetry/+metrics/Counter.m @@ -0,0 +1,40 @@ +classdef Counter < handle + + + % Copyright 2023 The MathWorks, Inc. + + properties (SetAccess=immutable) + Name (1,1) string + Description (1,1) string + Unit (1,1) string + end + + properties (Access=private) + Proxy % Proxy object to interface C++ code + end + + methods (Access={?opentelemetry.metrics.Meter}) + + function obj = Counter(proxy, ctname, ctdescription, ctunit) + % Private constructor. Use getCounter method of Meter + % to create Counters. + obj.Proxy = proxy; + obj.Name = ctname; + obj.Description = ctdescription; + obj.Unit = ctunit; + end + + end + + methods + + function add(obj, value) + if isnumeric(value) && isscalar(value) + obj.Proxy.add(value); + end + end + + end + + +end diff --git a/api/metrics/+opentelemetry/+metrics/Meter.m b/api/metrics/+opentelemetry/+metrics/Meter.m new file mode 100644 index 0000000..e84e172 --- /dev/null +++ b/api/metrics/+opentelemetry/+metrics/Meter.m @@ -0,0 +1,50 @@ +classdef Meter < handle + % A Meter that is used to create spans. + + % Copyright 2023 The MathWorks, Inc. + + properties (SetAccess=immutable) + Name (1,1) string % Meter name + Version (1,1) string % Meter version + Schema (1,1) string % URL that documents the schema of the generated spans + end + + properties (Access=private) + Proxy % Proxy object to interface C++ code + end + + methods (Access={?opentelemetry.sdk.metrics.MeterProvider}) + + function obj = Meter(proxy, mtname, mtversion, mtschema) + % Private constructor. Use getMeter method of MeterProvider + % to create Meters. + obj.Proxy = proxy; + obj.Name = mtname; + obj.Version = mtversion; + obj.Schema = mtschema; + end + + end + + methods + + function counter = createCounter(obj, ctname, ctdescription, ctunit) + arguments + obj + ctname + ctdescription = "" + ctunit = "" + end + import opentelemetry.utils.mustBeScalarString + ctname = mustBeScalarString(ctname); + ctdescription = mustBeScalarString(ctdescription); + ctunit = mustBeScalarString(ctunit); + id = obj.Proxy.createCounter(ctname, ctdescription, ctunit); + Counterproxy = libmexclass.proxy.Proxy("Name", ... + "libmexclass.opentelemetry.CounterProxy", "ID", id); + counter = opentelemetry.metrics.Counter(Counterproxy, ctname, ctdescription, ctunit); + end + + end + +end diff --git a/api/metrics/include/opentelemetry-matlab/metrics/CounterProxy.h b/api/metrics/include/opentelemetry-matlab/metrics/CounterProxy.h new file mode 100644 index 0000000..ec0277b --- /dev/null +++ b/api/metrics/include/opentelemetry-matlab/metrics/CounterProxy.h @@ -0,0 +1,32 @@ +// Copyright 2023 The MathWorks, Inc. + +#pragma once + +#include "libmexclass/proxy/Proxy.h" +#include "libmexclass/proxy/method/Context.h" + +#include "opentelemetry/metrics/meter.h" +#include "opentelemetry/metrics/sync_instruments.h" + + +namespace metrics_api = opentelemetry::metrics; +namespace nostd = opentelemetry::nostd; + +namespace libmexclass::opentelemetry { +class CounterProxy : public libmexclass::proxy::Proxy { + public: + CounterProxy(nostd::shared_ptr > counter) { + CppCounter = std::move(counter); + REGISTER_METHOD(CounterProxy, add); + } + + void add(libmexclass::proxy::method::Context& context); + + private: + + nostd::shared_ptr > CppCounter; + +}; +} // namespace libmexclass::opentelemetry + + diff --git a/api/metrics/include/opentelemetry-matlab/metrics/MeterProxy.h b/api/metrics/include/opentelemetry-matlab/metrics/MeterProxy.h new file mode 100644 index 0000000..72d79d6 --- /dev/null +++ b/api/metrics/include/opentelemetry-matlab/metrics/MeterProxy.h @@ -0,0 +1,26 @@ +// Copyright 2023 The MathWorks, Inc. + +#pragma once + +#include "libmexclass/proxy/Proxy.h" +#include "libmexclass/proxy/method/Context.h" + +#include "opentelemetry/metrics/meter.h" + +namespace metrics_api = opentelemetry::metrics; +namespace nostd = opentelemetry::nostd; + +namespace libmexclass::opentelemetry { +class MeterProxy : public libmexclass::proxy::Proxy { + public: + MeterProxy(nostd::shared_ptr mt) : CppMeter(mt) { + REGISTER_METHOD(MeterProxy, createCounter); + } + + void createCounter(libmexclass::proxy::method::Context& context); + + private: + + nostd::shared_ptr CppMeter; +}; +} // namespace libmexclass::opentelemetry diff --git a/api/metrics/src/CounterProxy.cpp b/api/metrics/src/CounterProxy.cpp new file mode 100644 index 0000000..99a09b9 --- /dev/null +++ b/api/metrics/src/CounterProxy.cpp @@ -0,0 +1,25 @@ +// Copyright 2023 The MathWorks, Inc. + +#include "opentelemetry-matlab/metrics/CounterProxy.h" + +#include "libmexclass/proxy/ProxyManager.h" + + +#include "MatlabDataArray.hpp" + +#include + +namespace libmexclass::opentelemetry { + + +void CounterProxy::add(libmexclass::proxy::method::Context& context){ + + matlab::data::Array value_mda = context.inputs[0]; + double value = static_cast(value_mda[0]); + CppCounter->Add(value); + +} + + + +} // namespace libmexclass::opentelemetry diff --git a/api/metrics/src/MeterProxy.cpp b/api/metrics/src/MeterProxy.cpp new file mode 100644 index 0000000..07c574e --- /dev/null +++ b/api/metrics/src/MeterProxy.cpp @@ -0,0 +1,35 @@ +// Copyright 2023 The MathWorks, Inc. + +#include "opentelemetry-matlab/metrics/MeterProxy.h" +#include "opentelemetry-matlab/metrics/CounterProxy.h" +#include "libmexclass/proxy/ProxyManager.h" + +#include "MatlabDataArray.hpp" + +#include + +namespace libmexclass::opentelemetry { +void MeterProxy::createCounter(libmexclass::proxy::method::Context& context) { + // Always assumes 3 inputs + matlab::data::StringArray name_mda = context.inputs[0]; + std::string name = static_cast(name_mda[0]); + matlab::data::StringArray description_mda = context.inputs[1]; + std::string description= static_cast(description_mda[0]); + matlab::data::StringArray unit_mda = context.inputs[2]; + std::string unit = static_cast(unit_mda[0]); + + nostd::shared_ptr > ct = std::move(CppMeter->CreateDoubleCounter(name, description, unit)); + + // instantiate a CounterProxy instance + CounterProxy* newproxy = new CounterProxy(ct); + auto proxy = std::shared_ptr(newproxy); + + // obtain a proxy ID + libmexclass::proxy::ID proxyid = libmexclass::proxy::ProxyManager::manageProxy(proxy); + + // return the ID + matlab::data::ArrayFactory factory; + auto proxyid_mda = factory.createScalar(proxyid); + context.outputs[0] = proxyid_mda; +} +} // namespace libmexclass::opentelemetry diff --git a/sdk/metrics/+opentelemetry/+sdk/+metrics/MeterProvider.m b/sdk/metrics/+opentelemetry/+sdk/+metrics/MeterProvider.m index e475131..070b784 100644 --- a/sdk/metrics/+opentelemetry/+sdk/+metrics/MeterProvider.m +++ b/sdk/metrics/+opentelemetry/+sdk/+metrics/MeterProvider.m @@ -32,5 +32,25 @@ "libmexclass.opentelemetry.sdk.MeterProviderProxy", ... "ConstructorArguments", {}); end + + function meter = getMeter(obj, mtname, mtversion, mtschema) + arguments + obj + mtname + mtversion = "" + mtschema = "" + end + % name, version, schema accepts any types that can convert to a + % string + import opentelemetry.utils.mustBeScalarString + mtname = mustBeScalarString(mtname); + mtversion = mustBeScalarString(mtversion); + mtschema = mustBeScalarString(mtschema); + id = obj.Proxy.getMeter(mtname, mtversion, mtschema); + Meterproxy = libmexclass.proxy.Proxy("Name", ... + "libmexclass.opentelemetry.MeterProxy", "ID", id); + meter = opentelemetry.metrics.Meter(Meterproxy, mtname, mtversion, mtschema); + end + end end diff --git a/sdk/metrics/include/opentelemetry-matlab/sdk/metrics/MeterProviderProxy.h b/sdk/metrics/include/opentelemetry-matlab/sdk/metrics/MeterProviderProxy.h index af34198..686bd93 100644 --- a/sdk/metrics/include/opentelemetry-matlab/sdk/metrics/MeterProviderProxy.h +++ b/sdk/metrics/include/opentelemetry-matlab/sdk/metrics/MeterProviderProxy.h @@ -5,19 +5,47 @@ #include "libmexclass/proxy/Proxy.h" #include "libmexclass/proxy/method/Context.h" + +#include "opentelemetry/exporters/otlp/otlp_http_metric_exporter_factory.h" +#include "opentelemetry/exporters/otlp/otlp_http_metric_exporter.h" +#include "opentelemetry/exporters/otlp/otlp_http_metric_exporter_options.h" +#include "opentelemetry/exporters/otlp/otlp_http_exporter.h" +#include "opentelemetry/exporters/otlp/protobuf_include_prefix.h" + +#include "opentelemetry/sdk/common/global_log_handler.h" +#include "opentelemetry/metrics/provider.h" #include "opentelemetry/metrics/meter_provider.h" +#include "opentelemetry/sdk/metrics/aggregation/default_aggregation.h" +#include "opentelemetry/sdk/metrics/aggregation/histogram_aggregation.h" +#include "opentelemetry/sdk/metrics/export/periodic_exporting_metric_reader_factory.h" +#include "opentelemetry/sdk/metrics/meter.h" +#include "opentelemetry/sdk/metrics/meter_provider.h" +#include "opentelemetry/sdk/metrics/meter_provider_factory.h" +#include "opentelemetry/sdk/metrics/push_metric_exporter.h" +#include "opentelemetry/sdk/metrics/view/instrument_selector_factory.h" +#include "opentelemetry/sdk/metrics/view/meter_selector_factory.h" +#include "opentelemetry/sdk/metrics/view/view_factory.h" + +#include "opentelemetry-matlab/metrics/MeterProxy.h" namespace metrics_api = opentelemetry::metrics; namespace nostd = opentelemetry::nostd; +namespace metrics_sdk = opentelemetry::sdk::metrics; +namespace common = opentelemetry::common; +namespace otlpexporter = opentelemetry::exporter::otlp; + namespace libmexclass::opentelemetry::sdk { class MeterProviderProxy : public libmexclass::proxy::Proxy { public: MeterProviderProxy(nostd::shared_ptr mp) : CppMeterProvider(mp) { + REGISTER_METHOD(MeterProviderProxy, getMeter); } static libmexclass::proxy::MakeResult make(const libmexclass::proxy::FunctionArguments& constructor_arguments); + void getMeter(libmexclass::proxy::method::Context& context); + protected: nostd::shared_ptr CppMeterProvider; }; diff --git a/sdk/metrics/src/MeterProviderProxy.cpp b/sdk/metrics/src/MeterProviderProxy.cpp index d2f8f55..64b91c1 100644 --- a/sdk/metrics/src/MeterProviderProxy.cpp +++ b/sdk/metrics/src/MeterProviderProxy.cpp @@ -4,16 +4,57 @@ #include "libmexclass/proxy/ProxyManager.h" -#include "opentelemetry/sdk/metrics/meter_provider_factory.h" - -namespace metrics_sdk = opentelemetry::sdk::metrics; +#include +#include +#include namespace libmexclass::opentelemetry::sdk { libmexclass::proxy::MakeResult MeterProviderProxy::make(const libmexclass::proxy::FunctionArguments& constructor_arguments) { + libmexclass::proxy::MakeResult out; - out = std::make_shared(nostd::shared_ptr( - std::move(metrics_sdk::MeterProviderFactory::Create()))); + + auto exporter = otlpexporter::OtlpHttpMetricExporterFactory::Create(); + // Initialize and set the periodic metrics reader + metrics_sdk::PeriodicExportingMetricReaderOptions options; + options.export_interval_millis = std::chrono::milliseconds(1000); + options.export_timeout_millis = std::chrono::milliseconds(500); + auto reader = metrics_sdk::PeriodicExportingMetricReaderFactory::Create(std::move(exporter), options); + + auto p = metrics_sdk::MeterProviderFactory::Create(); + // auto p = nostd::shared_ptr(std::move(metrics_sdk::MeterProviderFactory::Create())); + auto *p_sdk = static_cast(p.get()); + p_sdk->AddMetricReader(std::move(reader)); + + auto p_out = nostd::shared_ptr(std::move(p)); + + out = std::make_shared(p_out); + return out; } +void MeterProviderProxy::getMeter(libmexclass::proxy::method::Context& context) { + // Always assumes 3 inputs + matlab::data::StringArray name_mda = context.inputs[0]; + std::string name = static_cast(name_mda[0]); + matlab::data::StringArray version_mda = context.inputs[1]; + std::string version = static_cast(version_mda[0]); + matlab::data::StringArray schema_mda = context.inputs[2]; + std::string schema = static_cast(schema_mda[0]); + + auto mt = CppMeterProvider->GetMeter(name, version, schema); + + // instantiate a MeterProxy instance + MeterProxy* newproxy = new MeterProxy(mt); + auto mtproxy = std::shared_ptr(newproxy); + + // obtain a proxy ID + libmexclass::proxy::ID proxyid = libmexclass::proxy::ProxyManager::manageProxy(mtproxy); + + // return the ID + matlab::data::ArrayFactory factory; + auto proxyid_mda = factory.createScalar(proxyid); + context.outputs[0] = proxyid_mda; +} + + } // namespace libmexclass::opentelemetry From b89079bf944398f4f4d030439be4eabd3883e163 Mon Sep 17 00:00:00 2001 From: Rick Tu Date: Fri, 11 Aug 2023 15:22:38 -0400 Subject: [PATCH 05/17] fix: comment and headers incorporate feedback in 8/11 code review. --- api/metrics/+opentelemetry/+metrics/Counter.m | 3 ++- api/metrics/+opentelemetry/+metrics/Meter.m | 3 ++- .../include/opentelemetry-matlab/metrics/CounterProxy.h | 3 +-- .../opentelemetry-matlab/sdk/metrics/MeterProviderProxy.h | 6 +----- sdk/metrics/src/MeterProviderProxy.cpp | 6 ------ 5 files changed, 6 insertions(+), 15 deletions(-) diff --git a/api/metrics/+opentelemetry/+metrics/Counter.m b/api/metrics/+opentelemetry/+metrics/Counter.m index f96d4b4..237d640 100644 --- a/api/metrics/+opentelemetry/+metrics/Counter.m +++ b/api/metrics/+opentelemetry/+metrics/Counter.m @@ -1,5 +1,6 @@ classdef Counter < handle - + % Counter is a value that accumulates over time, + % you can think of this like an odometer on a car; it only ever goes up. % Copyright 2023 The MathWorks, Inc. diff --git a/api/metrics/+opentelemetry/+metrics/Meter.m b/api/metrics/+opentelemetry/+metrics/Meter.m index e84e172..77bb8ca 100644 --- a/api/metrics/+opentelemetry/+metrics/Meter.m +++ b/api/metrics/+opentelemetry/+metrics/Meter.m @@ -1,5 +1,6 @@ classdef Meter < handle - % A Meter that is used to create spans. + % A Meter creates metric instruments, capturing measurements about a service at runtime. + % Meters are created from Meter Providers. % Copyright 2023 The MathWorks, Inc. diff --git a/api/metrics/include/opentelemetry-matlab/metrics/CounterProxy.h b/api/metrics/include/opentelemetry-matlab/metrics/CounterProxy.h index ec0277b..3a1cf95 100644 --- a/api/metrics/include/opentelemetry-matlab/metrics/CounterProxy.h +++ b/api/metrics/include/opentelemetry-matlab/metrics/CounterProxy.h @@ -15,8 +15,7 @@ namespace nostd = opentelemetry::nostd; namespace libmexclass::opentelemetry { class CounterProxy : public libmexclass::proxy::Proxy { public: - CounterProxy(nostd::shared_ptr > counter) { - CppCounter = std::move(counter); + CounterProxy(nostd::shared_ptr > ct) : CppCounter(ct) { REGISTER_METHOD(CounterProxy, add); } diff --git a/sdk/metrics/include/opentelemetry-matlab/sdk/metrics/MeterProviderProxy.h b/sdk/metrics/include/opentelemetry-matlab/sdk/metrics/MeterProviderProxy.h index 686bd93..3526822 100644 --- a/sdk/metrics/include/opentelemetry-matlab/sdk/metrics/MeterProviderProxy.h +++ b/sdk/metrics/include/opentelemetry-matlab/sdk/metrics/MeterProviderProxy.h @@ -10,11 +10,10 @@ #include "opentelemetry/exporters/otlp/otlp_http_metric_exporter.h" #include "opentelemetry/exporters/otlp/otlp_http_metric_exporter_options.h" #include "opentelemetry/exporters/otlp/otlp_http_exporter.h" -#include "opentelemetry/exporters/otlp/protobuf_include_prefix.h" -#include "opentelemetry/sdk/common/global_log_handler.h" #include "opentelemetry/metrics/provider.h" #include "opentelemetry/metrics/meter_provider.h" +#include "opentelemetry/sdk/common/global_log_handler.h" #include "opentelemetry/sdk/metrics/aggregation/default_aggregation.h" #include "opentelemetry/sdk/metrics/aggregation/histogram_aggregation.h" #include "opentelemetry/sdk/metrics/export/periodic_exporting_metric_reader_factory.h" @@ -22,9 +21,6 @@ #include "opentelemetry/sdk/metrics/meter_provider.h" #include "opentelemetry/sdk/metrics/meter_provider_factory.h" #include "opentelemetry/sdk/metrics/push_metric_exporter.h" -#include "opentelemetry/sdk/metrics/view/instrument_selector_factory.h" -#include "opentelemetry/sdk/metrics/view/meter_selector_factory.h" -#include "opentelemetry/sdk/metrics/view/view_factory.h" #include "opentelemetry-matlab/metrics/MeterProxy.h" diff --git a/sdk/metrics/src/MeterProviderProxy.cpp b/sdk/metrics/src/MeterProviderProxy.cpp index 64b91c1..e0eb3c3 100644 --- a/sdk/metrics/src/MeterProviderProxy.cpp +++ b/sdk/metrics/src/MeterProviderProxy.cpp @@ -5,8 +5,6 @@ #include "libmexclass/proxy/ProxyManager.h" #include -#include -#include namespace libmexclass::opentelemetry::sdk { libmexclass::proxy::MakeResult MeterProviderProxy::make(const libmexclass::proxy::FunctionArguments& constructor_arguments) { @@ -16,17 +14,13 @@ libmexclass::proxy::MakeResult MeterProviderProxy::make(const libmexclass::proxy auto exporter = otlpexporter::OtlpHttpMetricExporterFactory::Create(); // Initialize and set the periodic metrics reader metrics_sdk::PeriodicExportingMetricReaderOptions options; - options.export_interval_millis = std::chrono::milliseconds(1000); - options.export_timeout_millis = std::chrono::milliseconds(500); auto reader = metrics_sdk::PeriodicExportingMetricReaderFactory::Create(std::move(exporter), options); auto p = metrics_sdk::MeterProviderFactory::Create(); - // auto p = nostd::shared_ptr(std::move(metrics_sdk::MeterProviderFactory::Create())); auto *p_sdk = static_cast(p.get()); p_sdk->AddMetricReader(std::move(reader)); auto p_out = nostd::shared_ptr(std::move(p)); - out = std::make_shared(p_out); return out; From d37755e94c92d4181087dafd8f07c6de500df6aa Mon Sep 17 00:00:00 2001 From: duncanpo Date: Fri, 28 Jul 2023 16:10:05 -0400 Subject: [PATCH 06/17] Initial submit of metrics --- CMakeLists.txt | 7 +++- OtelMatlabProxyFactory.cpp | 4 +++ .../+sdk/+metrics/MeterProvider.m | 36 +++++++++++++++++++ .../sdk/metrics/MeterProviderProxy.h | 24 +++++++++++++ sdk/metrics/src/MeterProviderProxy.cpp | 19 ++++++++++ 5 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 sdk/metrics/+opentelemetry/+sdk/+metrics/MeterProvider.m create mode 100644 sdk/metrics/include/opentelemetry-matlab/sdk/metrics/MeterProviderProxy.h create mode 100644 sdk/metrics/src/MeterProviderProxy.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 9cd97df..50229ff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -75,9 +75,10 @@ set(CONTEXT_API_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/api/context/include) set(BAGGAGE_API_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/api/baggage/include) set(COMMON_API_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/api/common/include) set(TRACE_SDK_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/sdk/trace/include) +set(METRICS_SDK_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/sdk/metrics/include) set(COMMON_SDK_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/sdk/common/include) set(OTLP_EXPORTER_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/exporters/otlp/include) -set(OPENTELEMETRY_PROXY_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} ${TRACE_API_INCLUDE_DIR} ${CONTEXT_API_INCLUDE_DIR} ${BAGGAGE_API_INCLUDE_DIR} ${COMMON_API_INCLUDE_DIR} ${TRACE_SDK_INCLUDE_DIR} ${COMMON_SDK_INCLUDE_DIR} ${OTLP_EXPORTER_INCLUDE_DIR} ${OPENTELEMETRY_CPP_INCLUDE_DIRS}) +set(OPENTELEMETRY_PROXY_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} ${TRACE_API_INCLUDE_DIR} ${CONTEXT_API_INCLUDE_DIR} ${BAGGAGE_API_INCLUDE_DIR} ${COMMON_API_INCLUDE_DIR} ${TRACE_SDK_INCLUDE_DIR} ${METRICS_SDK_INCLUDE_DIR} ${COMMON_SDK_INCLUDE_DIR} ${OTLP_EXPORTER_INCLUDE_DIR} ${OPENTELEMETRY_CPP_INCLUDE_DIRS}) set(OPENTELEMETRY_PROXY_FACTORY_CLASS_NAME OtelMatlabProxyFactory) set(OPENTELEMETRY_PROXY_FACTORY_SOURCES_DIR ${CMAKE_CURRENT_SOURCE_DIR}) @@ -86,6 +87,7 @@ set(CONTEXT_API_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/api/context/src) set(BAGGAGE_API_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/api/baggage/src) set(COMMON_API_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/api/common/src) set(TRACE_SDK_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/sdk/trace/src) +set(METRICS_SDK_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/sdk/metrics/src) set(COMMON_SDK_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/sdk/common/src) set(OTLP_EXPORTER_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/exporters/otlp/src) set(OPENTELEMETRY_PROXY_SOURCES @@ -104,6 +106,7 @@ set(OPENTELEMETRY_PROXY_SOURCES ${TRACE_SDK_SOURCE_DIR}/SimpleSpanProcessorProxy.cpp ${TRACE_SDK_SOURCE_DIR}/BatchSpanProcessorProxy.cpp ${TRACE_SDK_SOURCE_DIR}/ParentBasedSamplerProxy.cpp + ${METRICS_SDK_SOURCE_DIR}/MeterProviderProxy.cpp ${COMMON_SDK_SOURCE_DIR}/resource.cpp) if(WITH_OTLP_HTTP) set(OPENTELEMETRY_PROXY_SOURCES ${OPENTELEMETRY_PROXY_SOURCES} @@ -222,6 +225,7 @@ set(CONTEXT_API_MATLAB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/api/context/+opentele set(BAGGAGE_API_MATLAB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/api/baggage/+opentelemetry) set(COMMON_API_MATLAB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/api/common/+opentelemetry) set(TRACE_SDK_MATLAB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/sdk/trace/+opentelemetry) +set(METRICS_SDK_MATLAB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/sdk/metrics/+opentelemetry) set(DEFAULT_EXPORTER_MATLAB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/exporters/otlp/+opentelemetry/+exporters/+otlp/defaultSpanExporter.m) set(OTLP_HTTP_EXPORTER_MATLAB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpHttpSpanExporter.m) set(OTLP_GRPC_EXPORTER_MATLAB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpGrpcSpanExporter.m) @@ -233,6 +237,7 @@ install(DIRECTORY ${CONTEXT_API_MATLAB_SOURCES} DESTINATION .) install(DIRECTORY ${BAGGAGE_API_MATLAB_SOURCES} DESTINATION .) install(DIRECTORY ${COMMON_API_MATLAB_SOURCES} DESTINATION .) install(DIRECTORY ${TRACE_SDK_MATLAB_SOURCES} DESTINATION .) +install(DIRECTORY ${METRICS_SDK_MATLAB_SOURCES} DESTINATION .) install(FILES ${DEFAULT_EXPORTER_MATLAB_SOURCES} DESTINATION ${OTLP_EXPORTERS_DIR}) if(WITH_OTLP_HTTP) install(FILES ${OTLP_HTTP_EXPORTER_MATLAB_SOURCES} DESTINATION ${OTLP_EXPORTERS_DIR}) diff --git a/OtelMatlabProxyFactory.cpp b/OtelMatlabProxyFactory.cpp index a2f1315..925094d 100644 --- a/OtelMatlabProxyFactory.cpp +++ b/OtelMatlabProxyFactory.cpp @@ -22,6 +22,7 @@ #include "opentelemetry-matlab/sdk/trace/AlwaysOffSamplerProxy.h" #include "opentelemetry-matlab/sdk/trace/TraceIdRatioBasedSamplerProxy.h" #include "opentelemetry-matlab/sdk/trace/ParentBasedSamplerProxy.h" +#include "opentelemetry-matlab/sdk/metrics/MeterProviderProxy.h" #ifdef WITH_OTLP_HTTP #include "opentelemetry-matlab/exporters/otlp/OtlpHttpSpanExporterProxy.h" #endif @@ -54,6 +55,9 @@ OtelMatlabProxyFactory::make_proxy(const libmexclass::proxy::ClassName& class_na REGISTER_PROXY(libmexclass.opentelemetry.sdk.AlwaysOffSamplerProxy, libmexclass::opentelemetry::sdk::AlwaysOffSamplerProxy); REGISTER_PROXY(libmexclass.opentelemetry.sdk.TraceIdRatioBasedSamplerProxy, libmexclass::opentelemetry::sdk::TraceIdRatioBasedSamplerProxy); REGISTER_PROXY(libmexclass.opentelemetry.sdk.ParentBasedSamplerProxy, libmexclass::opentelemetry::sdk::ParentBasedSamplerProxy); + + REGISTER_PROXY(libmexclass.opentelemetry.sdk.MeterProviderProxy, libmexclass::opentelemetry::sdk::MeterProviderProxy); + #ifdef WITH_OTLP_HTTP REGISTER_PROXY(libmexclass.opentelemetry.exporters.OtlpHttpSpanExporterProxy, libmexclass::opentelemetry::exporters::OtlpHttpSpanExporterProxy); #endif diff --git a/sdk/metrics/+opentelemetry/+sdk/+metrics/MeterProvider.m b/sdk/metrics/+opentelemetry/+sdk/+metrics/MeterProvider.m new file mode 100644 index 0000000..e475131 --- /dev/null +++ b/sdk/metrics/+opentelemetry/+sdk/+metrics/MeterProvider.m @@ -0,0 +1,36 @@ +classdef MeterProvider < handle + % An SDK implementation of meter provider, which stores a set of configurations used + % in a metrics system. + + % Copyright 2023 The MathWorks, Inc. + + properties (Access=private) + Proxy + end + + methods + function obj = MeterProvider() + % SDK implementation of tracer provider + % MP = OPENTELEMETRY.SDK.METRICS.METERPROVIDER creates a meter + % provider that uses a periodic exporting metric reader and default configurations. + % + % MP = OPENTELEMETRY.SDK.METRICS.METERPROVIDER(R) uses metric + % reader R. Currently, the only supported metric reader is the periodic + % exporting metric reader. + % + % TP = OPENTELEMETRY.SDK.METRICS.METERPROVIDER(R, PARAM1, VALUE1, + % PARAM2, VALUE2, ...) specifies optional parameter name/value pairs. + % Parameters are: + % "View" - View object used to customize collected metrics. + % "Resource" - Additional resource attributes. + % Specified as a dictionary. + % + % See also OPENTELEMETRY.SDK.METRICS.PERIODICEXPORTINGMETRICREADER + % OPENTELEMETRY.SDK.METRICS.VIEW + + obj.Proxy = libmexclass.proxy.Proxy("Name", ... + "libmexclass.opentelemetry.sdk.MeterProviderProxy", ... + "ConstructorArguments", {}); + end + end +end diff --git a/sdk/metrics/include/opentelemetry-matlab/sdk/metrics/MeterProviderProxy.h b/sdk/metrics/include/opentelemetry-matlab/sdk/metrics/MeterProviderProxy.h new file mode 100644 index 0000000..af34198 --- /dev/null +++ b/sdk/metrics/include/opentelemetry-matlab/sdk/metrics/MeterProviderProxy.h @@ -0,0 +1,24 @@ +// Copyright 2023 The MathWorks, Inc. + +#pragma once + +#include "libmexclass/proxy/Proxy.h" +#include "libmexclass/proxy/method/Context.h" + +#include "opentelemetry/metrics/meter_provider.h" + +namespace metrics_api = opentelemetry::metrics; +namespace nostd = opentelemetry::nostd; + +namespace libmexclass::opentelemetry::sdk { +class MeterProviderProxy : public libmexclass::proxy::Proxy { + public: + MeterProviderProxy(nostd::shared_ptr mp) : CppMeterProvider(mp) { + } + + static libmexclass::proxy::MakeResult make(const libmexclass::proxy::FunctionArguments& constructor_arguments); + + protected: + nostd::shared_ptr CppMeterProvider; +}; +} // namespace libmexclass::opentelemetry diff --git a/sdk/metrics/src/MeterProviderProxy.cpp b/sdk/metrics/src/MeterProviderProxy.cpp new file mode 100644 index 0000000..d2f8f55 --- /dev/null +++ b/sdk/metrics/src/MeterProviderProxy.cpp @@ -0,0 +1,19 @@ +// Copyright 2023 The MathWorks, Inc. + +#include "opentelemetry-matlab/sdk/metrics/MeterProviderProxy.h" + +#include "libmexclass/proxy/ProxyManager.h" + +#include "opentelemetry/sdk/metrics/meter_provider_factory.h" + +namespace metrics_sdk = opentelemetry::sdk::metrics; + +namespace libmexclass::opentelemetry::sdk { +libmexclass::proxy::MakeResult MeterProviderProxy::make(const libmexclass::proxy::FunctionArguments& constructor_arguments) { + libmexclass::proxy::MakeResult out; + out = std::make_shared(nostd::shared_ptr( + std::move(metrics_sdk::MeterProviderFactory::Create()))); + return out; +} + +} // namespace libmexclass::opentelemetry From 62d036a8fc80f562a4e2effe06499d68eb0fc986 Mon Sep 17 00:00:00 2001 From: duncanpo Date: Fri, 28 Jul 2023 23:39:55 -0400 Subject: [PATCH 07/17] Update build.yml to use latest version of opentelemetry-cpp --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 310c7d5..a06f075 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -20,7 +20,7 @@ jobs: with: repository: open-telemetry/opentelemetry-cpp path: opentelemetry-cpp - ref: v1.9.0 + ref: v1.10.0 - name: Download vcpkg uses: actions/checkout@v3 with: From aa3c642f3c068836b572a1e84f91d34bc367e564 Mon Sep 17 00:00:00 2001 From: duncanpo Date: Sun, 30 Jul 2023 09:01:57 -0400 Subject: [PATCH 08/17] Update build.yml to use latest version of opentelemetry-cpp --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a06f075..68b8c09 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -41,7 +41,7 @@ jobs: - name: Build OpenTelemetry-cpp run: | cd opentelemetry-cpp - cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_CXX_STANDARD=20 -DWITH_OTLP=ON -DWITH_OTLP_HTTP=ON -DWITH_OTLP_GRPC=OFF -DBUILD_TESTING=OFF -DWITH_BENCHMARK=OFF -DOPENTELEMETRY_INSTALL=ON -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake + cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_CXX_STANDARD=20 -DWITH_OTLP_HTTP=ON -DWITH_OTLP_GRPC=OFF -DBUILD_TESTING=OFF -DWITH_BENCHMARK=OFF -DOPENTELEMETRY_INSTALL=ON -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake cmake --build build --config Release --target all cmake --install build --prefix ${{ env.OPENTELEMETRY_CPP_INSTALL }} - name: Build OpenTelemetry-Matlab From 03028088c07ca3e7fc6a109e9530ab1d1ceda955 Mon Sep 17 00:00:00 2001 From: Rick Tu Date: Fri, 11 Aug 2023 10:18:46 -0400 Subject: [PATCH 09/17] doubleCounter 1. meterProvider->cgetMeter 2. meter->createDoubleCounter 3. counter->add --- CMakeLists.txt | 8 ++- api/metrics/+opentelemetry/+metrics/Counter.m | 40 +++++++++++++++ api/metrics/+opentelemetry/+metrics/Meter.m | 50 ++++++++++++++++++ .../metrics/CounterProxy.h | 32 ++++++++++++ .../opentelemetry-matlab/metrics/MeterProxy.h | 26 ++++++++++ api/metrics/src/CounterProxy.cpp | 25 +++++++++ api/metrics/src/MeterProxy.cpp | 35 +++++++++++++ .../+sdk/+metrics/MeterProvider.m | 20 ++++++++ .../sdk/metrics/MeterProviderProxy.h | 28 ++++++++++ sdk/metrics/src/MeterProviderProxy.cpp | 51 +++++++++++++++++-- 10 files changed, 309 insertions(+), 6 deletions(-) create mode 100644 api/metrics/+opentelemetry/+metrics/Counter.m create mode 100644 api/metrics/+opentelemetry/+metrics/Meter.m create mode 100644 api/metrics/include/opentelemetry-matlab/metrics/CounterProxy.h create mode 100644 api/metrics/include/opentelemetry-matlab/metrics/MeterProxy.h create mode 100644 api/metrics/src/CounterProxy.cpp create mode 100644 api/metrics/src/MeterProxy.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 50229ff..5c529b4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,6 +71,7 @@ if(WITH_OTLP_GRPC) endif() set(TRACE_API_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/api/trace/include) +set(METRICS_API_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/api/metrics/include) set(CONTEXT_API_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/api/context/include) set(BAGGAGE_API_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/api/baggage/include) set(COMMON_API_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/api/common/include) @@ -78,11 +79,12 @@ set(TRACE_SDK_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/sdk/trace/include) set(METRICS_SDK_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/sdk/metrics/include) set(COMMON_SDK_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/sdk/common/include) set(OTLP_EXPORTER_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/exporters/otlp/include) -set(OPENTELEMETRY_PROXY_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} ${TRACE_API_INCLUDE_DIR} ${CONTEXT_API_INCLUDE_DIR} ${BAGGAGE_API_INCLUDE_DIR} ${COMMON_API_INCLUDE_DIR} ${TRACE_SDK_INCLUDE_DIR} ${METRICS_SDK_INCLUDE_DIR} ${COMMON_SDK_INCLUDE_DIR} ${OTLP_EXPORTER_INCLUDE_DIR} ${OPENTELEMETRY_CPP_INCLUDE_DIRS}) +set(OPENTELEMETRY_PROXY_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} ${TRACE_API_INCLUDE_DIR} ${METRICS_API_INCLUDE_DIR} ${CONTEXT_API_INCLUDE_DIR} ${BAGGAGE_API_INCLUDE_DIR} ${COMMON_API_INCLUDE_DIR} ${TRACE_SDK_INCLUDE_DIR} ${METRICS_SDK_INCLUDE_DIR} ${COMMON_SDK_INCLUDE_DIR} ${OTLP_EXPORTER_INCLUDE_DIR} ${OPENTELEMETRY_CPP_INCLUDE_DIRS}) set(OPENTELEMETRY_PROXY_FACTORY_CLASS_NAME OtelMatlabProxyFactory) set(OPENTELEMETRY_PROXY_FACTORY_SOURCES_DIR ${CMAKE_CURRENT_SOURCE_DIR}) set(TRACE_API_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/api/trace/src) +set(METRICS_API_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/api/metrics/src) set(CONTEXT_API_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/api/context/src) set(BAGGAGE_API_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/api/baggage/src) set(COMMON_API_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/api/common/src) @@ -97,6 +99,8 @@ set(OPENTELEMETRY_PROXY_SOURCES ${TRACE_API_SOURCE_DIR}/SpanProxy.cpp ${TRACE_API_SOURCE_DIR}/SpanContextProxy.cpp ${COMMON_API_SOURCE_DIR}/attribute.cpp + ${METRICS_API_SOURCE_DIR}/MeterProxy.cpp + ${METRICS_API_SOURCE_DIR}/CounterProxy.cpp ${CONTEXT_API_SOURCE_DIR}/TextMapPropagatorProxy.cpp ${CONTEXT_API_SOURCE_DIR}/CompositePropagatorProxy.cpp ${CONTEXT_API_SOURCE_DIR}/TextMapCarrierProxy.cpp @@ -221,6 +225,7 @@ libmexclass_client_install( # Install M files set(TRACE_API_MATLAB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/api/trace/+opentelemetry) +set(METRICS_API_MATLAB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/api/metrics/+opentelemetry) set(CONTEXT_API_MATLAB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/api/context/+opentelemetry) set(BAGGAGE_API_MATLAB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/api/baggage/+opentelemetry) set(COMMON_API_MATLAB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/api/common/+opentelemetry) @@ -233,6 +238,7 @@ set(OTLP_GRPC_EXPORTER_MATLAB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/exporters/otlp set(OTLP_EXPORTERS_DIR +opentelemetry/+exporters/+otlp) install(DIRECTORY ${TRACE_API_MATLAB_SOURCES} DESTINATION .) +install(DIRECTORY ${METRICS_API_MATLAB_SOURCES} DESTINATION .) install(DIRECTORY ${CONTEXT_API_MATLAB_SOURCES} DESTINATION .) install(DIRECTORY ${BAGGAGE_API_MATLAB_SOURCES} DESTINATION .) install(DIRECTORY ${COMMON_API_MATLAB_SOURCES} DESTINATION .) diff --git a/api/metrics/+opentelemetry/+metrics/Counter.m b/api/metrics/+opentelemetry/+metrics/Counter.m new file mode 100644 index 0000000..f96d4b4 --- /dev/null +++ b/api/metrics/+opentelemetry/+metrics/Counter.m @@ -0,0 +1,40 @@ +classdef Counter < handle + + + % Copyright 2023 The MathWorks, Inc. + + properties (SetAccess=immutable) + Name (1,1) string + Description (1,1) string + Unit (1,1) string + end + + properties (Access=private) + Proxy % Proxy object to interface C++ code + end + + methods (Access={?opentelemetry.metrics.Meter}) + + function obj = Counter(proxy, ctname, ctdescription, ctunit) + % Private constructor. Use getCounter method of Meter + % to create Counters. + obj.Proxy = proxy; + obj.Name = ctname; + obj.Description = ctdescription; + obj.Unit = ctunit; + end + + end + + methods + + function add(obj, value) + if isnumeric(value) && isscalar(value) + obj.Proxy.add(value); + end + end + + end + + +end diff --git a/api/metrics/+opentelemetry/+metrics/Meter.m b/api/metrics/+opentelemetry/+metrics/Meter.m new file mode 100644 index 0000000..e84e172 --- /dev/null +++ b/api/metrics/+opentelemetry/+metrics/Meter.m @@ -0,0 +1,50 @@ +classdef Meter < handle + % A Meter that is used to create spans. + + % Copyright 2023 The MathWorks, Inc. + + properties (SetAccess=immutable) + Name (1,1) string % Meter name + Version (1,1) string % Meter version + Schema (1,1) string % URL that documents the schema of the generated spans + end + + properties (Access=private) + Proxy % Proxy object to interface C++ code + end + + methods (Access={?opentelemetry.sdk.metrics.MeterProvider}) + + function obj = Meter(proxy, mtname, mtversion, mtschema) + % Private constructor. Use getMeter method of MeterProvider + % to create Meters. + obj.Proxy = proxy; + obj.Name = mtname; + obj.Version = mtversion; + obj.Schema = mtschema; + end + + end + + methods + + function counter = createCounter(obj, ctname, ctdescription, ctunit) + arguments + obj + ctname + ctdescription = "" + ctunit = "" + end + import opentelemetry.utils.mustBeScalarString + ctname = mustBeScalarString(ctname); + ctdescription = mustBeScalarString(ctdescription); + ctunit = mustBeScalarString(ctunit); + id = obj.Proxy.createCounter(ctname, ctdescription, ctunit); + Counterproxy = libmexclass.proxy.Proxy("Name", ... + "libmexclass.opentelemetry.CounterProxy", "ID", id); + counter = opentelemetry.metrics.Counter(Counterproxy, ctname, ctdescription, ctunit); + end + + end + +end diff --git a/api/metrics/include/opentelemetry-matlab/metrics/CounterProxy.h b/api/metrics/include/opentelemetry-matlab/metrics/CounterProxy.h new file mode 100644 index 0000000..ec0277b --- /dev/null +++ b/api/metrics/include/opentelemetry-matlab/metrics/CounterProxy.h @@ -0,0 +1,32 @@ +// Copyright 2023 The MathWorks, Inc. + +#pragma once + +#include "libmexclass/proxy/Proxy.h" +#include "libmexclass/proxy/method/Context.h" + +#include "opentelemetry/metrics/meter.h" +#include "opentelemetry/metrics/sync_instruments.h" + + +namespace metrics_api = opentelemetry::metrics; +namespace nostd = opentelemetry::nostd; + +namespace libmexclass::opentelemetry { +class CounterProxy : public libmexclass::proxy::Proxy { + public: + CounterProxy(nostd::shared_ptr > counter) { + CppCounter = std::move(counter); + REGISTER_METHOD(CounterProxy, add); + } + + void add(libmexclass::proxy::method::Context& context); + + private: + + nostd::shared_ptr > CppCounter; + +}; +} // namespace libmexclass::opentelemetry + + diff --git a/api/metrics/include/opentelemetry-matlab/metrics/MeterProxy.h b/api/metrics/include/opentelemetry-matlab/metrics/MeterProxy.h new file mode 100644 index 0000000..72d79d6 --- /dev/null +++ b/api/metrics/include/opentelemetry-matlab/metrics/MeterProxy.h @@ -0,0 +1,26 @@ +// Copyright 2023 The MathWorks, Inc. + +#pragma once + +#include "libmexclass/proxy/Proxy.h" +#include "libmexclass/proxy/method/Context.h" + +#include "opentelemetry/metrics/meter.h" + +namespace metrics_api = opentelemetry::metrics; +namespace nostd = opentelemetry::nostd; + +namespace libmexclass::opentelemetry { +class MeterProxy : public libmexclass::proxy::Proxy { + public: + MeterProxy(nostd::shared_ptr mt) : CppMeter(mt) { + REGISTER_METHOD(MeterProxy, createCounter); + } + + void createCounter(libmexclass::proxy::method::Context& context); + + private: + + nostd::shared_ptr CppMeter; +}; +} // namespace libmexclass::opentelemetry diff --git a/api/metrics/src/CounterProxy.cpp b/api/metrics/src/CounterProxy.cpp new file mode 100644 index 0000000..99a09b9 --- /dev/null +++ b/api/metrics/src/CounterProxy.cpp @@ -0,0 +1,25 @@ +// Copyright 2023 The MathWorks, Inc. + +#include "opentelemetry-matlab/metrics/CounterProxy.h" + +#include "libmexclass/proxy/ProxyManager.h" + + +#include "MatlabDataArray.hpp" + +#include + +namespace libmexclass::opentelemetry { + + +void CounterProxy::add(libmexclass::proxy::method::Context& context){ + + matlab::data::Array value_mda = context.inputs[0]; + double value = static_cast(value_mda[0]); + CppCounter->Add(value); + +} + + + +} // namespace libmexclass::opentelemetry diff --git a/api/metrics/src/MeterProxy.cpp b/api/metrics/src/MeterProxy.cpp new file mode 100644 index 0000000..07c574e --- /dev/null +++ b/api/metrics/src/MeterProxy.cpp @@ -0,0 +1,35 @@ +// Copyright 2023 The MathWorks, Inc. + +#include "opentelemetry-matlab/metrics/MeterProxy.h" +#include "opentelemetry-matlab/metrics/CounterProxy.h" +#include "libmexclass/proxy/ProxyManager.h" + +#include "MatlabDataArray.hpp" + +#include + +namespace libmexclass::opentelemetry { +void MeterProxy::createCounter(libmexclass::proxy::method::Context& context) { + // Always assumes 3 inputs + matlab::data::StringArray name_mda = context.inputs[0]; + std::string name = static_cast(name_mda[0]); + matlab::data::StringArray description_mda = context.inputs[1]; + std::string description= static_cast(description_mda[0]); + matlab::data::StringArray unit_mda = context.inputs[2]; + std::string unit = static_cast(unit_mda[0]); + + nostd::shared_ptr > ct = std::move(CppMeter->CreateDoubleCounter(name, description, unit)); + + // instantiate a CounterProxy instance + CounterProxy* newproxy = new CounterProxy(ct); + auto proxy = std::shared_ptr(newproxy); + + // obtain a proxy ID + libmexclass::proxy::ID proxyid = libmexclass::proxy::ProxyManager::manageProxy(proxy); + + // return the ID + matlab::data::ArrayFactory factory; + auto proxyid_mda = factory.createScalar(proxyid); + context.outputs[0] = proxyid_mda; +} +} // namespace libmexclass::opentelemetry diff --git a/sdk/metrics/+opentelemetry/+sdk/+metrics/MeterProvider.m b/sdk/metrics/+opentelemetry/+sdk/+metrics/MeterProvider.m index e475131..070b784 100644 --- a/sdk/metrics/+opentelemetry/+sdk/+metrics/MeterProvider.m +++ b/sdk/metrics/+opentelemetry/+sdk/+metrics/MeterProvider.m @@ -32,5 +32,25 @@ "libmexclass.opentelemetry.sdk.MeterProviderProxy", ... "ConstructorArguments", {}); end + + function meter = getMeter(obj, mtname, mtversion, mtschema) + arguments + obj + mtname + mtversion = "" + mtschema = "" + end + % name, version, schema accepts any types that can convert to a + % string + import opentelemetry.utils.mustBeScalarString + mtname = mustBeScalarString(mtname); + mtversion = mustBeScalarString(mtversion); + mtschema = mustBeScalarString(mtschema); + id = obj.Proxy.getMeter(mtname, mtversion, mtschema); + Meterproxy = libmexclass.proxy.Proxy("Name", ... + "libmexclass.opentelemetry.MeterProxy", "ID", id); + meter = opentelemetry.metrics.Meter(Meterproxy, mtname, mtversion, mtschema); + end + end end diff --git a/sdk/metrics/include/opentelemetry-matlab/sdk/metrics/MeterProviderProxy.h b/sdk/metrics/include/opentelemetry-matlab/sdk/metrics/MeterProviderProxy.h index af34198..686bd93 100644 --- a/sdk/metrics/include/opentelemetry-matlab/sdk/metrics/MeterProviderProxy.h +++ b/sdk/metrics/include/opentelemetry-matlab/sdk/metrics/MeterProviderProxy.h @@ -5,19 +5,47 @@ #include "libmexclass/proxy/Proxy.h" #include "libmexclass/proxy/method/Context.h" + +#include "opentelemetry/exporters/otlp/otlp_http_metric_exporter_factory.h" +#include "opentelemetry/exporters/otlp/otlp_http_metric_exporter.h" +#include "opentelemetry/exporters/otlp/otlp_http_metric_exporter_options.h" +#include "opentelemetry/exporters/otlp/otlp_http_exporter.h" +#include "opentelemetry/exporters/otlp/protobuf_include_prefix.h" + +#include "opentelemetry/sdk/common/global_log_handler.h" +#include "opentelemetry/metrics/provider.h" #include "opentelemetry/metrics/meter_provider.h" +#include "opentelemetry/sdk/metrics/aggregation/default_aggregation.h" +#include "opentelemetry/sdk/metrics/aggregation/histogram_aggregation.h" +#include "opentelemetry/sdk/metrics/export/periodic_exporting_metric_reader_factory.h" +#include "opentelemetry/sdk/metrics/meter.h" +#include "opentelemetry/sdk/metrics/meter_provider.h" +#include "opentelemetry/sdk/metrics/meter_provider_factory.h" +#include "opentelemetry/sdk/metrics/push_metric_exporter.h" +#include "opentelemetry/sdk/metrics/view/instrument_selector_factory.h" +#include "opentelemetry/sdk/metrics/view/meter_selector_factory.h" +#include "opentelemetry/sdk/metrics/view/view_factory.h" + +#include "opentelemetry-matlab/metrics/MeterProxy.h" namespace metrics_api = opentelemetry::metrics; namespace nostd = opentelemetry::nostd; +namespace metrics_sdk = opentelemetry::sdk::metrics; +namespace common = opentelemetry::common; +namespace otlpexporter = opentelemetry::exporter::otlp; + namespace libmexclass::opentelemetry::sdk { class MeterProviderProxy : public libmexclass::proxy::Proxy { public: MeterProviderProxy(nostd::shared_ptr mp) : CppMeterProvider(mp) { + REGISTER_METHOD(MeterProviderProxy, getMeter); } static libmexclass::proxy::MakeResult make(const libmexclass::proxy::FunctionArguments& constructor_arguments); + void getMeter(libmexclass::proxy::method::Context& context); + protected: nostd::shared_ptr CppMeterProvider; }; diff --git a/sdk/metrics/src/MeterProviderProxy.cpp b/sdk/metrics/src/MeterProviderProxy.cpp index d2f8f55..64b91c1 100644 --- a/sdk/metrics/src/MeterProviderProxy.cpp +++ b/sdk/metrics/src/MeterProviderProxy.cpp @@ -4,16 +4,57 @@ #include "libmexclass/proxy/ProxyManager.h" -#include "opentelemetry/sdk/metrics/meter_provider_factory.h" - -namespace metrics_sdk = opentelemetry::sdk::metrics; +#include +#include +#include namespace libmexclass::opentelemetry::sdk { libmexclass::proxy::MakeResult MeterProviderProxy::make(const libmexclass::proxy::FunctionArguments& constructor_arguments) { + libmexclass::proxy::MakeResult out; - out = std::make_shared(nostd::shared_ptr( - std::move(metrics_sdk::MeterProviderFactory::Create()))); + + auto exporter = otlpexporter::OtlpHttpMetricExporterFactory::Create(); + // Initialize and set the periodic metrics reader + metrics_sdk::PeriodicExportingMetricReaderOptions options; + options.export_interval_millis = std::chrono::milliseconds(1000); + options.export_timeout_millis = std::chrono::milliseconds(500); + auto reader = metrics_sdk::PeriodicExportingMetricReaderFactory::Create(std::move(exporter), options); + + auto p = metrics_sdk::MeterProviderFactory::Create(); + // auto p = nostd::shared_ptr(std::move(metrics_sdk::MeterProviderFactory::Create())); + auto *p_sdk = static_cast(p.get()); + p_sdk->AddMetricReader(std::move(reader)); + + auto p_out = nostd::shared_ptr(std::move(p)); + + out = std::make_shared(p_out); + return out; } +void MeterProviderProxy::getMeter(libmexclass::proxy::method::Context& context) { + // Always assumes 3 inputs + matlab::data::StringArray name_mda = context.inputs[0]; + std::string name = static_cast(name_mda[0]); + matlab::data::StringArray version_mda = context.inputs[1]; + std::string version = static_cast(version_mda[0]); + matlab::data::StringArray schema_mda = context.inputs[2]; + std::string schema = static_cast(schema_mda[0]); + + auto mt = CppMeterProvider->GetMeter(name, version, schema); + + // instantiate a MeterProxy instance + MeterProxy* newproxy = new MeterProxy(mt); + auto mtproxy = std::shared_ptr(newproxy); + + // obtain a proxy ID + libmexclass::proxy::ID proxyid = libmexclass::proxy::ProxyManager::manageProxy(mtproxy); + + // return the ID + matlab::data::ArrayFactory factory; + auto proxyid_mda = factory.createScalar(proxyid); + context.outputs[0] = proxyid_mda; +} + + } // namespace libmexclass::opentelemetry From e90e6a403f92c192cbdf8db577ae132ddec3d160 Mon Sep 17 00:00:00 2001 From: Rick Tu Date: Fri, 11 Aug 2023 15:22:38 -0400 Subject: [PATCH 10/17] fix: comment and headers incorporate feedback in 8/11 code review. --- api/metrics/+opentelemetry/+metrics/Counter.m | 3 ++- api/metrics/+opentelemetry/+metrics/Meter.m | 3 ++- .../include/opentelemetry-matlab/metrics/CounterProxy.h | 3 +-- .../opentelemetry-matlab/sdk/metrics/MeterProviderProxy.h | 6 +----- sdk/metrics/src/MeterProviderProxy.cpp | 6 ------ 5 files changed, 6 insertions(+), 15 deletions(-) diff --git a/api/metrics/+opentelemetry/+metrics/Counter.m b/api/metrics/+opentelemetry/+metrics/Counter.m index f96d4b4..237d640 100644 --- a/api/metrics/+opentelemetry/+metrics/Counter.m +++ b/api/metrics/+opentelemetry/+metrics/Counter.m @@ -1,5 +1,6 @@ classdef Counter < handle - + % Counter is a value that accumulates over time, + % you can think of this like an odometer on a car; it only ever goes up. % Copyright 2023 The MathWorks, Inc. diff --git a/api/metrics/+opentelemetry/+metrics/Meter.m b/api/metrics/+opentelemetry/+metrics/Meter.m index e84e172..77bb8ca 100644 --- a/api/metrics/+opentelemetry/+metrics/Meter.m +++ b/api/metrics/+opentelemetry/+metrics/Meter.m @@ -1,5 +1,6 @@ classdef Meter < handle - % A Meter that is used to create spans. + % A Meter creates metric instruments, capturing measurements about a service at runtime. + % Meters are created from Meter Providers. % Copyright 2023 The MathWorks, Inc. diff --git a/api/metrics/include/opentelemetry-matlab/metrics/CounterProxy.h b/api/metrics/include/opentelemetry-matlab/metrics/CounterProxy.h index ec0277b..3a1cf95 100644 --- a/api/metrics/include/opentelemetry-matlab/metrics/CounterProxy.h +++ b/api/metrics/include/opentelemetry-matlab/metrics/CounterProxy.h @@ -15,8 +15,7 @@ namespace nostd = opentelemetry::nostd; namespace libmexclass::opentelemetry { class CounterProxy : public libmexclass::proxy::Proxy { public: - CounterProxy(nostd::shared_ptr > counter) { - CppCounter = std::move(counter); + CounterProxy(nostd::shared_ptr > ct) : CppCounter(ct) { REGISTER_METHOD(CounterProxy, add); } diff --git a/sdk/metrics/include/opentelemetry-matlab/sdk/metrics/MeterProviderProxy.h b/sdk/metrics/include/opentelemetry-matlab/sdk/metrics/MeterProviderProxy.h index 686bd93..3526822 100644 --- a/sdk/metrics/include/opentelemetry-matlab/sdk/metrics/MeterProviderProxy.h +++ b/sdk/metrics/include/opentelemetry-matlab/sdk/metrics/MeterProviderProxy.h @@ -10,11 +10,10 @@ #include "opentelemetry/exporters/otlp/otlp_http_metric_exporter.h" #include "opentelemetry/exporters/otlp/otlp_http_metric_exporter_options.h" #include "opentelemetry/exporters/otlp/otlp_http_exporter.h" -#include "opentelemetry/exporters/otlp/protobuf_include_prefix.h" -#include "opentelemetry/sdk/common/global_log_handler.h" #include "opentelemetry/metrics/provider.h" #include "opentelemetry/metrics/meter_provider.h" +#include "opentelemetry/sdk/common/global_log_handler.h" #include "opentelemetry/sdk/metrics/aggregation/default_aggregation.h" #include "opentelemetry/sdk/metrics/aggregation/histogram_aggregation.h" #include "opentelemetry/sdk/metrics/export/periodic_exporting_metric_reader_factory.h" @@ -22,9 +21,6 @@ #include "opentelemetry/sdk/metrics/meter_provider.h" #include "opentelemetry/sdk/metrics/meter_provider_factory.h" #include "opentelemetry/sdk/metrics/push_metric_exporter.h" -#include "opentelemetry/sdk/metrics/view/instrument_selector_factory.h" -#include "opentelemetry/sdk/metrics/view/meter_selector_factory.h" -#include "opentelemetry/sdk/metrics/view/view_factory.h" #include "opentelemetry-matlab/metrics/MeterProxy.h" diff --git a/sdk/metrics/src/MeterProviderProxy.cpp b/sdk/metrics/src/MeterProviderProxy.cpp index 64b91c1..e0eb3c3 100644 --- a/sdk/metrics/src/MeterProviderProxy.cpp +++ b/sdk/metrics/src/MeterProviderProxy.cpp @@ -5,8 +5,6 @@ #include "libmexclass/proxy/ProxyManager.h" #include -#include -#include namespace libmexclass::opentelemetry::sdk { libmexclass::proxy::MakeResult MeterProviderProxy::make(const libmexclass::proxy::FunctionArguments& constructor_arguments) { @@ -16,17 +14,13 @@ libmexclass::proxy::MakeResult MeterProviderProxy::make(const libmexclass::proxy auto exporter = otlpexporter::OtlpHttpMetricExporterFactory::Create(); // Initialize and set the periodic metrics reader metrics_sdk::PeriodicExportingMetricReaderOptions options; - options.export_interval_millis = std::chrono::milliseconds(1000); - options.export_timeout_millis = std::chrono::milliseconds(500); auto reader = metrics_sdk::PeriodicExportingMetricReaderFactory::Create(std::move(exporter), options); auto p = metrics_sdk::MeterProviderFactory::Create(); - // auto p = nostd::shared_ptr(std::move(metrics_sdk::MeterProviderFactory::Create())); auto *p_sdk = static_cast(p.get()); p_sdk->AddMetricReader(std::move(reader)); auto p_out = nostd::shared_ptr(std::move(p)); - out = std::make_shared(p_out); return out; From 9e729e3218e6676a0250510820bc3a007bbacf59 Mon Sep 17 00:00:00 2001 From: duncanpo Date: Thu, 17 Aug 2023 16:57:33 -0400 Subject: [PATCH 11/17] Update metrics code to use utils function from common folder --- api/metrics/+opentelemetry/+metrics/Meter.m | 2 +- sdk/metrics/+opentelemetry/+sdk/+metrics/MeterProvider.m | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/api/metrics/+opentelemetry/+metrics/Meter.m b/api/metrics/+opentelemetry/+metrics/Meter.m index 77bb8ca..bad9666 100644 --- a/api/metrics/+opentelemetry/+metrics/Meter.m +++ b/api/metrics/+opentelemetry/+metrics/Meter.m @@ -36,7 +36,7 @@ ctdescription = "" ctunit = "" end - import opentelemetry.utils.mustBeScalarString + import opentelemetry.common.mustBeScalarString ctname = mustBeScalarString(ctname); ctdescription = mustBeScalarString(ctdescription); ctunit = mustBeScalarString(ctunit); diff --git a/sdk/metrics/+opentelemetry/+sdk/+metrics/MeterProvider.m b/sdk/metrics/+opentelemetry/+sdk/+metrics/MeterProvider.m index 070b784..ec019eb 100644 --- a/sdk/metrics/+opentelemetry/+sdk/+metrics/MeterProvider.m +++ b/sdk/metrics/+opentelemetry/+sdk/+metrics/MeterProvider.m @@ -42,7 +42,7 @@ end % name, version, schema accepts any types that can convert to a % string - import opentelemetry.utils.mustBeScalarString + import opentelemetry.common.mustBeScalarString mtname = mustBeScalarString(mtname); mtversion = mustBeScalarString(mtversion); mtschema = mustBeScalarString(mtschema); From 23ec1df5da2bd56ce3b491436f8f9c9f480cc444 Mon Sep 17 00:00:00 2001 From: duncanpo Date: Tue, 29 Aug 2023 12:24:31 -0400 Subject: [PATCH 12/17] fix a fallout from previous merge --- CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index b3c01be..e61d8d7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -196,16 +196,19 @@ target_link_libraries(${OPENTELEMETRY_PROXY_LIBRARY_NAME} PRIVATE ${OTEL_CPP_PRE ${OTEL_CPP_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}opentelemetry_trace${CMAKE_STATIC_LIBRARY_SUFFIX} ${OTEL_CPP_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}opentelemetry_version${CMAKE_STATIC_LIBRARY_SUFFIX} ${OTEL_CPP_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}opentelemetry_logs${CMAKE_STATIC_LIBRARY_SUFFIX} + ${OTEL_CPP_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}opentelemetry_metrics${CMAKE_STATIC_LIBRARY_SUFFIX} ${Protobuf_LIBRARIES}) if(WITH_OTLP_HTTP) target_link_libraries(${OPENTELEMETRY_PROXY_LIBRARY_NAME} PRIVATE ${OTEL_CPP_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}opentelemetry_exporter_otlp_http${CMAKE_STATIC_LIBRARY_SUFFIX} ${OTEL_CPP_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}opentelemetry_exporter_otlp_http_client${CMAKE_STATIC_LIBRARY_SUFFIX} + ${OTEL_CPP_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}opentelemetry_exporter_otlp_http_metric${CMAKE_STATIC_LIBRARY_SUFFIX} ${OTEL_CPP_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}opentelemetry_http_client_curl${CMAKE_STATIC_LIBRARY_SUFFIX} ${CURL_LIBRARIES}) endif() if(WITH_OTLP_GRPC) target_link_libraries(${OPENTELEMETRY_PROXY_LIBRARY_NAME} PRIVATE ${OTEL_CPP_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}opentelemetry_exporter_otlp_grpc${CMAKE_STATIC_LIBRARY_SUFFIX} ${OTEL_CPP_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}opentelemetry_exporter_otlp_grpc_client${CMAKE_STATIC_LIBRARY_SUFFIX} + ${OTEL_CPP_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}opentelemetry_exporter_otlp_grpc_metrics${CMAKE_STATIC_LIBRARY_SUFFIX} ${OTEL_CPP_PREFIX}/lib/${CMAKE_SHARED_LIBRARY_PREFIX}opentelemetry_proto_grpc${OTEL_PROTO_LIBRARY_SUFFIX} gRPC::grpc++ absl::synchronization) From 77831416d71708fa8b4c36fc4997900807e36687 Mon Sep 17 00:00:00 2001 From: Rick Tu Date: Wed, 6 Sep 2023 12:18:20 -0400 Subject: [PATCH 13/17] feat: UpDownCounter, Histogram, tmetrics 1. Class: UpDownCounter, Histogram 2. Test: tmetrics --- CMakeLists.txt | 5 +- api/metrics/+opentelemetry/+metrics/Counter.m | 24 +- .../+opentelemetry/+metrics/Histogram.m | 55 +++ api/metrics/+opentelemetry/+metrics/Meter.m | 43 ++- .../+opentelemetry/+metrics/UpDownCounter.m | 58 +++ .../metrics/CounterProxy.h | 2 + .../metrics/HistogramProxy.h | 36 ++ .../opentelemetry-matlab/metrics/MeterProxy.h | 10 + .../metrics/UpDownCounterProxy.h | 33 ++ api/metrics/src/CounterProxy.cpp | 18 +- api/metrics/src/HistogramProxy.cpp | 44 +++ api/metrics/src/MeterProxy.cpp | 55 ++- api/metrics/src/UpDownCounterProxy.cpp | 41 ++ test/tmetrics.m | 349 ++++++++++++++++++ 14 files changed, 764 insertions(+), 9 deletions(-) create mode 100644 api/metrics/+opentelemetry/+metrics/Histogram.m create mode 100644 api/metrics/+opentelemetry/+metrics/UpDownCounter.m create mode 100644 api/metrics/include/opentelemetry-matlab/metrics/HistogramProxy.h create mode 100644 api/metrics/include/opentelemetry-matlab/metrics/UpDownCounterProxy.h create mode 100644 api/metrics/src/HistogramProxy.cpp create mode 100644 api/metrics/src/UpDownCounterProxy.cpp create mode 100644 test/tmetrics.m diff --git a/CMakeLists.txt b/CMakeLists.txt index e61d8d7..0eefb27 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,7 +64,8 @@ else() set(OTEL_CPP_CXX_STANDARD 11) endif() -set(patch_command git apply ${CMAKE_SOURCE_DIR}/otel-cpp.patch) +# set(patch_command git apply ${CMAKE_SOURCE_DIR}/otel-cpp.patch) +set(patch_command "") ExternalProject_Add( ${OTEL_CPP_PROJECT_NAME} @@ -137,6 +138,8 @@ set(OPENTELEMETRY_PROXY_SOURCES ${COMMON_API_SOURCE_DIR}/attribute.cpp ${METRICS_API_SOURCE_DIR}/MeterProxy.cpp ${METRICS_API_SOURCE_DIR}/CounterProxy.cpp + ${METRICS_API_SOURCE_DIR}/UpDownCounterProxy.cpp + ${METRICS_API_SOURCE_DIR}/HistogramProxy.cpp ${CONTEXT_API_SOURCE_DIR}/TextMapPropagatorProxy.cpp ${CONTEXT_API_SOURCE_DIR}/CompositePropagatorProxy.cpp ${CONTEXT_API_SOURCE_DIR}/TextMapCarrierProxy.cpp diff --git a/api/metrics/+opentelemetry/+metrics/Counter.m b/api/metrics/+opentelemetry/+metrics/Counter.m index 237d640..a26d8f0 100644 --- a/api/metrics/+opentelemetry/+metrics/Counter.m +++ b/api/metrics/+opentelemetry/+metrics/Counter.m @@ -17,7 +17,7 @@ methods (Access={?opentelemetry.metrics.Meter}) function obj = Counter(proxy, ctname, ctdescription, ctunit) - % Private constructor. Use getCounter method of Meter + % Private constructor. Use createCounter method of Meter % to create Counters. obj.Proxy = proxy; obj.Name = ctname; @@ -29,10 +29,28 @@ methods - function add(obj, value) + function add(obj, value, varargin) + % input value must be a numerical scalar if isnumeric(value) && isscalar(value) - obj.Proxy.add(value); + + if nargin == 2 + obj.Proxy.add(value); + + elseif isa(varargin{1}, "dictionary") + attrkeys = keys(varargin{1}); + attrvals = values(varargin{1},"cell"); + if all(cellfun(@iscell, attrvals)) + attrvals = [attrvals{:}]; + end + obj.Proxy.add(value,attrkeys,attrvals); + + else + attrkeys = [varargin{1:2:(nargin-2)}]'; + attrvals = [varargin(2:2:(nargin-2))]'; + obj.Proxy.add(value,attrkeys,attrvals); + end end + end end diff --git a/api/metrics/+opentelemetry/+metrics/Histogram.m b/api/metrics/+opentelemetry/+metrics/Histogram.m new file mode 100644 index 0000000..5cb7df5 --- /dev/null +++ b/api/metrics/+opentelemetry/+metrics/Histogram.m @@ -0,0 +1,55 @@ +classdef Histogram < handle + % Histogram is an instrument that adds or reduce values. + + % Copyright 2023 The MathWorks, Inc. + + properties (SetAccess=immutable) + Name (1,1) string + Description (1,1) string + Unit (1,1) string + end + + properties (Access=public) + Proxy % Proxy object to interface C++ code + end + + methods (Access={?opentelemetry.metrics.Meter}) + + function obj = Histogram(proxy, hiname, hidescription, hiunit) + % Private constructor. Use createHistogram method of Meter + % to create Histograms. + obj.Proxy = proxy; + obj.Name = hiname; + obj.Description = hidescription; + obj.Unit = hiunit; + end + + end + + methods + + function record(obj, value, varargin) + % input value must be a numerical scalar + if isnumeric(value) && isscalar(value) + if nargin == 2 + obj.Proxy.record(value); + elseif isa(varargin{1}, "dictionary") + attrkeys = keys(varargin{1}); + attrvals = values(varargin{1},"cell"); + if all(cellfun(@iscell, attrvals)) + attrvals = [attrvals{:}]; + end + obj.Proxy.record(value,attrkeys,attrvals); + else + attrkeys = [varargin{1:2:(nargin-2)}]'; + attrvals = [varargin(2:2:(nargin-2))]'; + obj.Proxy.record(value,attrkeys,attrvals); + end + end + + end + + end + + +end diff --git a/api/metrics/+opentelemetry/+metrics/Meter.m b/api/metrics/+opentelemetry/+metrics/Meter.m index e46fd53..250a5b9 100644 --- a/api/metrics/+opentelemetry/+metrics/Meter.m +++ b/api/metrics/+opentelemetry/+metrics/Meter.m @@ -36,15 +36,52 @@ ctdescription = "" ctunit = "" end - import opentelemetry.common.mustBeScalarString ctname = mustBeScalarString(ctname); ctdescription = mustBeScalarString(ctdescription); ctunit = mustBeScalarString(ctunit); id = obj.Proxy.createCounter(ctname, ctdescription, ctunit); - Counterproxy = libmexclass.proxy.Proxy("Name", ... + CounterProxy = libmexclass.proxy.Proxy("Name", ... "libmexclass.opentelemetry.CounterProxy", "ID", id); - counter = opentelemetry.metrics.Counter(Counterproxy, ctname, ctdescription, ctunit); + counter = opentelemetry.metrics.Counter(CounterProxy, ctname, ctdescription, ctunit); + end + + + function updowncounter = createUpDownCounter(obj, ctname, ctdescription, ctunit) + arguments + obj + ctname + ctdescription = "" + ctunit = "" + end + + import opentelemetry.common.mustBeScalarString + ctname = mustBeScalarString(ctname); + ctdescription = mustBeScalarString(ctdescription); + ctunit = mustBeScalarString(ctunit); + id = obj.Proxy.createUpDownCounter(ctname, ctdescription, ctunit); + UpDownCounterProxy = libmexclass.proxy.Proxy("Name", ... + "libmexclass.opentelemetry.UpDownCounterProxy", "ID", id); + updowncounter = opentelemetry.metrics.UpDownCounter(UpDownCounterProxy, ctname, ctdescription, ctunit); + end + + + function histogram = createHistogram(obj, hiname, hidescription, hiunit) + arguments + obj + hiname + hidescription = "" + hiunit = "" + end + + import opentelemetry.common.mustBeScalarString + hiname = mustBeScalarString(hiname); + hidescription = mustBeScalarString(hidescription); + hiunit = mustBeScalarString(hiunit); + id = obj.Proxy.createHistogram(hiname, hidescription, hiunit); + HistogramProxy = libmexclass.proxy.Proxy("Name", ... + "libmexclass.opentelemetry.HistogramProxy", "ID", id); + histogram = opentelemetry.metrics.Histogram(HistogramProxy, hiname, hidescription, hiunit); end end diff --git a/api/metrics/+opentelemetry/+metrics/UpDownCounter.m b/api/metrics/+opentelemetry/+metrics/UpDownCounter.m new file mode 100644 index 0000000..3b84c75 --- /dev/null +++ b/api/metrics/+opentelemetry/+metrics/UpDownCounter.m @@ -0,0 +1,58 @@ +classdef UpDownCounter < handle + % UpDownCounter is an instrument that adds or reduce values. + + % Copyright 2023 The MathWorks, Inc. + + properties (SetAccess=immutable) + Name (1,1) string + Description (1,1) string + Unit (1,1) string + end + + properties (Access=public) + Proxy % Proxy object to interface C++ code + end + + methods (Access={?opentelemetry.metrics.Meter}) + + function obj = UpDownCounter(proxy, ctname, ctdescription, ctunit) + % Private constructor. Use createUpDownCounter method of Meter + % to create UpDownCounters. + obj.Proxy = proxy; + obj.Name = ctname; + obj.Description = ctdescription; + obj.Unit = ctunit; + end + + end + + methods + + function add(obj, value, varargin) + % input value must be a numerical scalar + if isnumeric(value) && isscalar(value) + + if nargin == 2 + obj.Proxy.add(value); + + elseif isa(varargin{1}, "dictionary") + attrkeys = keys(varargin{1}); + attrvals = values(varargin{1},"cell"); + if all(cellfun(@iscell, attrvals)) + attrvals = [attrvals{:}]; + end + obj.Proxy.add(value,attrkeys,attrvals); + + else + attrkeys = [varargin{1:2:(nargin-2)}]'; + attrvals = [varargin(2:2:(nargin-2))]'; + obj.Proxy.add(value,attrkeys,attrvals); + end + end + + end + + end + + +end diff --git a/api/metrics/include/opentelemetry-matlab/metrics/CounterProxy.h b/api/metrics/include/opentelemetry-matlab/metrics/CounterProxy.h index 3a1cf95..6271d60 100644 --- a/api/metrics/include/opentelemetry-matlab/metrics/CounterProxy.h +++ b/api/metrics/include/opentelemetry-matlab/metrics/CounterProxy.h @@ -8,6 +8,8 @@ #include "opentelemetry/metrics/meter.h" #include "opentelemetry/metrics/sync_instruments.h" +#include "opentelemetry-matlab/common/attribute.h" +#include "opentelemetry-matlab/common/ProcessedAttributes.h" namespace metrics_api = opentelemetry::metrics; namespace nostd = opentelemetry::nostd; diff --git a/api/metrics/include/opentelemetry-matlab/metrics/HistogramProxy.h b/api/metrics/include/opentelemetry-matlab/metrics/HistogramProxy.h new file mode 100644 index 0000000..248c628 --- /dev/null +++ b/api/metrics/include/opentelemetry-matlab/metrics/HistogramProxy.h @@ -0,0 +1,36 @@ +// Copyright 2023 The MathWorks, Inc. + +#pragma once + +#include "libmexclass/proxy/Proxy.h" +#include "libmexclass/proxy/method/Context.h" + +#include "opentelemetry/context/context.h" +#include "opentelemetry/metrics/meter.h" +#include "opentelemetry/metrics/sync_instruments.h" + +#include "opentelemetry-matlab/common/attribute.h" +#include "opentelemetry-matlab/common/ProcessedAttributes.h" +#include "opentelemetry-matlab/context/ContextProxy.h" + +namespace metrics_api = opentelemetry::metrics; +namespace context = opentelemetry::context; +namespace nostd = opentelemetry::nostd; + +namespace libmexclass::opentelemetry { +class HistogramProxy : public libmexclass::proxy::Proxy { + public: + HistogramProxy(nostd::shared_ptr > hist) : CppHistogram(hist) { + REGISTER_METHOD(HistogramProxy, record); + } + + void record(libmexclass::proxy::method::Context& context); + + private: + + nostd::shared_ptr > CppHistogram; + +}; +} // namespace libmexclass::opentelemetry + + diff --git a/api/metrics/include/opentelemetry-matlab/metrics/MeterProxy.h b/api/metrics/include/opentelemetry-matlab/metrics/MeterProxy.h index 72d79d6..ab45e48 100644 --- a/api/metrics/include/opentelemetry-matlab/metrics/MeterProxy.h +++ b/api/metrics/include/opentelemetry-matlab/metrics/MeterProxy.h @@ -5,6 +5,10 @@ #include "libmexclass/proxy/Proxy.h" #include "libmexclass/proxy/method/Context.h" +#include "opentelemetry-matlab/metrics/CounterProxy.h" +#include "opentelemetry-matlab/metrics/HistogramProxy.h" +#include "opentelemetry-matlab/metrics/UpDownCounterProxy.h" + #include "opentelemetry/metrics/meter.h" namespace metrics_api = opentelemetry::metrics; @@ -15,10 +19,16 @@ class MeterProxy : public libmexclass::proxy::Proxy { public: MeterProxy(nostd::shared_ptr mt) : CppMeter(mt) { REGISTER_METHOD(MeterProxy, createCounter); + REGISTER_METHOD(MeterProxy, createUpDownCounter); + REGISTER_METHOD(MeterProxy, createHistogram); } void createCounter(libmexclass::proxy::method::Context& context); + void createUpDownCounter(libmexclass::proxy::method::Context& context); + + void createHistogram(libmexclass::proxy::method::Context& context); + private: nostd::shared_ptr CppMeter; diff --git a/api/metrics/include/opentelemetry-matlab/metrics/UpDownCounterProxy.h b/api/metrics/include/opentelemetry-matlab/metrics/UpDownCounterProxy.h new file mode 100644 index 0000000..6a41c75 --- /dev/null +++ b/api/metrics/include/opentelemetry-matlab/metrics/UpDownCounterProxy.h @@ -0,0 +1,33 @@ +// Copyright 2023 The MathWorks, Inc. + +#pragma once + +#include "libmexclass/proxy/Proxy.h" +#include "libmexclass/proxy/method/Context.h" + +#include "opentelemetry/metrics/meter.h" +#include "opentelemetry/metrics/sync_instruments.h" + +#include "opentelemetry-matlab/common/attribute.h" +#include "opentelemetry-matlab/common/ProcessedAttributes.h" + +namespace metrics_api = opentelemetry::metrics; +namespace nostd = opentelemetry::nostd; + +namespace libmexclass::opentelemetry { +class UpDownCounterProxy : public libmexclass::proxy::Proxy { + public: + UpDownCounterProxy(nostd::shared_ptr > ct) : CppUpDownCounter(ct) { + REGISTER_METHOD(UpDownCounterProxy, add); + } + + void add(libmexclass::proxy::method::Context& context); + + private: + + nostd::shared_ptr > CppUpDownCounter; + +}; +} // namespace libmexclass::opentelemetry + + diff --git a/api/metrics/src/CounterProxy.cpp b/api/metrics/src/CounterProxy.cpp index 99a09b9..77e498f 100644 --- a/api/metrics/src/CounterProxy.cpp +++ b/api/metrics/src/CounterProxy.cpp @@ -16,7 +16,23 @@ void CounterProxy::add(libmexclass::proxy::method::Context& context){ matlab::data::Array value_mda = context.inputs[0]; double value = static_cast(value_mda[0]); - CppCounter->Add(value); + size_t nin = context.inputs.getNumberOfElements(); + if (nin == 1){ + CppCounter->Add(value); + } + // add attributes + else { + ProcessedAttributes attrs; + matlab::data::StringArray attrnames_mda = context.inputs[1]; + matlab::data::Array attrvalues_mda = context.inputs[2]; + size_t nattrs = attrnames_mda.getNumberOfElements(); + for (size_t i = 0; i < nattrs; i ++){ + std::string attrname = static_cast(attrnames_mda[i]); + matlab::data::Array attrvalue = attrvalues_mda[i]; + processAttribute(attrname, attrvalue, attrs); + } + CppCounter->Add(value, attrs.Attributes); + } } diff --git a/api/metrics/src/HistogramProxy.cpp b/api/metrics/src/HistogramProxy.cpp new file mode 100644 index 0000000..3d3ea5f --- /dev/null +++ b/api/metrics/src/HistogramProxy.cpp @@ -0,0 +1,44 @@ +// Copyright 2023 The MathWorks, Inc. + +#include "opentelemetry-matlab/metrics/HistogramProxy.h" + +#include "libmexclass/proxy/ProxyManager.h" + + +#include "MatlabDataArray.hpp" + +#include + +namespace libmexclass::opentelemetry { + + +void HistogramProxy::record(libmexclass::proxy::method::Context& context){ + // Get value + matlab::data::Array value_mda = context.inputs[0]; + double value = static_cast(value_mda[0]); + // Create empty context + auto ctxt = context_api::Context(); + // If no attributes input, record value and context + size_t nin = context.inputs.getNumberOfElements(); + if (nin == 1){ + CppHistogram->Record(value, ctxt); + } + // Otherwise, get attributes, record value, attributes and context + else { + ProcessedAttributes attrs; + matlab::data::StringArray attrnames_mda = context.inputs[1]; + matlab::data::Array attrvalues_mda = context.inputs[2]; + size_t nattrs = attrnames_mda.getNumberOfElements(); + for (size_t i = 0; i < nattrs; i ++){ + std::string attrname = static_cast(attrnames_mda[i]); + matlab::data::Array attrvalue = attrvalues_mda[i]; + processAttribute(attrname, attrvalue, attrs); + } + CppHistogram->Record(value, attrs.Attributes, ctxt); + } + +} + + + +} // namespace libmexclass::opentelemetry diff --git a/api/metrics/src/MeterProxy.cpp b/api/metrics/src/MeterProxy.cpp index 07c574e..3d0d399 100644 --- a/api/metrics/src/MeterProxy.cpp +++ b/api/metrics/src/MeterProxy.cpp @@ -1,7 +1,7 @@ // Copyright 2023 The MathWorks, Inc. #include "opentelemetry-matlab/metrics/MeterProxy.h" -#include "opentelemetry-matlab/metrics/CounterProxy.h" + #include "libmexclass/proxy/ProxyManager.h" #include "MatlabDataArray.hpp" @@ -32,4 +32,57 @@ void MeterProxy::createCounter(libmexclass::proxy::method::Context& context) { auto proxyid_mda = factory.createScalar(proxyid); context.outputs[0] = proxyid_mda; } + + +void MeterProxy::createUpDownCounter(libmexclass::proxy::method::Context& context) { + // Always assumes 3 inputs + matlab::data::StringArray name_mda = context.inputs[0]; + std::string name = static_cast(name_mda[0]); + matlab::data::StringArray description_mda = context.inputs[1]; + std::string description= static_cast(description_mda[0]); + matlab::data::StringArray unit_mda = context.inputs[2]; + std::string unit = static_cast(unit_mda[0]); + + nostd::shared_ptr > ct = std::move(CppMeter->CreateDoubleUpDownCounter +(name, description, unit)); + + // instantiate a UpDownCounterProxy instance + UpDownCounterProxy* newproxy = new UpDownCounterProxy(ct); + auto proxy = std::shared_ptr(newproxy); + + // obtain a proxy ID + libmexclass::proxy::ID proxyid = libmexclass::proxy::ProxyManager::manageProxy(proxy); + + // return the ID + matlab::data::ArrayFactory factory; + auto proxyid_mda = factory.createScalar(proxyid); + context.outputs[0] = proxyid_mda; +} + + +void MeterProxy::createHistogram(libmexclass::proxy::method::Context& context) { + // Always assumes 3 inputs + matlab::data::StringArray name_mda = context.inputs[0]; + std::string name = static_cast(name_mda[0]); + matlab::data::StringArray description_mda = context.inputs[1]; + std::string description= static_cast(description_mda[0]); + matlab::data::StringArray unit_mda = context.inputs[2]; + std::string unit = static_cast(unit_mda[0]); + + nostd::shared_ptr > hist = std::move(CppMeter->CreateDoubleHistogram(name, description, unit)); + + // instantiate a HistogramProxy instance + HistogramProxy* newproxy = new HistogramProxy(hist); + auto proxy = std::shared_ptr(newproxy); + + // obtain a proxy ID + libmexclass::proxy::ID proxyid = libmexclass::proxy::ProxyManager::manageProxy(proxy); + + // return the ID + matlab::data::ArrayFactory factory; + auto proxyid_mda = factory.createScalar(proxyid); + context.outputs[0] = proxyid_mda; +} + + } // namespace libmexclass::opentelemetry diff --git a/api/metrics/src/UpDownCounterProxy.cpp b/api/metrics/src/UpDownCounterProxy.cpp new file mode 100644 index 0000000..f4d35ef --- /dev/null +++ b/api/metrics/src/UpDownCounterProxy.cpp @@ -0,0 +1,41 @@ +// Copyright 2023 The MathWorks, Inc. + +#include "opentelemetry-matlab/metrics/UpDownCounterProxy.h" + +#include "libmexclass/proxy/ProxyManager.h" + + +#include "MatlabDataArray.hpp" + +#include + +namespace libmexclass::opentelemetry { + + +void UpDownCounterProxy::add(libmexclass::proxy::method::Context& context){ + + matlab::data::Array value_mda = context.inputs[0]; + double value = static_cast(value_mda[0]); + size_t nin = context.inputs.getNumberOfElements(); + if (nin == 1){ + CppUpDownCounter->Add(value); + } + // add attributes + else { + ProcessedAttributes attrs; + matlab::data::StringArray attrnames_mda = context.inputs[1]; + matlab::data::Array attrvalues_mda = context.inputs[2]; + size_t nattrs = attrnames_mda.getNumberOfElements(); + for (size_t i = 0; i < nattrs; i ++){ + std::string attrname = static_cast(attrnames_mda[i]); + matlab::data::Array attrvalue = attrvalues_mda[i]; + processAttribute(attrname, attrvalue, attrs); + } + CppUpDownCounter->Add(value, attrs.Attributes); + } + +} + + + +} // namespace libmexclass::opentelemetry diff --git a/test/tmetrics.m b/test/tmetrics.m new file mode 100644 index 0000000..f28db40 --- /dev/null +++ b/test/tmetrics.m @@ -0,0 +1,349 @@ +classdef tmetrics < matlab.unittest.TestCase + % tests for traces and spans + + % Copyright 2023 The MathWorks, Inc. + + properties + OtelConfigFile + OtelRoot + JsonFile + PidFile + OtelcolName + Otelcol + ListPid + ReadPidList + ExtractPid + Sigint + Sigterm + end + + methods (TestClassSetup) + function setupOnce(testCase) + commonSetupOnce(testCase); + end + end + + methods (TestMethodSetup) + function setup(testCase) + commonSetup(testCase); + end + end + + methods (TestMethodTeardown) + function teardown(testCase) + commonTeardown(testCase); + end + end + + methods (Test) + + function testCounterBasic(testCase) + % test names and added value in Counter + + metername = "foo"; + countername = "bar"; + + p = opentelemetry.sdk.metrics.MeterProvider(); + mt = p.getMeter(metername); + ct = mt.createCounter(countername); + + % verify MATLAB object properties + verifyEqual(testCase, mt.Name, metername); + verifyEqual(testCase, mt.Version, ""); + verifyEqual(testCase, mt.Schema, ""); + verifyEqual(testCase, ct.Name, countername); + + % create testing value + val = 10; + + % add value and attributes + ct.add(val); + + % wait for default collector response time (60s) + pause(70); + + % fetch result + results = readJsonResults(testCase); + results = results{1}; + + % verify meter and counter names + verifyEqual(testCase, string(results.resourceMetrics.scopeMetrics.metrics.name), countername); + verifyEqual(testCase, string(results.resourceMetrics.scopeMetrics.scope.name), metername); + + % fetch datapoint + dp = results.resourceMetrics.scopeMetrics.metrics.sum.dataPoints; + + % verify counter value + verifyEqual(testCase, dp.asDouble, val); + + end + + + function testCounterAddAttributes(testCase) + % test names, added value and attributes in Counter + + metername = "foo"; + countername = "bar"; + + p = opentelemetry.sdk.metrics.MeterProvider(); + mt = p.getMeter(metername); + ct = mt.createCounter(countername); + + % verify MATLAB object properties + verifyEqual(testCase, mt.Name, metername); + verifyEqual(testCase, mt.Version, ""); + verifyEqual(testCase, mt.Schema, ""); + verifyEqual(testCase, ct.Name, countername); + + % create testing value and dictionary + dict = dictionary("k1","v1","k2",5); + vals = [1,2,3]; + dict_keys = keys(dict); + dict_vals = values(dict); + + % add value and attributes + ct.add(vals(1),dict); + ct.add(vals(2),dict); + ct.add(vals(3),dict_keys(1),dict_vals(1),dict_keys(2),dict_vals(2)); + + % wait for default collector response time (60s) + pause(70); + + % fetch result + results = readJsonResults(testCase); + results = results{1}; + + % verify meter and counter names + verifyEqual(testCase, string(results.resourceMetrics.scopeMetrics.metrics.name), countername); + verifyEqual(testCase, string(results.resourceMetrics.scopeMetrics.scope.name), metername); + + % fetch datapoint + dp = results.resourceMetrics.scopeMetrics.metrics.sum.dataPoints; + + % verify counter value + verifyEqual(testCase, dp.asDouble, sum(vals)); + + % verify counter attributes + verifyEqual(testCase, string(dp.attributes(1).key), dict_keys(1)); + verifyEqual(testCase, string(dp.attributes(1).value.stringValue), dict_vals(1)); + verifyEqual(testCase, string(dp.attributes(2).key), dict_keys(2)); + verifyEqual(testCase, string(dp.attributes(2).value.stringValue), dict_vals(2)); + + end + + + function testCounterAddNegative(testCase) + % test if counter value remain 0 when added negative value + + metername = "foo"; + countername = "bar"; + + p = opentelemetry.sdk.metrics.MeterProvider(); + mt = p.getMeter(metername); + ct = mt.createCounter(countername); + + % add negative value to counter + ct.add(-1); + pause(70); + + % fetch results + results = readJsonResults(testCase); + results = results{1}; + dp = results.resourceMetrics.scopeMetrics.metrics.sum.dataPoints; + + % verify that the counter value is still 0 + verifyEqual(testCase, dp.asDouble, 0); + + end + + + function testUpDownCounterBasic(testCase) + % test names and added value in UpDownCounter + + metername = "foo"; + countername = "bar"; + + p = opentelemetry.sdk.metrics.MeterProvider(); + mt = p.getMeter(metername); + ct = mt.createUpDownCounter(countername); + + % verify MATLAB object properties + verifyEqual(testCase, mt.Name, metername); + verifyEqual(testCase, mt.Version, ""); + verifyEqual(testCase, mt.Schema, ""); + verifyEqual(testCase, ct.Name, countername); + + % create testing value + val = 10; + + % add value and attributes + ct.add(val); + + % wait for default collector response time (60s) + pause(70); + + % fetch result + results = readJsonResults(testCase); + results = results{1}; + + % verify meter and counter names + verifyEqual(testCase, string(results.resourceMetrics.scopeMetrics.metrics.name), countername); + verifyEqual(testCase, string(results.resourceMetrics.scopeMetrics.scope.name), metername); + + % fetch datapoint + dp = results.resourceMetrics.scopeMetrics.metrics.sum.dataPoints; + + % verify counter value + verifyEqual(testCase, dp.asDouble, val); + + end + + + function testUpDownCounterAddAttributes(testCase) + % test names, added value and attributes in UpDownCounter + + metername = "foo"; + countername = "bar"; + + p = opentelemetry.sdk.metrics.MeterProvider(); + mt = p.getMeter(metername); + ct = mt.createUpDownCounter(countername); + + % verify MATLAB object properties + verifyEqual(testCase, mt.Name, metername); + verifyEqual(testCase, mt.Version, ""); + verifyEqual(testCase, mt.Schema, ""); + verifyEqual(testCase, ct.Name, countername); + + % create testing value and dictionary + dict = dictionary("k1","v1","k2",5); + vals = [2,-1,3]; + dict_keys = keys(dict); + dict_vals = values(dict); + + % add value and attributes + ct.add(vals(1),dict); + ct.add(vals(2),dict); + ct.add(vals(3),dict_keys(1),dict_vals(1),dict_keys(2),dict_vals(2)); + + % wait for default collector response time (60s) + pause(70); + + % fetch result + results = readJsonResults(testCase); + results = results{1}; + + % verify meter and counter names + verifyEqual(testCase, string(results.resourceMetrics.scopeMetrics.metrics.name), countername); + verifyEqual(testCase, string(results.resourceMetrics.scopeMetrics.scope.name), metername); + + % fetch datapoint + dp = results.resourceMetrics.scopeMetrics.metrics.sum.dataPoints; + + % verify counter value + verifyEqual(testCase, dp.asDouble, sum(vals)); + + % verify counter attributes + verifyEqual(testCase, string(dp.attributes(1).key), dict_keys(1)); + verifyEqual(testCase, string(dp.attributes(1).value.stringValue), dict_vals(1)); + verifyEqual(testCase, string(dp.attributes(2).key), dict_keys(2)); + verifyEqual(testCase, string(dp.attributes(2).value.stringValue), dict_vals(2)); + + end + + + function testHistogramBasic(testCase) + % test recorded values in histogram + + metername = "foo"; + histname = "bar"; + + p = opentelemetry.sdk.metrics.MeterProvider(); + mt = p.getMeter(metername); + hist = mt.createHistogram(histname); + + % create value for histogram + val = 1; + + % record value + hist.record(val); + + % wait for collector response + pause(75); + + % fetch results + results = readJsonResults(testCase); + results = results{1}; + dp = results.resourceMetrics.scopeMetrics.metrics.histogram.dataPoints; + bounds = dp.explicitBounds; + counts = dp.bucketCounts; + + % verify statistics + verifyEqual(testCase, dp.min, val); + verifyEqual(testCase, dp.max, val); + verifyEqual(testCase, dp.sum, val); + + % verify count in bucket + lower = bounds(1); + upper = bounds(2); + expect_count = sum(val>lower & val<=upper); + verifyEqual(testCase, str2double(counts{2}), expect_count); + + end + + + function testHistogramRecordAttributes(testCase) + % test recorded values and attributes in histogram + + metername = "foo"; + histname = "bar"; + + p = opentelemetry.sdk.metrics.MeterProvider(); + mt = p.getMeter(metername); + hist = mt.createHistogram(histname); + + % create value and attributes for histogram + dict = dictionary("k1","v1","k2","v2"); + vals = [1,5,10]; + dict_keys = keys(dict); + dict_vals = values(dict); + + % record value and attributes + hist.record(vals(1),dict); + hist.record(vals(2),dict); + hist.record(vals(3),dict_keys(1),dict_vals(1),dict_keys(2),dict_vals(2)); + + % wait for collector response + pause(75); + + % fetch results + results = readJsonResults(testCase); + results = results{1}; + dp = results.resourceMetrics.scopeMetrics.metrics.histogram.dataPoints; + bounds = dp.explicitBounds; + counts = dp.bucketCounts; + + % verify statistics + verifyEqual(testCase, dp.min, min(vals)); + verifyEqual(testCase, dp.max, max(vals)); + verifyEqual(testCase, dp.sum, sum(vals)); + + % verify attributes + verifyEqual(testCase, string(dp.attributes(1).key), dict_keys(1)); + verifyEqual(testCase, string(dp.attributes(1).value.stringValue), dict_vals(1)); + verifyEqual(testCase, string(dp.attributes(2).key), dict_keys(2)); + verifyEqual(testCase, string(dp.attributes(2).value.stringValue), dict_vals(2)); + + % verify count in bucket + for i = 2:(length(counts)-1) + lower = bounds(i-1); + upper = bounds(i); + expect_count = sum(vals>lower & vals<=upper); + verifyEqual(testCase, str2double(counts{i}), expect_count); + end + + end + + end + +end From e0bd4e72974cc6098be9c2a50da8c41bb8ad231d Mon Sep 17 00:00:00 2001 From: Rick Tu Date: Wed, 6 Sep 2023 12:22:32 -0400 Subject: [PATCH 14/17] fix: reverse patch cmd in cmake --- CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0eefb27..77dac1c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,8 +64,7 @@ else() set(OTEL_CPP_CXX_STANDARD 11) endif() -# set(patch_command git apply ${CMAKE_SOURCE_DIR}/otel-cpp.patch) -set(patch_command "") +set(patch_command git apply ${CMAKE_SOURCE_DIR}/otel-cpp.patch) ExternalProject_Add( ${OTEL_CPP_PROJECT_NAME} From 72ac9a321965dc9d6b7afba7e0529f079569cefe Mon Sep 17 00:00:00 2001 From: Rick Tu Date: Wed, 6 Sep 2023 13:19:21 -0400 Subject: [PATCH 15/17] fix: merge updates in cmake patch cmd fix --- CMakeLists.txt | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 77dac1c..a03a16f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,9 @@ option(WITH_OTLP_GRPC "Whether to include the OTLP gRPC exporter" OFF) if(NOT WITH_OTLP_HTTP AND NOT WITH_OTLP_GRPC) message(FATAL_ERROR "At least one of WITH_OTLP_HTTP and WITH_OTLP_GRPC must be ON") endif() +if(APPLE) + option(SKIP_OTEL_CPP_PATCH "Whether to skip patching OpenTelemetry-cpp" OFF) +endif() # ###################################### # libmexclass FetchContent Configuration @@ -64,13 +67,18 @@ else() set(OTEL_CPP_CXX_STANDARD 11) endif() -set(patch_command git apply ${CMAKE_SOURCE_DIR}/otel-cpp.patch) +if(NOT APPLE OR SKIP_OTEL_CPP_PATCH) + set(patch_command "") +else() + set(patch_command git apply ${CMAKE_SOURCE_DIR}/otel-cpp.patch) +endif() ExternalProject_Add( ${OTEL_CPP_PROJECT_NAME} GIT_REPOSITORY ${OTEL_CPP_GIT_REPOSITORY} GIT_TAG ${OTEL_CPP_GIT_TAG} PREFIX ${OTEL_CPP_PREFIX} + UPDATE_DISCONNECTED 1 PATCH_COMMAND ${patch_command} CMAKE_ARGS -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DWITH_OTLP_HTTP=${WITH_OTLP_HTTP} -DWITH_OTLP_GRPC=${WITH_OTLP_GRPC} -DBUILD_TESTING=OFF -DWITH_BENCHMARK=OFF -DOPENTELEMETRY_INSTALL=ON -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} -DCMAKE_CXX_STANDARD=${OTEL_CPP_CXX_STANDARD} INSTALL_DIR ${OTEL_CPP_PREFIX} @@ -182,13 +190,20 @@ if(WITH_OTLP_GRPC) endif() endif() +# On Windows, suppress a compiler warning about deprecation of result_of +if(WIN32) + set(CUSTOM_CXX_FLAGS -D_SILENCE_CXX17_RESULT_OF_DEPRECATION_WARNING) +else() + set(CUSTOM_CXX_FLAGS "") +endif() + if(WIN32) set(OTEL_PROTO_LIBRARY_SUFFIX ${CMAKE_STATIC_LIBRARY_SUFFIX}) else() set(OTEL_PROTO_LIBRARY_SUFFIX ${CMAKE_SHARED_LIBRARY_SUFFIX}) endif() -target_compile_options(${OPENTELEMETRY_PROXY_LIBRARY_NAME} PRIVATE ${OTLP_MACROS}) +target_compile_options(${OPENTELEMETRY_PROXY_LIBRARY_NAME} PRIVATE ${OTLP_MACROS} ${CUSTOM_CXX_FLAGS}) # link against OpenTelemetry-cpp libraries and their dependencies target_link_libraries(${OPENTELEMETRY_PROXY_LIBRARY_NAME} PRIVATE ${OTEL_CPP_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}opentelemetry_common${CMAKE_STATIC_LIBRARY_SUFFIX} @@ -323,4 +338,4 @@ if(WITH_OTLP_GRPC) endif() # Install dependent runtime libraries -install(FILES ${OPENTELEMETRY_PROXY_RUNTIME_LIBRARIES} DESTINATION +libmexclass/+proxy) +install(FILES ${OPENTELEMETRY_PROXY_RUNTIME_LIBRARIES} DESTINATION +libmexclass/+proxy) \ No newline at end of file From ccfe101591b49ea263401279481e8eb137704f7d Mon Sep 17 00:00:00 2001 From: Rick Tu Date: Wed, 6 Sep 2023 13:45:49 -0400 Subject: [PATCH 16/17] fix: attribute pairs input indexing --- api/metrics/+opentelemetry/+metrics/Counter.m | 4 ++-- api/metrics/+opentelemetry/+metrics/Histogram.m | 4 ++-- api/metrics/+opentelemetry/+metrics/UpDownCounter.m | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/api/metrics/+opentelemetry/+metrics/Counter.m b/api/metrics/+opentelemetry/+metrics/Counter.m index a26d8f0..f416f41 100644 --- a/api/metrics/+opentelemetry/+metrics/Counter.m +++ b/api/metrics/+opentelemetry/+metrics/Counter.m @@ -45,8 +45,8 @@ function add(obj, value, varargin) obj.Proxy.add(value,attrkeys,attrvals); else - attrkeys = [varargin{1:2:(nargin-2)}]'; - attrvals = [varargin(2:2:(nargin-2))]'; + attrkeys = [varargin{1:2:length(varargin)}]'; + attrvals = [varargin(2:2:length(varargin))]'; obj.Proxy.add(value,attrkeys,attrvals); end end diff --git a/api/metrics/+opentelemetry/+metrics/Histogram.m b/api/metrics/+opentelemetry/+metrics/Histogram.m index 5cb7df5..8abc9ee 100644 --- a/api/metrics/+opentelemetry/+metrics/Histogram.m +++ b/api/metrics/+opentelemetry/+metrics/Histogram.m @@ -41,8 +41,8 @@ function record(obj, value, varargin) end obj.Proxy.record(value,attrkeys,attrvals); else - attrkeys = [varargin{1:2:(nargin-2)}]'; - attrvals = [varargin(2:2:(nargin-2))]'; + attrkeys = [varargin{1:2:length(varargin)}]'; + attrvals = [varargin(2:2:length(varargin))]'; obj.Proxy.record(value,attrkeys,attrvals); end end diff --git a/api/metrics/+opentelemetry/+metrics/UpDownCounter.m b/api/metrics/+opentelemetry/+metrics/UpDownCounter.m index 3b84c75..b008dc5 100644 --- a/api/metrics/+opentelemetry/+metrics/UpDownCounter.m +++ b/api/metrics/+opentelemetry/+metrics/UpDownCounter.m @@ -44,8 +44,8 @@ function add(obj, value, varargin) obj.Proxy.add(value,attrkeys,attrvals); else - attrkeys = [varargin{1:2:(nargin-2)}]'; - attrvals = [varargin(2:2:(nargin-2))]'; + attrkeys = [varargin{1:2:length(varargin)}]'; + attrvals = [varargin(2:2:length(varargin))]'; obj.Proxy.add(value,attrkeys,attrvals); end end From c44d0e574b53cec9a0a7bcc3e5058ac6b3e53456 Mon Sep 17 00:00:00 2001 From: Rick Tu Date: Thu, 7 Sep 2023 11:18:48 -0400 Subject: [PATCH 17/17] fix: attributes and bucket tests incorporate feedback from PR#13 for tmetrics --- test/tmetrics.m | 81 +++++++++++++++++++++++++++++-------------------- 1 file changed, 48 insertions(+), 33 deletions(-) diff --git a/test/tmetrics.m b/test/tmetrics.m index f28db40..c452504 100644 --- a/test/tmetrics.m +++ b/test/tmetrics.m @@ -89,15 +89,9 @@ function testCounterAddAttributes(testCase) mt = p.getMeter(metername); ct = mt.createCounter(countername); - % verify MATLAB object properties - verifyEqual(testCase, mt.Name, metername); - verifyEqual(testCase, mt.Version, ""); - verifyEqual(testCase, mt.Schema, ""); - verifyEqual(testCase, ct.Name, countername); - % create testing value and dictionary dict = dictionary("k1","v1","k2",5); - vals = [1,2,3]; + vals = [1,2.4,3]; dict_keys = keys(dict); dict_vals = values(dict); @@ -124,10 +118,13 @@ function testCounterAddAttributes(testCase) verifyEqual(testCase, dp.asDouble, sum(vals)); % verify counter attributes - verifyEqual(testCase, string(dp.attributes(1).key), dict_keys(1)); - verifyEqual(testCase, string(dp.attributes(1).value.stringValue), dict_vals(1)); - verifyEqual(testCase, string(dp.attributes(2).key), dict_keys(2)); - verifyEqual(testCase, string(dp.attributes(2).value.stringValue), dict_vals(2)); + resourcekeys = string({dp.attributes.key}); + idx1 = find(resourcekeys == dict_keys(1)); + idx2 = find(resourcekeys == dict_keys(2)); + verifyEqual(testCase, string(dp.attributes(idx1).key), dict_keys(1)); + verifyEqual(testCase, string(dp.attributes(idx1).value.stringValue), dict_vals(1)); + verifyEqual(testCase, string(dp.attributes(idx2).key), dict_keys(2)); + verifyEqual(testCase, string(dp.attributes(idx2).value.stringValue), dict_vals(2)); end @@ -174,7 +171,7 @@ function testUpDownCounterBasic(testCase) verifyEqual(testCase, ct.Name, countername); % create testing value - val = 10; + val = -10; % add value and attributes ct.add(val); @@ -209,15 +206,9 @@ function testUpDownCounterAddAttributes(testCase) mt = p.getMeter(metername); ct = mt.createUpDownCounter(countername); - % verify MATLAB object properties - verifyEqual(testCase, mt.Name, metername); - verifyEqual(testCase, mt.Version, ""); - verifyEqual(testCase, mt.Schema, ""); - verifyEqual(testCase, ct.Name, countername); - % create testing value and dictionary dict = dictionary("k1","v1","k2",5); - vals = [2,-1,3]; + vals = [2,-1.9,3]; dict_keys = keys(dict); dict_vals = values(dict); @@ -244,10 +235,13 @@ function testUpDownCounterAddAttributes(testCase) verifyEqual(testCase, dp.asDouble, sum(vals)); % verify counter attributes - verifyEqual(testCase, string(dp.attributes(1).key), dict_keys(1)); - verifyEqual(testCase, string(dp.attributes(1).value.stringValue), dict_vals(1)); - verifyEqual(testCase, string(dp.attributes(2).key), dict_keys(2)); - verifyEqual(testCase, string(dp.attributes(2).value.stringValue), dict_vals(2)); + resourcekeys = string({dp.attributes.key}); + idx1 = find(resourcekeys == dict_keys(1)); + idx2 = find(resourcekeys == dict_keys(2)); + verifyEqual(testCase, string(dp.attributes(idx1).key), dict_keys(1)); + verifyEqual(testCase, string(dp.attributes(idx1).value.stringValue), dict_vals(1)); + verifyEqual(testCase, string(dp.attributes(idx2).key), dict_keys(2)); + verifyEqual(testCase, string(dp.attributes(idx2).value.stringValue), dict_vals(2)); end @@ -262,6 +256,12 @@ function testHistogramBasic(testCase) mt = p.getMeter(metername); hist = mt.createHistogram(histname); + % verify MATLAB object properties + verifyEqual(testCase, mt.Name, metername); + verifyEqual(testCase, mt.Version, ""); + verifyEqual(testCase, mt.Schema, ""); + verifyEqual(testCase, hist.Name, histname); + % create value for histogram val = 1; @@ -278,16 +278,25 @@ function testHistogramBasic(testCase) bounds = dp.explicitBounds; counts = dp.bucketCounts; + % verify meter and histogram names + verifyEqual(testCase, string(results.resourceMetrics.scopeMetrics.metrics.name), histname); + verifyEqual(testCase, string(results.resourceMetrics.scopeMetrics.scope.name), metername); + % verify statistics verifyEqual(testCase, dp.min, val); verifyEqual(testCase, dp.max, val); verifyEqual(testCase, dp.sum, val); % verify count in bucket - lower = bounds(1); - upper = bounds(2); - expect_count = sum(val>lower & val<=upper); - verifyEqual(testCase, str2double(counts{2}), expect_count); + len = length(counts); + verifyEqual(testCase, str2double(counts{1}), sum(val<=bounds(1))); + for i = 2:(len-1) + lower = bounds(i-1); + upper = bounds(i); + expect_count = sum(val>lower & val<=upper); + verifyEqual(testCase, str2double(counts{i}), expect_count); + end + verifyEqual(testCase, str2double(counts{len}), sum(val>bounds(len-1))); end @@ -304,7 +313,7 @@ function testHistogramRecordAttributes(testCase) % create value and attributes for histogram dict = dictionary("k1","v1","k2","v2"); - vals = [1,5,10]; + vals = [1,5,8.1]; dict_keys = keys(dict); dict_vals = values(dict); @@ -329,18 +338,24 @@ function testHistogramRecordAttributes(testCase) verifyEqual(testCase, dp.sum, sum(vals)); % verify attributes - verifyEqual(testCase, string(dp.attributes(1).key), dict_keys(1)); - verifyEqual(testCase, string(dp.attributes(1).value.stringValue), dict_vals(1)); - verifyEqual(testCase, string(dp.attributes(2).key), dict_keys(2)); - verifyEqual(testCase, string(dp.attributes(2).value.stringValue), dict_vals(2)); + resourcekeys = string({dp.attributes.key}); + idx1 = find(resourcekeys == dict_keys(1)); + idx2 = find(resourcekeys == dict_keys(2)); + verifyEqual(testCase, string(dp.attributes(idx1).key), dict_keys(1)); + verifyEqual(testCase, string(dp.attributes(idx1).value.stringValue), dict_vals(1)); + verifyEqual(testCase, string(dp.attributes(idx2).key), dict_keys(2)); + verifyEqual(testCase, string(dp.attributes(idx2).value.stringValue), dict_vals(2)); % verify count in bucket - for i = 2:(length(counts)-1) + len = length(counts); + verifyEqual(testCase, str2double(counts{1}), sum(vals<=bounds(1))); + for i = 2:(len-1) lower = bounds(i-1); upper = bounds(i); expect_count = sum(vals>lower & vals<=upper); verifyEqual(testCase, str2double(counts{i}), expect_count); end + verifyEqual(testCase, str2double(counts{len}), sum(vals>bounds(len-1))); end