Skip to content

Synchronous gauge #183

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,9 @@ if(NOT DEFINED OTEL_CPP_INSTALLED_DIR)

set(OTEL_CPP_CXX_STANDARD 14)

# The synchronous gauge metric instrument is only defined in ABI version 2
set(OTEL_CPP_ABI_VERSION OPENTELEMETRY_ABI_VERSION_NO=2)

set(PATCHES_DIR ${CMAKE_SOURCE_DIR}/patches)
if(SKIP_OTEL_CPP_PATCH)
set(patch_comand "")
Expand All @@ -209,14 +212,16 @@ if(NOT DEFINED OTEL_CPP_INSTALLED_DIR)
set(patch_command "")
endif()

# Note: examples are temporarily turned off (-DWITH_EXAMPLES=OFF) due to a build issue that is now fixed in #3284
# Renable examples after pulling in the fix
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 -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DWITH_OTLP_HTTP=${WITH_OTLP_HTTP} -DWITH_OTLP_GRPC=${WITH_OTLP_GRPC} -DWITH_OTLP_FILE=${WITH_OTLP_FILE} -DBUILD_TESTING=OFF -DWITH_BENCHMARK=OFF -DOPENTELEMETRY_INSTALL=ON -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} -DCMAKE_CXX_STANDARD=${OTEL_CPP_CXX_STANDARD} -DVCPKG_INSTALLED_DIR=${VCPKG_INSTALLED_DIR} ${TRIPLET_DEFINITIONS}
CMAKE_ARGS -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DWITH_ABI_VERSION_1=OFF -DWITH_ABI_VERSION_2=ON -DWITH_OTLP_HTTP=${WITH_OTLP_HTTP} -DWITH_OTLP_GRPC=${WITH_OTLP_GRPC} -DWITH_OTLP_FILE=${WITH_OTLP_FILE} -DWITH_EXAMPLES=OFF -DBUILD_TESTING=OFF -DWITH_BENCHMARK=OFF -DOPENTELEMETRY_INSTALL=ON -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} -DCMAKE_CXX_STANDARD=${OTEL_CPP_CXX_STANDARD} -DVCPKG_INSTALLED_DIR=${VCPKG_INSTALLED_DIR} ${TRIPLET_DEFINITIONS}
BUILD_BYPRODUCTS ${OTEL_CPP_LIBRARIES}
INSTALL_DIR ${OTEL_CPP_PREFIX}
INSTALL_COMMAND ${CMAKE_COMMAND} --install . --prefix ${OTEL_CPP_PREFIX} --config $<CONFIG>
Expand Down Expand Up @@ -291,6 +296,7 @@ set(OPENTELEMETRY_PROXY_SOURCES
${METRICS_API_SOURCE_DIR}/CounterProxy.cpp
${METRICS_API_SOURCE_DIR}/UpDownCounterProxy.cpp
${METRICS_API_SOURCE_DIR}/HistogramProxy.cpp
${METRICS_API_SOURCE_DIR}/GaugeProxy.cpp
${METRICS_API_SOURCE_DIR}/SynchronousInstrumentProxyFactory.cpp
${METRICS_API_SOURCE_DIR}/MeasurementFetcher.cpp
${METRICS_API_SOURCE_DIR}/AsynchronousInstrumentProxy.cpp
Expand Down Expand Up @@ -365,6 +371,8 @@ if(WITH_OTLP_FILE)
target_compile_definitions(${OPENTELEMETRY_PROXY_LIBRARY_NAME} PRIVATE WITH_OTLP_FILE)
endif()

target_compile_definitions(${OPENTELEMETRY_PROXY_LIBRARY_NAME} PRIVATE ${OTEL_CPP_ABI_VERSION})

# pass in version number
target_compile_definitions(${OPENTELEMETRY_PROXY_LIBRARY_NAME} PRIVATE OTEL_MATLAB_VERSION="${OTEL_MATLAB_VERSION}")
if(WIN32)
Expand Down
28 changes: 28 additions & 0 deletions api/metrics/+opentelemetry/+metrics/Gauge.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
classdef Gauge < opentelemetry.metrics.SynchronousInstrument
% Gauge is an instrument for recording non-aggregatable measurements.

% Copyright 2025 The MathWorks, Inc.

methods (Access={?opentelemetry.metrics.Meter})
function obj = Gauge(proxy, name, description, unit)
% Private constructor. Use createGauge method of Meter
% to create gauges.
[email protected](proxy, name, description, unit);
end
end

methods
function record(obj, value, varargin)
% RECORD Record a value
% RECORD(G, VALUE) records a scalar numeric value. VALUE can be positive or negative.
%
% RECORD(G, VALUE, ATTRIBUTES) also specifies attributes as a
% dictionary
%
% RECORD(G, VALUE, ATTRNAME1, ATTRVALUE1, ATTRNAME2,
% ATTRVALUE2, ...) specifies attributes as trailing
% name-value pairs.
obj.processValue(value, varargin{:});
end
end
end
38 changes: 32 additions & 6 deletions api/metrics/+opentelemetry/+metrics/Meter.m
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
% A Meter creates metric instruments, capturing measurements about a service at runtime.
% Meters are created from Meter Providers.

% Copyright 2023-2024 The MathWorks, Inc.
% Copyright 2023-2025 The MathWorks, Inc.

properties (SetAccess=immutable)
Name (1,1) string % Meter name
Expand Down Expand Up @@ -38,7 +38,7 @@
% C = CREATECOUNTER(M, NAME, DESCRIPTION, UNIT) also
% specifies a description and a unit.
%
% See also CREATEUPDOWNCOUNTER, CREATEHISTOGRAM,
% See also CREATEUPDOWNCOUNTER, CREATEHISTOGRAM, CREATEGAUGE,
% CREATEOBSERVABLECOUNTER
arguments
obj
Expand All @@ -64,7 +64,7 @@
% C = CREATEUPDOWNCOUNTER(M, NAME, DESCRIPTION, UNIT) also
% specifies a description and a unit.
%
% See also CREATECOUNTER, CREATEHISTOGRAM,
% See also CREATECOUNTER, CREATEHISTOGRAM, CREATEGAUGE,
% CREATEOBSERVABLEUPDOWNCOUNTER
arguments
obj
Expand All @@ -91,14 +91,14 @@
% H = CREATEHISTOGRAM(M, NAME, DESCRIPTION, UNIT) also
% specifies a description and a unit.
%
% See also CREATECOUNTER, CREATEUPDOWNCOUNTER,
% See also CREATECOUNTER, CREATEUPDOWNCOUNTER, CREATEGAUGE,
% OPENTELEMETRY.SDK.METRICS.VIEW
arguments
obj
name
description = ""
unit = ""
end
end

[name, description, unit] = processSynchronousInputs(name, ...
description, unit);
Expand All @@ -108,6 +108,32 @@
histogram = opentelemetry.metrics.Histogram(HistogramProxy, name, description, unit);
end

function gauge = createGauge(obj, name, description, unit)
% CREATEGAUGE Create a gauge
% G = CREATEGAUGE(M, NAME) creates a gauge
% with the specified name. A gauge's value can increase or
% decrease but it should never be summed in aggregation.
%
% G = CREATEGAUGE(M, NAME, DESCRIPTION, UNIT) also
% specifies a description and a unit.
%
% See also CREATECOUNTER, CREATEUPDOWNCOUNTER, CREATEHISTOGRAM,
% CREATEOBSERVABLEGAUGE
arguments
obj
name
description = ""
unit = ""
end

[name, description, unit] = processSynchronousInputs(name, ...
description, unit);
id = obj.Proxy.createGauge(name, description, unit);
GaugeProxy = libmexclass.proxy.Proxy("Name", ...
"libmexclass.opentelemetry.GaugeProxy", "ID", id);
gauge = opentelemetry.metrics.Gauge(GaugeProxy, name, description, unit);
end

function obscounter = createObservableCounter(obj, callback, name, ...
description, unit, timeout)
% CREATEOBSERVABLECOUNTER Create an observable counter
Expand Down Expand Up @@ -205,7 +231,7 @@
% positive duration scalar.
%
% See also OPENTELEMETRY.METRICS.OBSERVABLERESULT,
% CREATEOBSERVABLECOUNTER, CREATEOBSERVABLEUPDOWNCOUNTER
% CREATEGAUGE, CREATEOBSERVABLECOUNTER, CREATEOBSERVABLEUPDOWNCOUNTER
arguments
obj
callback
Expand Down
33 changes: 33 additions & 0 deletions api/metrics/include/opentelemetry-matlab/metrics/GaugeProxy.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright 2025 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 GaugeProxy : public libmexclass::proxy::Proxy {
public:
GaugeProxy(nostd::shared_ptr<metrics_api::Gauge<double> > g) : CppGauge(g) {
REGISTER_METHOD(GaugeProxy, processValue);
}

void processValue(libmexclass::proxy::method::Context& context);

private:

nostd::shared_ptr<metrics_api::Gauge<double> > CppGauge;

};
} // namespace libmexclass::opentelemetry


Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2023-2024 The MathWorks, Inc.
// Copyright 2023-2025 The MathWorks, Inc.

