diff --git a/CMakeLists.txt b/CMakeLists.txt index ce462a5..402c979 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -231,6 +231,7 @@ set(OPENTELEMETRY_PROXY_SOURCES ${TRACE_SDK_SOURCE_DIR}/BatchSpanProcessorProxy.cpp ${TRACE_SDK_SOURCE_DIR}/ParentBasedSamplerProxy.cpp ${METRICS_SDK_SOURCE_DIR}/MeterProviderProxy.cpp + ${METRICS_SDK_SOURCE_DIR}/ViewProxy.cpp ${METRICS_SDK_SOURCE_DIR}/PeriodicExportingMetricReaderProxy.cpp ${COMMON_SDK_SOURCE_DIR}/resource.cpp) if(WITH_OTLP_HTTP) diff --git a/OtelMatlabProxyFactory.cpp b/OtelMatlabProxyFactory.cpp index 8b04cf7..15b023b 100644 --- a/OtelMatlabProxyFactory.cpp +++ b/OtelMatlabProxyFactory.cpp @@ -23,6 +23,7 @@ #include "opentelemetry-matlab/sdk/trace/TraceIdRatioBasedSamplerProxy.h" #include "opentelemetry-matlab/sdk/trace/ParentBasedSamplerProxy.h" #include "opentelemetry-matlab/sdk/metrics/MeterProviderProxy.h" +#include "opentelemetry-matlab/sdk/metrics/ViewProxy.h" #include "opentelemetry-matlab/sdk/metrics/PeriodicExportingMetricReaderProxy.h" #ifdef WITH_OTLP_HTTP #include "opentelemetry-matlab/exporters/otlp/OtlpHttpSpanExporterProxy.h" @@ -61,6 +62,7 @@ OtelMatlabProxyFactory::make_proxy(const libmexclass::proxy::ClassName& class_na REGISTER_PROXY(libmexclass.opentelemetry.sdk.ParentBasedSamplerProxy, libmexclass::opentelemetry::sdk::ParentBasedSamplerProxy); REGISTER_PROXY(libmexclass.opentelemetry.sdk.MeterProviderProxy, libmexclass::opentelemetry::sdk::MeterProviderProxy); + REGISTER_PROXY(libmexclass.opentelemetry.sdk.ViewProxy, libmexclass::opentelemetry::sdk::ViewProxy); REGISTER_PROXY(libmexclass.opentelemetry.sdk.PeriodicExportingMetricReaderProxy, libmexclass::opentelemetry::sdk::PeriodicExportingMetricReaderProxy); #ifdef WITH_OTLP_HTTP diff --git a/sdk/metrics/+opentelemetry/+sdk/+metrics/MeterProvider.m b/sdk/metrics/+opentelemetry/+sdk/+metrics/MeterProvider.m index 7c5ce87..268802d 100644 --- a/sdk/metrics/+opentelemetry/+sdk/+metrics/MeterProvider.m +++ b/sdk/metrics/+opentelemetry/+sdk/+metrics/MeterProvider.m @@ -10,6 +10,7 @@ properties (Access=public) MetricReader + View Resource end @@ -98,6 +99,15 @@ function addMetricReader(obj, reader) obj.MetricReader = [obj.MetricReader, reader]; end + function addView(obj, view) + arguments + obj + view (1,1) {mustBeA(view, "opentelemetry.sdk.metrics.View")} + end + obj.Proxy.addView(view.Proxy.ID); + obj.View = [obj.View, view]; + end + function success = shutdown(obj) % SHUTDOWN Shutdown % SUCCESS = SHUTDOWN(MP) shuts down all metric readers associated with meter provider MP diff --git a/sdk/metrics/+opentelemetry/+sdk/+metrics/View.m b/sdk/metrics/+opentelemetry/+sdk/+metrics/View.m new file mode 100644 index 0000000..2ddf70b --- /dev/null +++ b/sdk/metrics/+opentelemetry/+sdk/+metrics/View.m @@ -0,0 +1,48 @@ +classdef View + +% Copyright 2023 The MathWorks, Inc. + + properties (GetAccess={?opentelemetry.sdk.metrics.MeterProvider}) + Proxy % Proxy object to interface C++ code + end + + properties (SetAccess=immutable) + Name + Description + Unit + InstrumentName + InstrumentType + MeterName + MeterVersion + MeterSchemaURL + AttributeKeys + Aggregation + HistogramBinEdges + end + + methods + function obj = View(name, description, unit, instrumentName, instrumentType, ... + meterName, meterVersion, meterSchemaURL, attributeKeys, ... + aggregation, histogramBinEdges, varargin) + + instrumentTypeCategory = int32(find(instrumentType==["kCounter", "kHistogram", "kUpDownCounter", "kObservableCounter", "kObservableGauge", "kObservableUpDownCounter"])-1); + + aggregationCategory = int32(find(instrumentType==["kDrop", "kHistogram", "kLastValue", "kSum", "kDefault"])-1); + + obj.Proxy = libmexclass.proxy.Proxy("Name", "libmexclass.opentelemetry.sdk.ViewProxy", ... + "ConstructorArguments", {name, description, unit, instrumentName, ... + instrumentTypeCategory, meterName, meterVersion, meterSchemaURL, ... + attributeKeys, aggregationCategory, histogramBinEdges, varargin}); + obj.Description = description; + obj.Unit = unit; + obj.InstrumentName = instrumentName; + obj.InstrumentType = instrumentType; + obj.MeterName = meterName; + obj.MeterVersion = meterVersion; + obj.MeterSchemaURL = meterSchemaURL; + obj.AttributeKeys = attributeKeys; + obj.Aggregation = aggregation; + obj.HistogramBinEdges = histogramBinEdges; + end + end +end \ No newline at end of file diff --git a/sdk/metrics/include/opentelemetry-matlab/sdk/metrics/MeterProviderProxy.h b/sdk/metrics/include/opentelemetry-matlab/sdk/metrics/MeterProviderProxy.h index 8d6d144..a017c94 100644 --- a/sdk/metrics/include/opentelemetry-matlab/sdk/metrics/MeterProviderProxy.h +++ b/sdk/metrics/include/opentelemetry-matlab/sdk/metrics/MeterProviderProxy.h @@ -42,6 +42,7 @@ class MeterProviderProxy : public libmexclass::opentelemetry::MeterProviderProxy public: MeterProviderProxy(nostd::shared_ptr mp) : libmexclass::opentelemetry::MeterProviderProxy(mp) { REGISTER_METHOD(MeterProviderProxy, addMetricReader); + REGISTER_METHOD(MeterProviderProxy, addView); REGISTER_METHOD(MeterProviderProxy, shutdown); REGISTER_METHOD(MeterProviderProxy, forceFlush); } @@ -50,6 +51,8 @@ class MeterProviderProxy : public libmexclass::opentelemetry::MeterProviderProxy void addMetricReader(libmexclass::proxy::method::Context& context); + void addView(libmexclass::proxy::method::Context& context); + void shutdown(libmexclass::proxy::method::Context& context); void forceFlush(libmexclass::proxy::method::Context& context); diff --git a/sdk/metrics/include/opentelemetry-matlab/sdk/metrics/ViewProxy.h b/sdk/metrics/include/opentelemetry-matlab/sdk/metrics/ViewProxy.h new file mode 100644 index 0000000..1bf18b6 --- /dev/null +++ b/sdk/metrics/include/opentelemetry-matlab/sdk/metrics/ViewProxy.h @@ -0,0 +1,50 @@ +// Copyright 2023 The MathWorks, Inc. + +#pragma once + +#include "libmexclass/proxy/Proxy.h" +#include "libmexclass/proxy/method/Context.h" + +#include "libmexclass/proxy/ProxyManager.h" + +#include "opentelemetry/sdk/metrics/view/view.h" +#include "opentelemetry/sdk/metrics/view/view_factory.h" +#include "opentelemetry/sdk/metrics/instruments.h" +#include "opentelemetry/sdk/metrics/aggregation/aggregation.h" +#include "opentelemetry/sdk/metrics/aggregation/aggregation_config.h" +#include "opentelemetry/sdk/metrics/view/attributes_processor.h" +#include "opentelemetry/sdk/metrics/view/instrument_selector.h" +#include "opentelemetry/sdk/metrics/view/instrument_selector_factory.h" +#include "opentelemetry/nostd/string_view.h" +#include "opentelemetry/sdk/metrics/view/meter_selector.h" +#include "opentelemetry/sdk/metrics/view/meter_selector_factory.h" + + +#include "opentelemetry-matlab/sdk/metrics/ViewProxy.h" + +namespace metrics_sdk = opentelemetry::sdk::metrics; +namespace nostd = opentelemetry::nostd; + +namespace libmexclass::opentelemetry::sdk { +class ViewProxy : public libmexclass::proxy::Proxy { +public: + ViewProxy(std::unique_ptr view, std::unique_ptr instrumentSelector, std::unique_ptr meterSelector); + + static libmexclass::proxy::MakeResult make(const libmexclass::proxy::FunctionArguments& constructor_arguments); + + // void processView(libmexclass::proxy::method::Context& context); + + std::unique_ptr getView(libmexclass::proxy::method::Context& context); + + std::unique_ptr getInstrumentSelector(libmexclass::proxy::method::Context& context); + + std::unique_ptr getMeterSelector(libmexclass::proxy::method::Context& context); + +private: + std::unique_ptr View; + + std::unique_ptr InstrumentSelector; + + std::unique_ptr MeterSelector; +}; +} diff --git a/sdk/metrics/src/MeterProviderProxy.cpp b/sdk/metrics/src/MeterProviderProxy.cpp index b70706d..df2b535 100644 --- a/sdk/metrics/src/MeterProviderProxy.cpp +++ b/sdk/metrics/src/MeterProviderProxy.cpp @@ -2,6 +2,7 @@ #include "opentelemetry-matlab/sdk/metrics/MeterProviderProxy.h" #include "opentelemetry-matlab/sdk/metrics/PeriodicExportingMetricReaderProxy.h" +#include "opentelemetry-matlab/sdk/metrics/ViewProxy.h" #include "libmexclass/proxy/ProxyManager.h" @@ -58,6 +59,17 @@ void MeterProviderProxy::addMetricReader(libmexclass::proxy::method::Context& co return; } +void MeterProviderProxy::addView(libmexclass::proxy::method::Context& context) { + matlab::data::TypedArray viewid_mda = context.inputs[0]; + libmexclass::proxy::ID viewid = viewid_mda[0]; + + static_cast(*CppMeterProvider).AddView( + std::static_pointer_cast(libmexclass::proxy::ProxyManager::getProxy(viewid))->getInstrumentSelector(context), + std::static_pointer_cast(libmexclass::proxy::ProxyManager::getProxy(viewid))->getMeterSelector(context), + std::static_pointer_cast(libmexclass::proxy::ProxyManager::getProxy(viewid))->getView(context)); + return; +} + void MeterProviderProxy::shutdown(libmexclass::proxy::method::Context& context) { matlab::data::ArrayFactory factory; auto result_mda = factory.createScalar(static_cast(*CppMeterProvider).Shutdown()); diff --git a/sdk/metrics/src/ViewProxy.cpp b/sdk/metrics/src/ViewProxy.cpp new file mode 100644 index 0000000..0b80b17 --- /dev/null +++ b/sdk/metrics/src/ViewProxy.cpp @@ -0,0 +1,114 @@ +// Copyright 2023 The MathWorks, Inc. + +#include "opentelemetry-matlab/sdk/metrics/ViewProxy.h" + +#include "libmexclass/proxy/ProxyManager.h" + +#include + +namespace libmexclass::opentelemetry::sdk { +ViewProxy::ViewProxy(std::unique_ptr view, std::unique_ptr instrumentSelector, std::unique_ptr meterSelector){ + View = std::move(view); + InstrumentSelector = std::move(instrumentSelector); + MeterSelector = std::move(meterSelector); + REGISTER_METHOD(ViewProxy, getView); + REGISTER_METHOD(ViewProxy, getInstrumentSelector); + REGISTER_METHOD(ViewProxy, getMeterSelector); +} + +libmexclass::proxy::MakeResult ViewProxy::make(const libmexclass::proxy::FunctionArguments& constructor_arguments) { + libmexclass::proxy::MakeResult out; + + //Create View + matlab::data::StringArray name_mda = constructor_arguments[0]; + auto name = name_mda[0]; + + matlab::data::StringArray description_mda = constructor_arguments[1]; + auto description = description_mda[0]; + + matlab::data::StringArray unit_mda = constructor_arguments[2]; + auto unit = unit_mda[0]; + + matlab::data::TypedArray aggregation_type_mda = constructor_arguments[9]; + auto aggregation_type = static_cast(static_cast(aggregation_type_mda[0])); + + std::shared_ptr aggregation_config = std::shared_ptr(new metrics_sdk::HistogramAggregationConfig()); + if(aggregation_type == metrics_sdk::AggregationType::kHistogram){ + matlab::data::TypedArray histogramBinEdges_mda = constructor_arguments[10]; + std::vector histogramBinEdges; + for (auto h : histogramBinEdges_mda) { + histogramBinEdges.push_back(h); + } + aggregation_config->boundaries_ = histogramBinEdges; + } + + std::unique_ptr attributes_processor; + matlab::data::StringArray attributes_mda = constructor_arguments[8]; + if(attributes_mda.getNumberOfElements()==0){ + attributes_processor = std::unique_ptr(new metrics_sdk::DefaultAttributesProcessor()); + }else{ + std::unordered_map allowed_attribute_keys; + for (auto a : attributes_mda) { + allowed_attribute_keys[a] = true; + } + attributes_processor = std::unique_ptr(new metrics_sdk::FilteringAttributesProcessor(allowed_attribute_keys)); + } + + auto view = metrics_sdk::ViewFactory::Create(name, description, + unit, aggregation_type, std::move(aggregation_config), std::move(attributes_processor)); + + // Create Instrument Selector + matlab::data::TypedArray instrument_type_mda = constructor_arguments[4]; + auto instrument_type = static_cast(static_cast(instrument_type_mda[0])); + + matlab::data::StringArray instrument_name_mda = constructor_arguments[3]; + auto instrument_name = static_cast(instrument_name_mda[0]); + auto instrument_name_view = nostd::string_view(instrument_name); + + auto unit_view = nostd::string_view(static_cast(unit)); + + auto instrumentSelector = metrics_sdk::InstrumentSelectorFactory::Create(instrument_type, + instrument_name, unit_view); + + + // Create Meter Selector + matlab::data::StringArray meter_name_mda = constructor_arguments[5]; + auto meter_name = static_cast(meter_name_mda[0]); + auto meter_name_view = nostd::string_view(meter_name); + + matlab::data::StringArray meter_version_mda = constructor_arguments[6]; + auto meter_version = static_cast(meter_version_mda[0]); + auto meter_version_view = nostd::string_view(meter_version); + + matlab::data::StringArray meter_schema_mda = constructor_arguments[7]; + auto meter_schema = static_cast(meter_schema_mda[0]); + auto meter_schema_view = nostd::string_view(meter_schema); + + auto meterSelector = metrics_sdk::MeterSelectorFactory::Create(meter_name_view, + meter_version_view, meter_schema_view); + + + + // out = std::make_shared(nostd::shared_ptr( + // std::move(metrics_sdk::ViewFactory::Create(name, description, + // unit, aggregation_type, std::move(aggregation_config), std::move(attributes_processor))))); + + + // return out; + + return std::make_shared(std::move(view), std::move(instrumentSelector), std::move(meterSelector)); +} + +std::unique_ptr ViewProxy::getView(libmexclass::proxy::method::Context& context){ + return std::move(View); +} + +std::unique_ptr ViewProxy::getInstrumentSelector(libmexclass::proxy::method::Context& context){ + return std::move(InstrumentSelector); +} + +std::unique_ptr ViewProxy::getMeterSelector(libmexclass::proxy::method::Context& context){ + return std::move(MeterSelector); +} + +} diff --git a/test/tmetrics_sdk.m b/test/tmetrics_sdk.m index 9a6a9fa..ea743a0 100644 --- a/test/tmetrics_sdk.m +++ b/test/tmetrics_sdk.m @@ -146,6 +146,66 @@ function testCustomResource(testCase) end end + % function testViewCounter(testCase) + % % testCustomResource: check custom resources are included in + % % emitted metrics + % commonSetup(testCase) + % + % exporter = opentelemetry.exporters.otlp.OtlpHttpMetricExporter(); + % reader = opentelemetry.sdk.metrics.PeriodicExportingMetricReader(exporter, ... + % "Interval", seconds(2), "Timeout", seconds(1)); + % mp = opentelemetry.sdk.metrics.MeterProvider(reader); + % + % m = getMeter(mp, "mymeter"); + % c = createCounter(m, "mycounter"); + % + % % create testing value + % val = 10; + % + % % add value and attributes + % c.add(val); + % + % pause(2.5); + % + % view = opentelemetry.sdk.metrics.View("View", "my View", "Unit", "Instrument", "kCounter", "mymeter", "", "", ["One" "Two" "Three"], "kDrop", [0 100 200 300 400 500]); + % + % addView(mp, view); + % + % clear mp; + % + % % % TODO: add test comparisons + % end + + % function testViewHistogram(testCase) + % % testCustomResource: check custom resources are included in + % % emitted metrics + % commonSetup(testCase) + % + % exporter = opentelemetry.exporters.otlp.OtlpHttpMetricExporter(); + % reader = opentelemetry.sdk.metrics.PeriodicExportingMetricReader(exporter, ... + % "Interval", seconds(2), "Timeout", seconds(1)); + % mp = opentelemetry.sdk.metrics.MeterProvider(reader); + % m = mp.getMeter("mymeter"); + % hist = m.createHistogram("histogram"); + % + % % create value for histogram + % val = 1; + % + % % record value + % hist.record(val); + % + % % wait for collector response + % pause(2.5); + % + % view = opentelemetry.sdk.metrics.View("View", "my View", "Unit", "Instrument", "kHistogram", "mymeter", "", "", ["One" "Two" "Three"], "kHistogram", [0 100 200 300 400 500]); + % + % addView(mp, view); + % + % clear mp; + % + % % % TODO: add test comparisons + % end + function testShutdown(testCase) % testShutdown: shutdown method should stop exporting % of metrics