#pragma once

Expand All @@ -8,6 +8,7 @@
#include "opentelemetry-matlab/metrics/CounterProxy.h"
#include "opentelemetry-matlab/metrics/HistogramProxy.h"
#include "opentelemetry-matlab/metrics/UpDownCounterProxy.h"
#include "opentelemetry-matlab/metrics/GaugeProxy.h"
#include "opentelemetry-matlab/metrics/ObservableCounterProxy.h"
#include "opentelemetry-matlab/metrics/ObservableUpDownCounterProxy.h"
#include "opentelemetry-matlab/metrics/ObservableGaugeProxy.h"
Expand All @@ -27,6 +28,7 @@ class MeterProxy : public libmexclass::proxy::Proxy {
REGISTER_METHOD(MeterProxy, createCounter);
REGISTER_METHOD(MeterProxy, createUpDownCounter);
REGISTER_METHOD(MeterProxy, createHistogram);
REGISTER_METHOD(MeterProxy, createGauge);
REGISTER_METHOD(MeterProxy, createObservableCounter);
REGISTER_METHOD(MeterProxy, createObservableUpDownCounter);
REGISTER_METHOD(MeterProxy, createObservableGauge);
Expand All @@ -38,6 +40,8 @@ class MeterProxy : public libmexclass::proxy::Proxy {

void createHistogram(libmexclass::proxy::method::Context& context);

void createGauge(libmexclass::proxy::method::Context& context);

void createObservableCounter(libmexclass::proxy::method::Context& context);

void createObservableUpDownCounter(libmexclass::proxy::method::Context& context);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2023 The MathWorks, Inc.
// Copyright 2023-2025 The MathWorks, Inc.

#pragma once

Expand All @@ -11,7 +11,7 @@ namespace nostd = opentelemetry::nostd;

namespace libmexclass::opentelemetry {

enum class SynchronousInstrumentType {Counter, UpDownCounter, Histogram};
enum class SynchronousInstrumentType {Counter, UpDownCounter, Histogram, Gauge};

class SynchronousInstrumentProxyFactory {
public:
Expand Down
36 changes: 36 additions & 0 deletions api/metrics/src/GaugeProxy.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright 2025 The MathWorks, Inc.

#include "opentelemetry-matlab/metrics/GaugeProxy.h"

#include "MatlabDataArray.hpp"

namespace libmexclass::opentelemetry {


void GaugeProxy::processValue(libmexclass::proxy::method::Context& context){

matlab::data::Array value_mda = context.inputs[0];
double value = static_cast<double>(value_mda[0]);
size_t nin = context.inputs.getNumberOfElements();
if (nin == 1){
CppGauge->Record(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<std::string>(attrnames_mda[i]);
matlab::data::Array attrvalue = attrvalues_mda[i];
processAttribute(attrname, attrvalue, attrs);
}
CppGauge->Record(value, attrs.Attributes);
}

}



} // namespace libmexclass::opentelemetry
6 changes: 5 additions & 1 deletion api/metrics/src/MeterProxy.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2023-2024 The MathWorks, Inc.
// Copyright 2023-2025 The MathWorks, Inc.

#include "opentelemetry-matlab/metrics/MeterProxy.h"
#include "opentelemetry-matlab/metrics/MeasurementFetcher.h"
Expand Down Expand Up @@ -46,6 +46,10 @@ void MeterProxy::createHistogram(libmexclass::proxy::method::Context& context) {
createSynchronous(context, SynchronousInstrumentType::Histogram);
}

void MeterProxy::createGauge(libmexclass::proxy::method::Context& context) {
createSynchronous(context, SynchronousInstrumentType::Gauge);
}

void MeterProxy::createAsynchronous(libmexclass::proxy::method::Context& context, AsynchronousInstrumentType type) {
// Always assumes 4 inputs
matlab::data::StringArray name_mda = context.inputs[0];
Expand Down
9 changes: 8 additions & 1 deletion api/metrics/src/SynchronousInstrumentProxyFactory.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
// Copyright 2023 The MathWorks, Inc.
// Copyright 2023-2025 The MathWorks, Inc.

#include "opentelemetry-matlab/metrics/SynchronousInstrumentProxyFactory.h"
#include "opentelemetry-matlab/metrics/CounterProxy.h"
#include "opentelemetry-matlab/metrics/HistogramProxy.h"
#include "opentelemetry-matlab/metrics/UpDownCounterProxy.h"
#include "opentelemetry-matlab/metrics/GaugeProxy.h"


namespace libmexclass::opentelemetry {
Expand All @@ -29,6 +30,12 @@ std::shared_ptr<libmexclass::proxy::Proxy> SynchronousInstrumentProxyFactory::cr
proxy = std::shared_ptr<libmexclass::proxy::Proxy>(new HistogramProxy(hist));
}
break;
case SynchronousInstrumentType::Gauge:
{
nostd::shared_ptr<metrics_api::Gauge<double> > g = std::move(CppMeter->CreateDoubleGauge(name, description, unit));
proxy = std::shared_ptr<libmexclass::proxy::Proxy>(new GaugeProxy(g));
}
break;
}
return proxy;
}
Expand Down
2 changes: 2 additions & 0 deletions examples/context_propagation/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ if(NOT DEFINED OTEL_CPP_INSTALLED_DIR)
add_dependencies(${CONTEXTPROP_EXAMPLE_CPP_TARGET} ${OTEL_CPP_PROJECT_NAME})
endif()

# Specify the ABI version, include directories, and libraries of otel-cpp. The C++ code in this example directly calls otel-cpp functions.
target_compile_definitions(${CONTEXTPROP_EXAMPLE_CPP_TARGET} PRIVATE ${OTEL_CPP_ABI_VERSION})
target_include_directories(${CONTEXTPROP_EXAMPLE_CPP_TARGET} PRIVATE ${OTEL_CPP_PREFIX}/include)
target_link_libraries(${CONTEXTPROP_EXAMPLE_CPP_TARGET} PRIVATE ${OPENTELEMETRY_PROXY_LINK_LIBRARIES})
if(UNIX AND NOT APPLE AND NOT CYGWIN)
Expand Down
4 changes: 2 additions & 2 deletions examples/metrics/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
There are two examples in this directory, metrics\_example and async\_metrics\_example.

## metrics\_example
This example shows how to emit OpenTelemetry synchronous metrics from MATLAB. It uses all 3 synchronous instruments counter, updowncounter, and histogram.
This example shows how to emit OpenTelemetry synchronous metrics from MATLAB. It uses all 4 synchronous instruments counter, updowncounter, histogram, and gauge.
* At the beginning of the first run, initialization is necessary to create and store a global meter provider.
* The example then enters a loop and at each iteration updates all 3 instruments. The metrics will then be exported periodically at a fixed time interval.
* The example then enters a loop and at each iteration updates all 4 instruments. The metrics will then be exported periodically at a fixed time interval.

## async\_metrics\_example
This example shows how to emit OpenTelemetry asynchronous metrics from MATLAB. Is uses all 3 asynchronous instruments observable counter, observable
Expand Down
14 changes: 8 additions & 6 deletions examples/metrics/metrics_example.m
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
function metrics_example(iterations)
% This example creates 3 metric instruments including a counter, an
% updowncounter, and a histogram. It then enters a loop and updates the
% value of the instruments at each iteration.
% This example creates 4 metric instruments including a counter, an
% updowncounter, a histogram, and a gauge. It then enters a loop and updates
% the value of the instruments at each iteration.

% Copyright 2023-2024 The MathWorks, Inc.
% Copyright 2023-2025 The MathWorks, Inc.

if nargin < 1
iterations = 20; % default to 20 iterations
Expand All @@ -17,13 +17,15 @@ function metrics_example(iterations)
c = createCounter(m, "counter");
u = createUpDownCounter(m, "updowncounter");
h = createHistogram(m, "histogram");
g = createGauge(m, "gauge");

% wait a little before starting
pause(2);
for i = 1:iterations
c.add(randi(10));
u.add(randi([-10 10]));
c.add(randi(10)); % integer between 1 and 10
u.add(randi([-10 10])); % integer between -10 and 10
h.record(50 + 15*randn); % normal distribution with mean 50 and std 15
g.record(100*rand); % real number between 0 and 100
pause(5);
end

Expand Down
2 changes: 2 additions & 0 deletions examples/webread/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ if(NOT DEFINED OTEL_CPP_INSTALLED_DIR)
add_dependencies(${WEBREAD_EXAMPLE_TARGET} ${OTEL_CPP_PROJECT_NAME})
endif()

# Specify the ABI version, include directories, and libraries of otel-cpp. The C++ code in this example directly calls otel-cpp functions.
target_compile_definitions(${WEBREAD_EXAMPLE_TARGET} PRIVATE ${OTEL_CPP_ABI_VERSION})
target_include_directories(${WEBREAD_EXAMPLE_TARGET} PRIVATE ${OTEL_CPP_PREFIX}/include)
target_link_libraries(${WEBREAD_EXAMPLE_TARGET} PRIVATE ${OPENTELEMETRY_PROXY_LINK_LIBRARIES})
if(UNIX AND NOT APPLE AND NOT CYGWIN)
Expand Down
Loading
Loading