diff --git a/CMakeLists.txt b/CMakeLists.txt index fcf7ef8..29942ff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -78,8 +78,9 @@ endif() option(WITH_OTLP_HTTP "Whether to include the OTLP HTTP exporter" ON) 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") +option(WITH_OTLP_FILE "Whether to include the OTLP file exporter" OFF) +if(NOT WITH_OTLP_HTTP AND NOT WITH_OTLP_GRPC AND NOT WITH_OTLP_FILE) + message(FATAL_ERROR "At least one of WITH_OTLP_HTTP, WITH_OTLP_GRPC, or WITH_OTLP_FILE must be ON") endif() if(APPLE) option(SKIP_OTEL_CPP_PATCH "Whether to skip patching OpenTelemetry-cpp" OFF) @@ -178,6 +179,12 @@ if(WITH_OTLP_GRPC) ${OTEL_CPP_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}opentelemetry_exporter_otlp_grpc_log${CMAKE_STATIC_LIBRARY_SUFFIX} ${OTEL_CPP_PREFIX}/lib/${CMAKE_SHARED_LIBRARY_PREFIX}opentelemetry_proto_grpc${OTEL_PROTO_LIBRARY_SUFFIX}) endif() +if(WITH_OTLP_FILE) + set(OTEL_CPP_LIBRARIES ${OTEL_CPP_LIBRARIES} ${OTEL_CPP_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}opentelemetry_exporter_otlp_file${CMAKE_STATIC_LIBRARY_SUFFIX} + ${OTEL_CPP_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}opentelemetry_exporter_otlp_file_client${CMAKE_STATIC_LIBRARY_SUFFIX} + ${OTEL_CPP_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}opentelemetry_exporter_otlp_file_metric${CMAKE_STATIC_LIBRARY_SUFFIX} + ${OTEL_CPP_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}opentelemetry_exporter_otlp_file_log${CMAKE_STATIC_LIBRARY_SUFFIX}) +endif() if(NOT DEFINED OTEL_CPP_INSTALLED_DIR) # No installed location supplied. Fetch it as an external project @@ -209,7 +216,7 @@ if(NOT DEFINED OTEL_CPP_INSTALLED_DIR) 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} -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_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} BUILD_BYPRODUCTS ${OTEL_CPP_LIBRARIES} INSTALL_DIR ${OTEL_CPP_PREFIX} INSTALL_COMMAND ${CMAKE_COMMAND} --install . --prefix ${OTEL_CPP_PREFIX} --config $ @@ -321,6 +328,13 @@ if(WITH_OTLP_GRPC) ${OTLP_EXPORTER_SOURCE_DIR}/OtlpGrpcMetricExporterProxy.cpp ${OTLP_EXPORTER_SOURCE_DIR}/OtlpGrpcLogRecordExporterProxy.cpp) endif() +if(WITH_OTLP_FILE) + set(OPENTELEMETRY_PROXY_SOURCES + ${OPENTELEMETRY_PROXY_SOURCES} + ${OTLP_EXPORTER_SOURCE_DIR}/OtlpFileSpanExporterProxy.cpp + ${OTLP_EXPORTER_SOURCE_DIR}/OtlpFileMetricExporterProxy.cpp + ${OTLP_EXPORTER_SOURCE_DIR}/OtlpFileLogRecordExporterProxy.cpp) +endif() if(WIN32) # Add a preprocessor definition _DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR to fix an invalid mex file issue on Windows. @@ -338,7 +352,7 @@ if(NOT DEFINED OTEL_CPP_INSTALLED_DIR) add_dependencies(${OPENTELEMETRY_PROXY_LIBRARY_NAME} ${OTEL_CPP_PROJECT_NAME}) endif() -# Additional compiler flags for HTTP/gRPC exporters +# Additional compiler flags for HTTP/gRPC/file exporters if(WITH_OTLP_HTTP) target_compile_definitions(${OPENTELEMETRY_PROXY_LIBRARY_NAME} PRIVATE WITH_OTLP_HTTP) endif() @@ -347,6 +361,10 @@ if(WITH_OTLP_GRPC) target_compile_definitions(${OPENTELEMETRY_PROXY_LIBRARY_NAME} PRIVATE WITH_OTLP_GRPC) endif() +if(WITH_OTLP_FILE) + target_compile_definitions(${OPENTELEMETRY_PROXY_LIBRARY_NAME} PRIVATE WITH_OTLP_FILE) +endif() + # pass in version number target_compile_definitions(${OPENTELEMETRY_PROXY_LIBRARY_NAME} PRIVATE OTEL_MATLAB_VERSION="${OTEL_MATLAB_VERSION}") if(WIN32) @@ -472,6 +490,11 @@ set(OTLP_GRPC_EXPORTER_MATLAB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpGrpcMetricExporter.m ${CMAKE_CURRENT_SOURCE_DIR}/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpGrpcLogRecordExporter.m ${CMAKE_CURRENT_SOURCE_DIR}/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpGrpcValidator.m) +set(OTLP_FILE_EXPORTER_MATLAB_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpFileSpanExporter.m + ${CMAKE_CURRENT_SOURCE_DIR}/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpFileMetricExporter.m + ${CMAKE_CURRENT_SOURCE_DIR}/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpFileLogRecordExporter.m + ${CMAKE_CURRENT_SOURCE_DIR}/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpFileValidator.m) set(OTLP_MISC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE) set(OTLP_EXPORTERS_DIR +opentelemetry/+exporters/+otlp) @@ -493,6 +516,9 @@ endif() if(WITH_OTLP_GRPC) install(FILES ${OTLP_GRPC_EXPORTER_MATLAB_SOURCES} DESTINATION ${OTLP_EXPORTERS_DIR}) endif() +if(WITH_OTLP_FILE) + install(FILES ${OTLP_FILE_EXPORTER_MATLAB_SOURCES} DESTINATION ${OTLP_EXPORTERS_DIR}) +endif() # Install license. The only reason it is needed is to work around a packaging bug where if # all files are in packages (+xxx directories), matlab.addons.toolbox.packageToolbox refuses to add the # toolbox path into MATLAB path. This issue is fixed in R2024a diff --git a/OtelMatlabProxyFactory.cpp b/OtelMatlabProxyFactory.cpp index c5dacc5..3a9cd55 100644 --- a/OtelMatlabProxyFactory.cpp +++ b/OtelMatlabProxyFactory.cpp @@ -40,6 +40,11 @@ #include "opentelemetry-matlab/exporters/otlp/OtlpGrpcMetricExporterProxy.h" #include "opentelemetry-matlab/exporters/otlp/OtlpGrpcLogRecordExporterProxy.h" #endif +#ifdef WITH_OTLP_FILE + #include "opentelemetry-matlab/exporters/otlp/OtlpFileSpanExporterProxy.h" + #include "opentelemetry-matlab/exporters/otlp/OtlpFileMetricExporterProxy.h" + #include "opentelemetry-matlab/exporters/otlp/OtlpFileLogRecordExporterProxy.h" +#endif libmexclass::proxy::MakeResult OtelMatlabProxyFactory::make_proxy(const libmexclass::proxy::ClassName& class_name, @@ -88,5 +93,10 @@ OtelMatlabProxyFactory::make_proxy(const libmexclass::proxy::ClassName& class_na REGISTER_PROXY(libmexclass.opentelemetry.exporters.OtlpGrpcMetricExporterProxy, libmexclass::opentelemetry::exporters::OtlpGrpcMetricExporterProxy); REGISTER_PROXY(libmexclass.opentelemetry.exporters.OtlpGrpcLogRecordExporterProxy, libmexclass::opentelemetry::exporters::OtlpGrpcLogRecordExporterProxy); #endif + #ifdef WITH_OTLP_FILE + REGISTER_PROXY(libmexclass.opentelemetry.exporters.OtlpFileSpanExporterProxy, libmexclass::opentelemetry::exporters::OtlpFileSpanExporterProxy); + REGISTER_PROXY(libmexclass.opentelemetry.exporters.OtlpFileMetricExporterProxy, libmexclass::opentelemetry::exporters::OtlpFileMetricExporterProxy); + REGISTER_PROXY(libmexclass.opentelemetry.exporters.OtlpFileLogRecordExporterProxy, libmexclass::opentelemetry::exporters::OtlpFileLogRecordExporterProxy); + #endif return nullptr; } diff --git a/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpFileLogRecordExporter.m b/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpFileLogRecordExporter.m new file mode 100644 index 0000000..0ee028c --- /dev/null +++ b/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpFileLogRecordExporter.m @@ -0,0 +1,124 @@ +classdef OtlpFileLogRecordExporter < opentelemetry.sdk.logs.LogRecordExporter +% OtlpFileLogRecordExporter exports log records in OpenTelemetry Protocol format to +% one or more files. + +% Copyright 2024 The MathWorks, Inc. + + properties + FileName (1,1) string = "logs-%N.jsonl" % Output file name + AliasName (1,1) string = "logs-latest.jsonl" % Alias file name, which is the latest file in rotation + FlushInterval (1,1) duration = seconds(30) % Time interval between log record exports + FlushRecordCount (1,1) double = 256 % Maximum number of records before exporting + MaxFileSize (1,1) double = 20971520 % Maximum output file size + MaxFileCount (1,1) double = 10 % Maximum number of output files, written to in rotation. + end + + properties (Access=private, Constant) + Validator = opentelemetry.exporters.otlp.OtlpFileValidator + end + + methods + function obj = OtlpFileLogRecordExporter(optionnames, optionvalues) + % OtlpFileLogRecordExporter exports log records in OpenTelemetry + % Protocol format to one or more files. + % EXP = OPENTELEMETRY.EXPORTERS.OTLP.OTLPFILELOGRECORDEXPORTER + % creates an exporter that uses default configurations. + % + % EXP = + % OPENTELEMETRY.EXPORTERS.OTLP.OTLPFILELOGRECORDEXPORTER(PARAM1, + % VALUE1, PARAM2, VALUE2, ...) specifies optional parameter + % name/value pairs. Parameters are: + % "FileName" - Output file name. Can contain + % pattern placeholders. Default + % name is "logs-%N.jsonl" + % "AliasName" - Alias file name, which is the + % latest file in rotation. Can + % contain pattern placeholders. + % Default name is "logs-latest.jsonl" + % "FlushInterval" - Time interval between log record + % exports, represented as a + % duration. Default is 30 seconds. + % "FlushRecordCount" - Maximum number of records before + % exporting. When the number of + % records exceed this value, an + % export will be started. Default + % is 256. + % "MaxFileSize" - Maximum output file size + % "MaxFileCount" - Maximum number of output files, + % written to in rotation. Default + % is 10. + % + % Supported pattern placeholders in FileName and AliasName are: + % %Y: year as a 4 digit decimal number + % %y: last 2 digits of year as a decimal number (range [00,99]) + % %m: month as a decimal number (range [01,12]) + % %j: day of the year as a decimal number (range [001,366]) + % %d: day of the month as a decimal number (range [01,31]) + % %w: weekday as a decimal number, where Sunday is 0 (range [0-6]) + % %H: hour as a decimal number, 24 hour clock (range [00-23]) + % %I: hour as a decimal number, 12 hour clock (range [01,12]) + % %M: minute as a decimal number (range [00,59]) + % %S: second as a decimal number (range [00,60]) + % %F: equivalent to "%Y-%m-%d" (the ISO 8601 date format) + % %T: equivalent to "%H:%M:%S" (the ISO 8601 time format) + % %R: equivalent to "%H:%M" + % %N: rotate index, starting from 0 + % %n: rotate index, starting from 1 + % + % See also + % OPENTELEMETRY.EXPORTERS.OTLP.OTLPHTTPLOGRECORDEXPORTER, + % OPENTELEMETRY.EXPORTERS.OTLP.OTLPGRPCLOGRECORDEXPORTER + arguments (Repeating) + optionnames (1,:) {mustBeTextScalar} + optionvalues + end + + obj = obj@opentelemetry.sdk.logs.LogRecordExporter(... + "libmexclass.opentelemetry.exporters.OtlpFileLogRecordExporterProxy"); + + validnames = ["FileName", "AliasName", "FlushInterval", ... + "FlushRecordCount", "MaxFileSize", "MaxFileCount"]; + for i = 1:length(optionnames) + namei = validatestring(optionnames{i}, validnames); + valuei = optionvalues{i}; + obj.(namei) = valuei; + end + end + + function obj = set.FileName(obj, fn) + fn = obj.Validator.validateName(fn, "FileName"); + obj.Proxy.setFileName(fn); + obj.FileName = fn; + end + + function obj = set.AliasName(obj, alias) + alias = obj.Validator.validateName(alias, "AliasName"); + obj.Proxy.setAliasName(alias); + obj.AliasName = alias; + end + + function obj = set.FlushInterval(obj, interval) + obj.Validator.validateFlushInterval(interval); + obj.Proxy.setFlushInterval(milliseconds(interval)); + obj.FlushInterval = interval; + end + + function obj = set.FlushRecordCount(obj, count) + count = obj.Validator.validateScalarPositiveInteger(count, "FlushRecordCount"); + obj.Proxy.setFlushRecordCount(count); + obj.FlushRecordCount = count; + end + + function obj = set.MaxFileSize(obj, maxsize) + maxsize = obj.Validator.validateScalarPositiveInteger(maxsize, "MaxFileSize"); + obj.Proxy.setMaxFileSize(maxsize); + obj.MaxFileSize = maxsize; + end + + function obj = set.MaxFileCount(obj, maxfilecount) + maxfilecount = obj.Validator.validateScalarPositiveInteger(maxfilecount, "MaxFileCount"); + obj.Proxy.setMaxFileCount(maxfilecount); + obj.MaxFileCount = maxfilecount; + end + end +end diff --git a/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpFileMetricExporter.m b/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpFileMetricExporter.m new file mode 100644 index 0000000..294fbc0 --- /dev/null +++ b/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpFileMetricExporter.m @@ -0,0 +1,124 @@ +classdef OtlpFileMetricExporter < opentelemetry.sdk.metrics.MetricExporter +% OtlpFileMetricExporter exports metrics in OpenTelemetry Protocol format to +% one or more files. + +% Copyright 2024 The MathWorks, Inc. + + properties + FileName (1,1) string = "metrics-%N.jsonl" % Output file name + AliasName (1,1) string = "metrics-latest.jsonl" % Alias file name, which is the latest file in rotation + FlushInterval (1,1) duration = seconds(30) % Time interval between metric exports + FlushRecordCount (1,1) double = 256 % Maximum number of records before exporting + MaxFileSize (1,1) double = 20971520 % Maximum output file size + MaxFileCount (1,1) double = 10 % Maximum number of output files, written to in rotation. + end + + properties (Access=private, Constant) + Validator = opentelemetry.exporters.otlp.OtlpFileValidator + end + + methods + function obj = OtlpFileMetricExporter(optionnames, optionvalues) + % OtlpFileMetricExporter exports metrics in OpenTelemetry Protocol + % format to one or more files. + % EXP = OPENTELEMETRY.EXPORTERS.OTLP.OTLPFILEMETRICEXPORTER + % creates an exporter that uses default configurations. + % + % EXP = + % OPENTELEMETRY.EXPORTERS.OTLP.OTLPFILEMETRICEXPORTER(PARAM1, + % VALUE1, PARAM2, VALUE2, ...) specifies optional parameter + % name/value pairs. Parameters are: + % "FileName" - Output file name. Can contain + % pattern placeholders. Default + % name is "metrics-%N.jsonl" + % "AliasName" - Alias file name, which is the + % latest file in rotation. Can + % contain pattern placeholders. + % Default name is "metrics-latest.jsonl" + % "FlushInterval" - Time interval between metric + % exports, represented as a + % duration. Default is 30 seconds. + % "FlushRecordCount" - Maximum number of records before + % exporting. When the number of + % records exceed this value, an + % export will be started. Default + % is 256. + % "MaxFileSize" - Maximum output file size + % "MaxFileCount" - Maximum number of output files, + % written to in rotation. Default + % is 10. + % + % Supported pattern placeholders in FileName and AliasName are: + % %Y: year as a 4 digit decimal number + % %y: last 2 digits of year as a decimal number (range [00,99]) + % %m: month as a decimal number (range [01,12]) + % %j: day of the year as a decimal number (range [001,366]) + % %d: day of the month as a decimal number (range [01,31]) + % %w: weekday as a decimal number, where Sunday is 0 (range [0-6]) + % %H: hour as a decimal number, 24 hour clock (range [00-23]) + % %I: hour as a decimal number, 12 hour clock (range [01,12]) + % %M: minute as a decimal number (range [00,59]) + % %S: second as a decimal number (range [00,60]) + % %F: equivalent to "%Y-%m-%d" (the ISO 8601 date format) + % %T: equivalent to "%H:%M:%S" (the ISO 8601 time format) + % %R: equivalent to "%H:%M" + % %N: rotate index, starting from 0 + % %n: rotate index, starting from 1 + % + % See also + % OPENTELEMETRY.EXPORTERS.OTLP.OTLPHTTPMETRICEXPORTER, + % OPENTELEMETRY.EXPORTERS.OTLP.OTLPGRPCMETRICEXPORTER + arguments (Repeating) + optionnames (1,:) {mustBeTextScalar} + optionvalues + end + + obj = obj@opentelemetry.sdk.metrics.MetricExporter(... + "libmexclass.opentelemetry.exporters.OtlpFileMetricExporterProxy"); + + validnames = ["FileName", "AliasName", "FlushInterval", ... + "FlushRecordCount", "MaxFileSize", "MaxFileCount"]; + for i = 1:length(optionnames) + namei = validatestring(optionnames{i}, validnames); + valuei = optionvalues{i}; + obj.(namei) = valuei; + end + end + + function obj = set.FileName(obj, fn) + fn = obj.Validator.validateName(fn, "FileName"); + obj.Proxy.setFileName(fn); + obj.FileName = fn; + end + + function obj = set.AliasName(obj, alias) + alias = obj.Validator.validateName(alias, "AliasName"); + obj.Proxy.setAliasName(alias); + obj.AliasName = alias; + end + + function obj = set.FlushInterval(obj, interval) + obj.Validator.validateFlushInterval(interval); + obj.Proxy.setFlushInterval(milliseconds(interval)); + obj.FlushInterval = interval; + end + + function obj = set.FlushRecordCount(obj, count) + count = obj.Validator.validateScalarPositiveInteger(count, "FlushRecordCount"); + obj.Proxy.setFlushRecordCount(count); + obj.FlushRecordCount = count; + end + + function obj = set.MaxFileSize(obj, maxsize) + maxsize = obj.Validator.validateScalarPositiveInteger(maxsize, "MaxFileSize"); + obj.Proxy.setMaxFileSize(maxsize); + obj.MaxFileSize = maxsize; + end + + function obj = set.MaxFileCount(obj, maxfilecount) + maxfilecount = obj.Validator.validateScalarPositiveInteger(maxfilecount, "MaxFileCount"); + obj.Proxy.setMaxFileCount(maxfilecount); + obj.MaxFileCount = maxfilecount; + end + end +end diff --git a/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpFileSpanExporter.m b/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpFileSpanExporter.m new file mode 100644 index 0000000..f00d9b8 --- /dev/null +++ b/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpFileSpanExporter.m @@ -0,0 +1,124 @@ +classdef OtlpFileSpanExporter < opentelemetry.sdk.trace.SpanExporter +% OtlpFileSpanExporter exports spans in OpenTelemetry Protocol format to +% one or more files. + +% Copyright 2024 The MathWorks, Inc. + + properties + FileName (1,1) string = "trace-%N.jsonl" % Output file name + AliasName (1,1) string = "trace-latest.jsonl" % Alias file name, which is the latest file in rotation + FlushInterval (1,1) duration = seconds(30) % Time interval between span exports + FlushRecordCount (1,1) double = 256 % Maximum number of records before exporting + MaxFileSize (1,1) double = 20971520 % Maximum output file size + MaxFileCount (1,1) double = 10 % Maximum number of output files, written to in rotation. + end + + properties (Access=private, Constant) + Validator = opentelemetry.exporters.otlp.OtlpFileValidator + end + + methods + function obj = OtlpFileSpanExporter(optionnames, optionvalues) + % OtlpFileSpanExporter exports spans in OpenTelemetry Protocol + % format to one or more files. + % EXP = OPENTELEMETRY.EXPORTERS.OTLP.OTLPFILESPANEXPORTER + % creates an exporter that uses default configurations. + % + % EXP = + % OPENTELEMETRY.EXPORTERS.OTLP.OTLPFILESPANEXPORTER(PARAM1, + % VALUE1, PARAM2, VALUE2, ...) specifies optional parameter + % name/value pairs. Parameters are: + % "FileName" - Output file name. Can contain + % pattern placeholders. Default + % name is "trace-%N.jsonl" + % "AliasName" - Alias file name, which is the + % latest file in rotation. Can + % contain pattern placeholders. + % Default name is "trace-latest.jsonl" + % "FlushInterval" - Time interval between span + % exports, represented as a + % duration. Default is 30 seconds. + % "FlushRecordCount" - Maximum number of records before + % exporting. When the number of + % records exceed this value, an + % export will be started. Default + % is 256. + % "MaxFileSize" - Maximum output file size + % "MaxFileCount" - Maximum number of output files, + % written to in rotation. Default + % is 10. + % + % Supported pattern placeholders in FileName and AliasName are: + % %Y: year as a 4 digit decimal number + % %y: last 2 digits of year as a decimal number (range [00,99]) + % %m: month as a decimal number (range [01,12]) + % %j: day of the year as a decimal number (range [001,366]) + % %d: day of the month as a decimal number (range [01,31]) + % %w: weekday as a decimal number, where Sunday is 0 (range [0-6]) + % %H: hour as a decimal number, 24 hour clock (range [00-23]) + % %I: hour as a decimal number, 12 hour clock (range [01,12]) + % %M: minute as a decimal number (range [00,59]) + % %S: second as a decimal number (range [00,60]) + % %F: equivalent to "%Y-%m-%d" (the ISO 8601 date format) + % %T: equivalent to "%H:%M:%S" (the ISO 8601 time format) + % %R: equivalent to "%H:%M" + % %N: rotate index, starting from 0 + % %n: rotate index, starting from 1 + % + % See also + % OPENTELEMETRY.EXPORTERS.OTLP.OTLPHTTPSPANEXPORTER, + % OPENTELEMETRY.EXPORTERS.OTLP.OTLPGRPCSPANEXPORTER + arguments (Repeating) + optionnames (1,:) {mustBeTextScalar} + optionvalues + end + + obj = obj@opentelemetry.sdk.trace.SpanExporter(... + "libmexclass.opentelemetry.exporters.OtlpFileSpanExporterProxy"); + + validnames = ["FileName", "AliasName", "FlushInterval", ... + "FlushRecordCount", "MaxFileSize", "MaxFileCount"]; + for i = 1:length(optionnames) + namei = validatestring(optionnames{i}, validnames); + valuei = optionvalues{i}; + obj.(namei) = valuei; + end + end + + function obj = set.FileName(obj, fn) + fn = obj.Validator.validateName(fn, "FileName"); + obj.Proxy.setFileName(fn); + obj.FileName = fn; + end + + function obj = set.AliasName(obj, alias) + alias = obj.Validator.validateName(alias, "AliasName"); + obj.Proxy.setAliasName(alias); + obj.AliasName = alias; + end + + function obj = set.FlushInterval(obj, interval) + obj.Validator.validateFlushInterval(interval); + obj.Proxy.setFlushInterval(milliseconds(interval)); + obj.FlushInterval = interval; + end + + function obj = set.FlushRecordCount(obj, count) + count = obj.Validator.validateScalarPositiveInteger(count, "FlushRecordCount"); + obj.Proxy.setFlushRecordCount(count); + obj.FlushRecordCount = count; + end + + function obj = set.MaxFileSize(obj, maxsize) + maxsize = obj.Validator.validateScalarPositiveInteger(maxsize, "MaxFileSize"); + obj.Proxy.setMaxFileSize(maxsize); + obj.MaxFileSize = maxsize; + end + + function obj = set.MaxFileCount(obj, maxfilecount) + maxfilecount = obj.Validator.validateScalarPositiveInteger(maxfilecount, "MaxFileCount"); + obj.Proxy.setMaxFileCount(maxfilecount); + obj.MaxFileCount = maxfilecount; + end + end +end diff --git a/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpFileValidator.m b/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpFileValidator.m new file mode 100644 index 0000000..a303a4e --- /dev/null +++ b/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpFileValidator.m @@ -0,0 +1,32 @@ +classdef OtlpFileValidator +% OtlpFileValidator Validate options inputs for OtlpFileSpanExporter, +% OtlpFileMetricExporter, and OtlpFileLogRecordExporter + +% Copyright 2024 The MathWorks, Inc. + + methods (Static) + function name = validateName(name, paramname) + if ~(isStringScalar(name) || (ischar(name) && isrow(name))) + error("opentelemetry:exporters:otlp:OtlpFileValidator:NameNotScalarText", ... + paramname + " must be a scalar string or a char row."); + end + name = string(name); + end + + function validateFlushInterval(interval) + if ~(isduration(interval) && isscalar(interval)) + error("opentelemetry:exporters:otlp:OtlpFileValidator:FlushIntervalNotScalarDuration", ... + "FlushInterval must be a scalar duration."); + end + end + + function value = validateScalarPositiveInteger(value, paramname) + if ~((islogical(value) || isnumeric(value)) && isscalar(value) && ... + value > 0 && round(value) == value) + error("opentelemetry:exporters:otlp:OtlpFileValidator:NotScalarPositiveInteger", ... + paramname + " must be a scalar positive integer.") + end + value = double(value); + end + end +end diff --git a/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpGrpcLogRecordExporter.m b/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpGrpcLogRecordExporter.m index 4887c07..5ad8556 100644 --- a/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpGrpcLogRecordExporter.m +++ b/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpGrpcLogRecordExporter.m @@ -14,7 +14,7 @@ HttpHeaders (1,1) dictionary = dictionary(string.empty, string.empty) % Additional HTTP headers end - properties (Constant) + properties (Access=private, Constant) Validator = opentelemetry.exporters.otlp.OtlpGrpcValidator end @@ -42,7 +42,8 @@ % will abort % "HTTPHeaders" - Additional HTTP Headers % - % See also OPENTELEMETRY.EXPORTERS.OTLP.OTLPHTTPLOGRECORDEXPORTER + % See also OPENTELEMETRY.EXPORTERS.OTLP.OTLPHTTPLOGRECORDEXPORTER, + % OPENTELEMETRY.EXPORTERS.OTLP.OTLPFILELOGRECORDEXPORTER arguments (Repeating) optionnames (1,:) {mustBeTextScalar} optionvalues diff --git a/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpGrpcMetricExporter.m b/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpGrpcMetricExporter.m index 4d3a250..4a1c7bd 100644 --- a/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpGrpcMetricExporter.m +++ b/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpGrpcMetricExporter.m @@ -3,7 +3,7 @@ % gRPC. By default, it exports to the default address of the OpenTelemetry % Collector. -% Copyright 2023 The MathWorks, Inc. +% Copyright 2023-2024 The MathWorks, Inc. properties Endpoint (1,1) string = "http://localhost:4317" % Export destination @@ -14,7 +14,7 @@ HttpHeaders (1,1) dictionary = dictionary(string.empty, string.empty) % Additional HTTP headers end - properties (Constant) + properties (Access=private, Constant) Validator = opentelemetry.exporters.otlp.OtlpGrpcValidator end @@ -44,7 +44,9 @@ % - An aggregation temporality of % - delta or cumulative % - % See also OPENTELEMETRY.EXPORTERS.OTLP.OTLPHTTPMETRICEXPORTER + % See also + % OPENTELEMETRY.EXPORTERS.OTLP.OTLPHTTPMETRICEXPORTER, + % OPENTELEMETRY.EXPORTERS.OTLP.OTLPFILEMETRICEXPORTER arguments (Repeating) optionnames (1,:) {mustBeTextScalar} optionvalues diff --git a/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpGrpcSpanExporter.m b/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpGrpcSpanExporter.m index 1e43f90..5a9d1a3 100644 --- a/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpGrpcSpanExporter.m +++ b/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpGrpcSpanExporter.m @@ -3,7 +3,7 @@ % gRPC. By default, it exports to the default address of the OpenTelemetry % Collector. -% Copyright 2023 The MathWorks, Inc. +% Copyright 2023-2024 The MathWorks, Inc. properties Endpoint (1,1) string = "http://localhost:4317" % Export destination @@ -14,7 +14,7 @@ HttpHeaders (1,1) dictionary = dictionary(string.empty, string.empty) % Additional HTTP headers end - properties (Constant) + properties (Access=private, Constant) Validator = opentelemetry.exporters.otlp.OtlpGrpcValidator end @@ -41,7 +41,9 @@ % will abort % "HTTPHeaders" - Additional HTTP Headers % - % See also OPENTELEMETRY.EXPORTERS.OTLP.OTLPHTTPSPANEXPORTER + % See also + % OPENTELEMETRY.EXPORTERS.OTLP.OTLPHTTPSPANEXPORTER, + % OPENTELEMETRY.EXPORTERS.OTLP.OTLPFILESPANEXPORTER arguments (Repeating) optionnames (1,:) {mustBeTextScalar} optionvalues diff --git a/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpGrpcValidator.m b/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpGrpcValidator.m index 05b6d02..505857c 100644 --- a/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpGrpcValidator.m +++ b/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpGrpcValidator.m @@ -1,8 +1,8 @@ classdef OtlpGrpcValidator < opentelemetry.exporters.otlp.OtlpValidator -% OtlpGrpcValidator Validate options inputs for OtlpGrpcSpanExporter and -% OtlpGrpcMetricExporter +% OtlpGrpcValidator Validate options inputs for OtlpGrpcSpanExporter, +% OtlpGrpcMetricExporter, and OtlpGrpcLogRecordExporter -% Copyright 2023 The MathWorks, Inc. +% Copyright 2023-2024 The MathWorks, Inc. methods (Static) function uc = validateUseCredentials(uc) diff --git a/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpHttpLogRecordExporter.m b/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpHttpLogRecordExporter.m index 489e4dc..63e138d 100644 --- a/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpHttpLogRecordExporter.m +++ b/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpHttpLogRecordExporter.m @@ -14,7 +14,7 @@ HttpHeaders (1,1) dictionary = dictionary(string.empty, string.empty) % Additional HTTP headers end - properties (Constant) + properties (Access=private, Constant) Validator = opentelemetry.exporters.otlp.OtlpHttpValidator end @@ -41,7 +41,9 @@ % will abort % "HTTPHeaders" - Additional HTTP Headers % - % See also OPENTELEMETRY.EXPORTERS.OTLP.OTLPGRPCLOGRECORDEXPORTER + % See also OPENTELEMETRY.EXPORTERS.OTLP.OTLPGRPCLOGRECORDEXPORTER, + % OPENTELEMETRY.EXPORTERS.OTLP.OTLPFILELOGRECORDEXPORTER + arguments (Repeating) optionnames (1,:) {mustBeTextScalar} optionvalues diff --git a/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpHttpMetricExporter.m b/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpHttpMetricExporter.m index de64aec..bbef0d6 100644 --- a/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpHttpMetricExporter.m +++ b/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpHttpMetricExporter.m @@ -14,7 +14,7 @@ HttpHeaders (1,1) dictionary = dictionary(string.empty, string.empty) % Additional HTTP headers end - properties (Constant) + properties (Access=private, Constant) Validator = opentelemetry.exporters.otlp.OtlpHttpValidator end @@ -44,7 +44,9 @@ % - An aggregation temporality of % - delta or cumulative % - % See also OPENTELEMETRY.EXPORTERS.OTLP.OTLPGRPCMETRICEXPORTER + % See also + % OPENTELEMETRY.EXPORTERS.OTLP.OTLPGRPCMETRICEXPORTER, + % OPENTELEMETRY.EXPORTERS.OTLP.OTLPFILEMETRICEXPORTER arguments (Repeating) optionnames (1,:) {mustBeTextScalar} optionvalues diff --git a/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpHttpSpanExporter.m b/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpHttpSpanExporter.m index b127788..d986c6f 100644 --- a/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpHttpSpanExporter.m +++ b/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpHttpSpanExporter.m @@ -14,7 +14,7 @@ HttpHeaders (1,1) dictionary = dictionary(string.empty, string.empty) % Additional HTTP headers end - properties (Constant) + properties (Access=private, Constant) Validator = opentelemetry.exporters.otlp.OtlpHttpValidator end @@ -41,7 +41,9 @@ % will abort % "HTTPHeaders" - Additional HTTP Headers % - % See also OPENTELEMETRY.EXPORTERS.OTLP.OTLPGRPCSPANEXPORTER + % See also + % OPENTELEMETRY.EXPORTERS.OTLP.OTLPGRPCSPANEXPORTER, + % OPENTELEMETRY.EXPORTERS.OTLP.OTLPFILESPANEXPORTER arguments (Repeating) optionnames (1,:) {mustBeTextScalar} optionvalues diff --git a/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpHttpValidator.m b/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpHttpValidator.m index 17ba494..3447307 100644 --- a/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpHttpValidator.m +++ b/exporters/otlp/+opentelemetry/+exporters/+otlp/OtlpHttpValidator.m @@ -1,8 +1,8 @@ classdef OtlpHttpValidator < opentelemetry.exporters.otlp.OtlpValidator -% OtlpHttpValidator Validate options inputs for OtlpHttpSpanExporter and -% OtlpHttpMetricExporter +% OtlpHttpValidator Validate options inputs for OtlpHttpSpanExporter, +% OtlpHttpMetricExporter, and OtlpHttpLogRecordExporter -% Copyright 2023 The MathWorks, Inc. +% Copyright 2023-2024 The MathWorks, Inc. methods (Static) function newformat = validateFormat(newformat) diff --git a/exporters/otlp/+opentelemetry/+exporters/+otlp/defaultLogRecordExporter.m b/exporters/otlp/+opentelemetry/+exporters/+otlp/defaultLogRecordExporter.m index cb54b81..7410543 100644 --- a/exporters/otlp/+opentelemetry/+exporters/+otlp/defaultLogRecordExporter.m +++ b/exporters/otlp/+opentelemetry/+exporters/+otlp/defaultLogRecordExporter.m @@ -2,15 +2,19 @@ % Get the default log record exporter depending on installation % EXP = OPENTELEMETRY.EXPORTERS.OTLP.DEFAULTSPANEXPORTER returns the % default log record exporter. OtlpHttpLogRecordExporter is the default if it is -% installed. Otherwise, OtlpGrpcLogRecordExporter is the default. +% installed. If not, OtlpGrpcLogRecordExporter is the default if it is +% installed. Otherwise, OtlpFileLogRecordExporter is the default. % % See also OPENTELEMETRY.EXPORTERS.OTLP.OTLPHTTPLOGRECORDEXPORTER, -% OPENTELEMETRY.EXPORTERS.OTLP.OTLPGRPCLOGRECORDEXPORTER +% OPENTELEMETRY.EXPORTERS.OTLP.OTLPGRPCLOGRECORDEXPORTER, +% OPENTELEMETRY.EXPORTERS.OTLP.OTLPFILELOGRECORDEXPORTER % Copyright 2024 The MathWorks, Inc. if exist("opentelemetry.exporters.otlp.OtlpHttpLogRecordExporter", "class") dexp = opentelemetry.exporters.otlp.OtlpHttpLogRecordExporter(varargin{:}); -else +elseif exist("opentelemetry.exporters.otlp.OtlpGrpcLogRecordExporter", "class") dexp = opentelemetry.exporters.otlp.OtlpGrpcLogRecordExporter(varargin{:}); +else + dexp = opentelemetry.exporters.otlp.OtlpFileLogRecordExporter(varargin{:}); end diff --git a/exporters/otlp/+opentelemetry/+exporters/+otlp/defaultMetricExporter.m b/exporters/otlp/+opentelemetry/+exporters/+otlp/defaultMetricExporter.m index 55029a6..d2b481e 100644 --- a/exporters/otlp/+opentelemetry/+exporters/+otlp/defaultMetricExporter.m +++ b/exporters/otlp/+opentelemetry/+exporters/+otlp/defaultMetricExporter.m @@ -2,15 +2,19 @@ % Get the default Metric exporter depending on installation % EXP = OPENTELEMETRY.EXPORTERS.OTLP.DEFAULTMETRICEXPORTER returns the % default Metric exporter. OtlpHttpMetricExporter is the default if it is -% installed. Otherwise, OtlpGrpcMetricExporter is the default. +% installed. If not, OtlpGrpcMetricExporter is the default if it is +% installed. Otherwise, OtlpFileMetricExporter is the default. % -% See also OPENTELEMETRY.EXPORTERS.OTLP.OTLPHTTPMetricEXPORTER, -% OPENTELEMETRY.EXPORTERS.OTLP.OTLPGRPCMetricEXPORTER +% See also OPENTELEMETRY.EXPORTERS.OTLP.OTLPHTTPMETRICEXPORTER, +% OPENTELEMETRY.EXPORTERS.OTLP.OTLPGRPCMETRICEXPORTER, +% OPENTELEMETRY.EXPORTERS.OTLP.OTLPFILEMETRICEXPORTER -% Copyright 2023 The MathWorks, Inc. +% Copyright 2023-2024 The MathWorks, Inc. if exist("opentelemetry.exporters.otlp.OtlpHttpMetricExporter", "class") dexp = opentelemetry.exporters.otlp.OtlpHttpMetricExporter(varargin{:}); -else +elseif exist("opentelemetry.exporters.otlp.OtlpGrpcMetricExporter", "class") dexp = opentelemetry.exporters.otlp.OtlpGrpcMetricExporter(varargin{:}); +else + dexp = opentelemetry.exporters.otlp.OtlpFileMetricExporter(varargin{:}); end diff --git a/exporters/otlp/+opentelemetry/+exporters/+otlp/defaultSpanExporter.m b/exporters/otlp/+opentelemetry/+exporters/+otlp/defaultSpanExporter.m index 85c2076..0d034b0 100644 --- a/exporters/otlp/+opentelemetry/+exporters/+otlp/defaultSpanExporter.m +++ b/exporters/otlp/+opentelemetry/+exporters/+otlp/defaultSpanExporter.m @@ -2,15 +2,19 @@ % Get the default span exporter depending on installation % EXP = OPENTELEMETRY.EXPORTERS.OTLP.DEFAULTSPANEXPORTER returns the % default span exporter. OtlpHttpSpanExporter is the default if it is -% installed. Otherwise, OtlpGrpcSpanExporter is the default. +% installed. If not, OtlpGrpcSpanExporter is the default if it is +% installed. Otherwise, OtlpFileSpanExporter is the default. % % See also OPENTELEMETRY.EXPORTERS.OTLP.OTLPHTTPSPANEXPORTER, -% OPENTELEMETRY.EXPORTERS.OTLP.OTLPGRPCSPANEXPORTER +% OPENTELEMETRY.EXPORTERS.OTLP.OTLPGRPCSPANEXPORTER, +% OPENTELEMETRY.EXPORTERS.OTLP.OTLPFILESPANEXPORTER -% Copyright 2023 The MathWorks, Inc. +% Copyright 2023-2024 The MathWorks, Inc. if exist("opentelemetry.exporters.otlp.OtlpHttpSpanExporter", "class") dexp = opentelemetry.exporters.otlp.OtlpHttpSpanExporter(varargin{:}); -else +elseif exist("opentelemetry.exporters.otlp.OtlpGrpcSpanExporter", "class") dexp = opentelemetry.exporters.otlp.OtlpGrpcSpanExporter(varargin{:}); +else + dexp = opentelemetry.exporters.otlp.OtlpFileSpanExporter(varargin{:}); end diff --git a/exporters/otlp/include/opentelemetry-matlab/exporters/otlp/OtlpFileLogRecordExporterProxy.h b/exporters/otlp/include/opentelemetry-matlab/exporters/otlp/OtlpFileLogRecordExporterProxy.h new file mode 100644 index 0000000..6b6892c --- /dev/null +++ b/exporters/otlp/include/opentelemetry-matlab/exporters/otlp/OtlpFileLogRecordExporterProxy.h @@ -0,0 +1,47 @@ +// Copyright 2024 The MathWorks, Inc. + +#pragma once + +#include "opentelemetry-matlab/sdk/logs/LogRecordExporterProxy.h" + +#include "libmexclass/proxy/Proxy.h" +#include "libmexclass/proxy/method/Context.h" + +#include "opentelemetry/sdk/logs/exporter.h" +#include "opentelemetry/exporters/otlp/otlp_file_log_record_exporter_options.h" + +namespace logs_sdk = opentelemetry::sdk::logs; +namespace otlp_exporter = opentelemetry::exporter::otlp; + +namespace libmexclass::opentelemetry::exporters { +class OtlpFileLogRecordExporterProxy: public libmexclass::opentelemetry::sdk::LogRecordExporterProxy { + public: + OtlpFileLogRecordExporterProxy(otlp_exporter::OtlpFileLogRecordExporterOptions options) : CppOptions(options) { + REGISTER_METHOD(OtlpFileLogRecordExporterProxy, setFileName); + REGISTER_METHOD(OtlpFileLogRecordExporterProxy, setAliasName); + REGISTER_METHOD(OtlpFileLogRecordExporterProxy, setFlushInterval); + REGISTER_METHOD(OtlpFileLogRecordExporterProxy, setFlushRecordCount); + REGISTER_METHOD(OtlpFileLogRecordExporterProxy, setMaxFileSize); + REGISTER_METHOD(OtlpFileLogRecordExporterProxy, setMaxFileCount); + } + + static libmexclass::proxy::MakeResult make(const libmexclass::proxy::FunctionArguments& constructor_arguments); + + std::unique_ptr getInstance() override; + + void setFileName(libmexclass::proxy::method::Context& context); + + void setAliasName(libmexclass::proxy::method::Context& context); + + void setFlushInterval(libmexclass::proxy::method::Context& context); + + void setFlushRecordCount(libmexclass::proxy::method::Context& context); + + void setMaxFileSize(libmexclass::proxy::method::Context& context); + + void setMaxFileCount(libmexclass::proxy::method::Context& context); + + private: + otlp_exporter::OtlpFileLogRecordExporterOptions CppOptions; +}; +} // namespace libmexclass::opentelemetry diff --git a/exporters/otlp/include/opentelemetry-matlab/exporters/otlp/OtlpFileMetricExporterProxy.h b/exporters/otlp/include/opentelemetry-matlab/exporters/otlp/OtlpFileMetricExporterProxy.h new file mode 100644 index 0000000..b6d489a --- /dev/null +++ b/exporters/otlp/include/opentelemetry-matlab/exporters/otlp/OtlpFileMetricExporterProxy.h @@ -0,0 +1,47 @@ +// Copyright 2024 The MathWorks, Inc. + +#pragma once + +#include "opentelemetry-matlab/sdk/metrics/MetricExporterProxy.h" + +#include "libmexclass/proxy/Proxy.h" +#include "libmexclass/proxy/method/Context.h" + +#include "opentelemetry/sdk/metrics/push_metric_exporter.h" +#include "opentelemetry/exporters/otlp/otlp_file_metric_exporter_options.h" + +namespace metric_sdk = opentelemetry::sdk::metrics; +namespace otlp_exporter = opentelemetry::exporter::otlp; + +namespace libmexclass::opentelemetry::exporters { +class OtlpFileMetricExporterProxy: public libmexclass::opentelemetry::sdk::MetricExporterProxy { + public: + OtlpFileMetricExporterProxy(otlp_exporter::OtlpFileMetricExporterOptions options) : CppOptions(options) { + REGISTER_METHOD(OtlpFileMetricExporterProxy, setFileName); + REGISTER_METHOD(OtlpFileMetricExporterProxy, setAliasName); + REGISTER_METHOD(OtlpFileMetricExporterProxy, setFlushInterval); + REGISTER_METHOD(OtlpFileMetricExporterProxy, setFlushRecordCount); + REGISTER_METHOD(OtlpFileMetricExporterProxy, setMaxFileSize); + REGISTER_METHOD(OtlpFileMetricExporterProxy, setMaxFileCount); + } + + static libmexclass::proxy::MakeResult make(const libmexclass::proxy::FunctionArguments& constructor_arguments); + + std::unique_ptr getInstance() override; + + void setFileName(libmexclass::proxy::method::Context& context); + + void setAliasName(libmexclass::proxy::method::Context& context); + + void setFlushInterval(libmexclass::proxy::method::Context& context); + + void setFlushRecordCount(libmexclass::proxy::method::Context& context); + + void setMaxFileSize(libmexclass::proxy::method::Context& context); + + void setMaxFileCount(libmexclass::proxy::method::Context& context); + + private: + otlp_exporter::OtlpFileMetricExporterOptions CppOptions; +}; +} // namespace libmexclass::opentelemetry diff --git a/exporters/otlp/include/opentelemetry-matlab/exporters/otlp/OtlpFileSpanExporterProxy.h b/exporters/otlp/include/opentelemetry-matlab/exporters/otlp/OtlpFileSpanExporterProxy.h new file mode 100644 index 0000000..d2b98cc --- /dev/null +++ b/exporters/otlp/include/opentelemetry-matlab/exporters/otlp/OtlpFileSpanExporterProxy.h @@ -0,0 +1,47 @@ +// Copyright 2024 The MathWorks, Inc. + +#pragma once + +#include "opentelemetry-matlab/sdk/trace/SpanExporterProxy.h" + +#include "libmexclass/proxy/Proxy.h" +#include "libmexclass/proxy/method/Context.h" + +#include "opentelemetry/sdk/trace/exporter.h" +#include "opentelemetry/exporters/otlp/otlp_file_exporter_options.h" + +namespace trace_sdk = opentelemetry::sdk::trace; +namespace otlp_exporter = opentelemetry::exporter::otlp; + +namespace libmexclass::opentelemetry::exporters { +class OtlpFileSpanExporterProxy: public libmexclass::opentelemetry::sdk::SpanExporterProxy { + public: + OtlpFileSpanExporterProxy(otlp_exporter::OtlpFileExporterOptions options) : CppOptions(options) { + REGISTER_METHOD(OtlpFileSpanExporterProxy, setFileName); + REGISTER_METHOD(OtlpFileSpanExporterProxy, setAliasName); + REGISTER_METHOD(OtlpFileSpanExporterProxy, setFlushInterval); + REGISTER_METHOD(OtlpFileSpanExporterProxy, setFlushRecordCount); + REGISTER_METHOD(OtlpFileSpanExporterProxy, setMaxFileSize); + REGISTER_METHOD(OtlpFileSpanExporterProxy, setMaxFileCount); + } + + static libmexclass::proxy::MakeResult make(const libmexclass::proxy::FunctionArguments& constructor_arguments); + + std::unique_ptr getInstance() override; + + void setFileName(libmexclass::proxy::method::Context& context); + + void setAliasName(libmexclass::proxy::method::Context& context); + + void setFlushInterval(libmexclass::proxy::method::Context& context); + + void setFlushRecordCount(libmexclass::proxy::method::Context& context); + + void setMaxFileSize(libmexclass::proxy::method::Context& context); + + void setMaxFileCount(libmexclass::proxy::method::Context& context); + + private: + otlp_exporter::OtlpFileExporterOptions CppOptions; +}; +} // namespace libmexclass::opentelemetry diff --git a/exporters/otlp/src/OtlpFileLogRecordExporterProxy.cpp b/exporters/otlp/src/OtlpFileLogRecordExporterProxy.cpp new file mode 100644 index 0000000..69217e3 --- /dev/null +++ b/exporters/otlp/src/OtlpFileLogRecordExporterProxy.cpp @@ -0,0 +1,71 @@ +// Copyright 2024 The MathWorks, Inc. + +#include "opentelemetry-matlab/exporters/otlp/OtlpFileLogRecordExporterProxy.h" + +#include "libmexclass/proxy/ProxyManager.h" + +#include "opentelemetry/exporters/otlp/otlp_file_log_record_exporter_factory.h" +#include "opentelemetry/exporters/otlp/otlp_file_log_record_exporter_options.h" + +namespace otlp_exporter = opentelemetry::exporter::otlp; +namespace nostd = opentelemetry::nostd; + +namespace libmexclass::opentelemetry::exporters { +libmexclass::proxy::MakeResult OtlpFileLogRecordExporterProxy::make(const libmexclass::proxy::FunctionArguments& constructor_arguments) { + otlp_exporter::OtlpFileLogRecordExporterOptions options; + return std::make_shared(options); +} + +std::unique_ptr OtlpFileLogRecordExporterProxy::getInstance() { + return otlp_exporter::OtlpFileLogRecordExporterFactory::Create(CppOptions); +} + +void OtlpFileLogRecordExporterProxy::setFileName(libmexclass::proxy::method::Context& context) { + matlab::data::StringArray filename_mda = context.inputs[0]; + std::string filename = static_cast(filename_mda[0]); + auto options = nostd::get(CppOptions.backend_options); + options.file_pattern = filename; + CppOptions.backend_options = options; +} + +void OtlpFileLogRecordExporterProxy::setAliasName(libmexclass::proxy::method::Context& context) { + matlab::data::StringArray aliasname_mda = context.inputs[0]; + std::string aliasname = static_cast(aliasname_mda[0]); + auto options = nostd::get(CppOptions.backend_options); + options.alias_pattern = aliasname; + CppOptions.backend_options = options; +} + +void OtlpFileLogRecordExporterProxy::setFlushInterval(libmexclass::proxy::method::Context& context) { + matlab::data::TypedArray flushinterval_mda = context.inputs[0]; + double flushinterval = flushinterval_mda[0]; + auto options = nostd::get(CppOptions.backend_options); + options.flush_interval = std::chrono::milliseconds(static_cast(flushinterval)); + CppOptions.backend_options = options; +} + +void OtlpFileLogRecordExporterProxy::setFlushRecordCount(libmexclass::proxy::method::Context& context) { + matlab::data::TypedArray flushrecordcount_mda = context.inputs[0]; + double flushrecordcount = flushrecordcount_mda[0]; + auto options = nostd::get(CppOptions.backend_options); + options.flush_count = static_cast(flushrecordcount); + CppOptions.backend_options = options; +} + +void OtlpFileLogRecordExporterProxy::setMaxFileSize(libmexclass::proxy::method::Context& context) { + matlab::data::TypedArray maxfilesize_mda = context.inputs[0]; + double maxfilesize = maxfilesize_mda[0]; + auto options = nostd::get(CppOptions.backend_options); + options.file_size = static_cast(maxfilesize); + CppOptions.backend_options = options; +} + +void OtlpFileLogRecordExporterProxy::setMaxFileCount(libmexclass::proxy::method::Context& context) { + matlab::data::TypedArray maxfilecount_mda = context.inputs[0]; + double maxfilecount = maxfilecount_mda[0]; + auto options = nostd::get(CppOptions.backend_options); + options.rotate_size = static_cast(maxfilecount); + CppOptions.backend_options = options; +} + +} // namespace libmexclass::opentelemetry diff --git a/exporters/otlp/src/OtlpFileMetricExporterProxy.cpp b/exporters/otlp/src/OtlpFileMetricExporterProxy.cpp new file mode 100644 index 0000000..e3bbcfe --- /dev/null +++ b/exporters/otlp/src/OtlpFileMetricExporterProxy.cpp @@ -0,0 +1,71 @@ +// Copyright 2024 The MathWorks, Inc. + +#include "opentelemetry-matlab/exporters/otlp/OtlpFileMetricExporterProxy.h" + +#include "libmexclass/proxy/ProxyManager.h" + +#include "opentelemetry/exporters/otlp/otlp_file_metric_exporter_factory.h" +#include "opentelemetry/exporters/otlp/otlp_file_client_options.h" + +namespace otlp_exporter = opentelemetry::exporter::otlp; +namespace nostd = opentelemetry::nostd; + +namespace libmexclass::opentelemetry::exporters { +libmexclass::proxy::MakeResult OtlpFileMetricExporterProxy::make(const libmexclass::proxy::FunctionArguments& constructor_arguments) { + otlp_exporter::OtlpFileMetricExporterOptions options; + return std::make_shared(options); +} + +std::unique_ptr OtlpFileMetricExporterProxy::getInstance() { + return otlp_exporter::OtlpFileMetricExporterFactory::Create(CppOptions); +} + +void OtlpFileMetricExporterProxy::setFileName(libmexclass::proxy::method::Context& context) { + matlab::data::StringArray filename_mda = context.inputs[0]; + std::string filename = static_cast(filename_mda[0]); + auto options = nostd::get(CppOptions.backend_options); + options.file_pattern = filename; + CppOptions.backend_options = options; +} + +void OtlpFileMetricExporterProxy::setAliasName(libmexclass::proxy::method::Context& context) { + matlab::data::StringArray aliasname_mda = context.inputs[0]; + std::string aliasname = static_cast(aliasname_mda[0]); + auto options = nostd::get(CppOptions.backend_options); + options.alias_pattern = aliasname; + CppOptions.backend_options = options; +} + +void OtlpFileMetricExporterProxy::setFlushInterval(libmexclass::proxy::method::Context& context) { + matlab::data::TypedArray flushinterval_mda = context.inputs[0]; + double flushinterval = flushinterval_mda[0]; + auto options = nostd::get(CppOptions.backend_options); + options.flush_interval = std::chrono::milliseconds(static_cast(flushinterval)); + CppOptions.backend_options = options; +} + +void OtlpFileMetricExporterProxy::setFlushRecordCount(libmexclass::proxy::method::Context& context) { + matlab::data::TypedArray flushrecordcount_mda = context.inputs[0]; + double flushrecordcount = flushrecordcount_mda[0]; + auto options = nostd::get(CppOptions.backend_options); + options.flush_count = static_cast(flushrecordcount); + CppOptions.backend_options = options; +} + +void OtlpFileMetricExporterProxy::setMaxFileSize(libmexclass::proxy::method::Context& context) { + matlab::data::TypedArray maxfilesize_mda = context.inputs[0]; + double maxfilesize = maxfilesize_mda[0]; + auto options = nostd::get(CppOptions.backend_options); + options.file_size = static_cast(maxfilesize); + CppOptions.backend_options = options; +} + +void OtlpFileMetricExporterProxy::setMaxFileCount(libmexclass::proxy::method::Context& context) { + matlab::data::TypedArray maxfilecount_mda = context.inputs[0]; + double maxfilecount = maxfilecount_mda[0]; + auto options = nostd::get(CppOptions.backend_options); + options.rotate_size = static_cast(maxfilecount); + CppOptions.backend_options = options; +} + +} // namespace libmexclass::opentelemetry diff --git a/exporters/otlp/src/OtlpFileSpanExporterProxy.cpp b/exporters/otlp/src/OtlpFileSpanExporterProxy.cpp new file mode 100644 index 0000000..e90f986 --- /dev/null +++ b/exporters/otlp/src/OtlpFileSpanExporterProxy.cpp @@ -0,0 +1,71 @@ +// Copyright 2024 The MathWorks, Inc. + +#include "opentelemetry-matlab/exporters/otlp/OtlpFileSpanExporterProxy.h" + +#include "libmexclass/proxy/ProxyManager.h" + +#include "opentelemetry/exporters/otlp/otlp_file_exporter_factory.h" +#include "opentelemetry/exporters/otlp/otlp_file_client_options.h" + +namespace otlp_exporter = opentelemetry::exporter::otlp; +namespace nostd = opentelemetry::nostd; + +namespace libmexclass::opentelemetry::exporters { +libmexclass::proxy::MakeResult OtlpFileSpanExporterProxy::make(const libmexclass::proxy::FunctionArguments& constructor_arguments) { + otlp_exporter::OtlpFileExporterOptions options; + return std::make_shared(options); +} + +std::unique_ptr OtlpFileSpanExporterProxy::getInstance() { + return otlp_exporter::OtlpFileExporterFactory::Create(CppOptions); +} + +void OtlpFileSpanExporterProxy::setFileName(libmexclass::proxy::method::Context& context) { + matlab::data::StringArray filename_mda = context.inputs[0]; + std::string filename = static_cast(filename_mda[0]); + auto options = nostd::get(CppOptions.backend_options); + options.file_pattern = filename; + CppOptions.backend_options = options; +} + +void OtlpFileSpanExporterProxy::setAliasName(libmexclass::proxy::method::Context& context) { + matlab::data::StringArray aliasname_mda = context.inputs[0]; + std::string aliasname = static_cast(aliasname_mda[0]); + auto options = nostd::get(CppOptions.backend_options); + options.alias_pattern = aliasname; + CppOptions.backend_options = options; +} + +void OtlpFileSpanExporterProxy::setFlushInterval(libmexclass::proxy::method::Context& context) { + matlab::data::TypedArray flushinterval_mda = context.inputs[0]; + double flushinterval = flushinterval_mda[0]; + auto options = nostd::get(CppOptions.backend_options); + options.flush_interval = std::chrono::milliseconds(static_cast(flushinterval)); + CppOptions.backend_options = options; +} + +void OtlpFileSpanExporterProxy::setFlushRecordCount(libmexclass::proxy::method::Context& context) { + matlab::data::TypedArray flushrecordcount_mda = context.inputs[0]; + double flushrecordcount = flushrecordcount_mda[0]; + auto options = nostd::get(CppOptions.backend_options); + options.flush_count = static_cast(flushrecordcount); + CppOptions.backend_options = options; +} + +void OtlpFileSpanExporterProxy::setMaxFileSize(libmexclass::proxy::method::Context& context) { + matlab::data::TypedArray maxfilesize_mda = context.inputs[0]; + double maxfilesize = maxfilesize_mda[0]; + auto options = nostd::get(CppOptions.backend_options); + options.file_size = static_cast(maxfilesize); + CppOptions.backend_options = options; +} + +void OtlpFileSpanExporterProxy::setMaxFileCount(libmexclass::proxy::method::Context& context) { + matlab::data::TypedArray maxfilecount_mda = context.inputs[0]; + double maxfilecount = maxfilecount_mda[0]; + auto options = nostd::get(CppOptions.backend_options); + options.rotate_size = static_cast(maxfilecount); + CppOptions.backend_options = options; +} + +} // namespace libmexclass::opentelemetry diff --git a/sdk/logs/+opentelemetry/+sdk/+logs/LogRecordExporter.m b/sdk/logs/+opentelemetry/+sdk/+logs/LogRecordExporter.m index 1263905..f878679 100644 --- a/sdk/logs/+opentelemetry/+sdk/+logs/LogRecordExporter.m +++ b/sdk/logs/+opentelemetry/+sdk/+logs/LogRecordExporter.m @@ -5,7 +5,8 @@ properties (GetAccess={?opentelemetry.sdk.logs.LogRecordProcessor, ... ?opentelemetry.exporters.otlp.OtlpHttpLogRecordExporter, ... - ?opentelemetry.exporters.otlp.OtlpGrpcLogRecordExporter}) + ?opentelemetry.exporters.otlp.OtlpGrpcLogRecordExporter, ... + ?opentelemetry.exporters.otlp.OtlpFileLogRecordExporter}) Proxy % Proxy object to interface C++ code end diff --git a/sdk/metrics/+opentelemetry/+sdk/+metrics/MetricExporter.m b/sdk/metrics/+opentelemetry/+sdk/+metrics/MetricExporter.m index 7a9da5b..7415385 100644 --- a/sdk/metrics/+opentelemetry/+sdk/+metrics/MetricExporter.m +++ b/sdk/metrics/+opentelemetry/+sdk/+metrics/MetricExporter.m @@ -1,15 +1,16 @@ classdef MetricExporter % Base class of metric exporters -% Copyright 2023 The MathWorks, Inc. +% Copyright 2023-2024 The MathWorks, Inc. properties - PreferredAggregationTemporality (1,1) string = "cumulative" % Preferred Aggregation Temporality + PreferredAggregationTemporality (1,1) string = "cumulative" % Preferred Aggregation Temporality end - properties (Access={?opentelemetry.sdk.metrics.PeriodicExportingMetricReader, ... + properties (Hidden, Access={?opentelemetry.sdk.metrics.PeriodicExportingMetricReader, ... ?opentelemetry.exporters.otlp.OtlpHttpMetricExporter, ... - ?opentelemetry.exporters.otlp.OtlpGrpcMetricExporter}) + ?opentelemetry.exporters.otlp.OtlpGrpcMetricExporter, ... + ?opentelemetry.exporters.otlp.OtlpFileMetricExporter}) Proxy % Proxy object to interface C++ code end diff --git a/sdk/trace/+opentelemetry/+sdk/+trace/SpanExporter.m b/sdk/trace/+opentelemetry/+sdk/+trace/SpanExporter.m index cf0e4df..42f4e00 100644 --- a/sdk/trace/+opentelemetry/+sdk/+trace/SpanExporter.m +++ b/sdk/trace/+opentelemetry/+sdk/+trace/SpanExporter.m @@ -1,11 +1,12 @@ classdef SpanExporter % Base class of span exporters -% Copyright 2023 The MathWorks, Inc. +% Copyright 2023-2024 The MathWorks, Inc. - properties (GetAccess={?opentelemetry.sdk.trace.SpanProcessor, ... + properties (Hidden, GetAccess={?opentelemetry.sdk.trace.SpanProcessor, ... ?opentelemetry.exporters.otlp.OtlpHttpSpanExporter, ... - ?opentelemetry.exporters.otlp.OtlpGrpcSpanExporter}) + ?opentelemetry.exporters.otlp.OtlpGrpcSpanExporter, ... + ?opentelemetry.exporters.otlp.OtlpFileSpanExporter}) Proxy % Proxy object to interface C++ code end diff --git a/test/tlogs_sdk.m b/test/tlogs_sdk.m index 26eb78a..1adca6e 100644 --- a/test/tlogs_sdk.m +++ b/test/tlogs_sdk.m @@ -39,7 +39,42 @@ function teardown(testCase) end end - methods (Test) + methods (Test) + function testOtlpFileExporter(testCase) + % testOtlpFileExporter: use a file exporter to write to files + + testCase.assumeTrue(logical(exist("opentelemetry.exporters.otlp.OtlpFileLogRecordExporter", "class")), ... + "Otlp file exporter must be installed."); + + % create temporary folder to write the output files + folderfixture = testCase.applyFixture(... + matlab.unittest.fixtures.TemporaryFolderFixture); + + % create file exporter + output = fullfile(folderfixture.Folder,"output%n.json"); + alias = fullfile(folderfixture.Folder,"output_latest.json"); + exp = opentelemetry.exporters.otlp.OtlpFileLogRecordExporter(... + FileName=output, AliasName=alias); + + lp = opentelemetry.sdk.logs.LoggerProvider(... + opentelemetry.sdk.logs.SimpleLogRecordProcessor(exp)); + + loggername = "foo"; + logseverity = "debug"; + logmessage = "bar"; + lg = getLogger(lp, loggername); + emitLogRecord(lg, logseverity, logmessage); + + % perform test comparisons + forceFlush(lp, testCase.ForceFlushTimeout); + results = jsondecode(fileread(alias)); + + % check logger name, log body and severity + verifyEqual(testCase, string(results.resourceLogs.scopeLogs.scope.name), loggername); + verifyEqual(testCase, string(results.resourceLogs.scopeLogs.logRecords.severityText), upper(logseverity)); + verifyEqual(testCase, string(results.resourceLogs.scopeLogs.logRecords.body.stringValue), logmessage); + end + function testAddLogRecordProcessor(testCase) % testAddLogRecordProcessor: addLogRecordProcessor method loggername = "foo"; diff --git a/test/tmetrics_sdk.m b/test/tmetrics_sdk.m index 2eb7304..b716392 100644 --- a/test/tmetrics_sdk.m +++ b/test/tmetrics_sdk.m @@ -64,6 +64,48 @@ function testExporterBasic(testCase) verifyEqual(testCase, string(exporter.PreferredAggregationTemporality), temporality); end + function testOtlpFileExporter(testCase) + % testOtlpFileExporter: use a file exporter to write to files + + testCase.assumeTrue(logical(exist("opentelemetry.exporters.otlp.OtlpFileMetricExporter", "class")), ... + "Otlp file exporter must be installed."); + + % create temporary folder to write the output files + folderfixture = testCase.applyFixture(... + matlab.unittest.fixtures.TemporaryFolderFixture); + + % create file exporter + output = fullfile(folderfixture.Folder,"output%n.json"); + alias = fullfile(folderfixture.Folder,"output_latest.json"); + exp = opentelemetry.exporters.otlp.OtlpFileMetricExporter(... + FileName=output, AliasName=alias); + reader = opentelemetry.sdk.metrics.PeriodicExportingMetricReader(exp, ... + Interval=testCase.ShortIntervalReader.Interval, ... + Timeout=testCase.ShortIntervalReader.Timeout); + p = opentelemetry.sdk.metrics.MeterProvider(reader); + + metername = "foo"; + countername = "bar"; + mt = p.getMeter(metername); + ct = mt.createCounter(countername); + + % create testing value + val = 10; + + % add value + ct.add(val); + + % fetch result + clear p; + results = jsondecode(fileread(alias)); + + % verify meter and counter names + verifyEqual(testCase, string(results.resourceMetrics.scopeMetrics.metrics.name), countername); + verifyEqual(testCase, string(results.resourceMetrics.scopeMetrics.scope.name), metername); + + % verify counter value + verifyEqual(testCase, results.resourceMetrics.scopeMetrics.metrics.sum.dataPoints.asDouble, val); + end function testDefaultReader(testCase) reader = opentelemetry.sdk.metrics.PeriodicExportingMetricReader(); diff --git a/test/ttrace_sdk.m b/test/ttrace_sdk.m index 3062a04..4268cc4 100644 --- a/test/ttrace_sdk.m +++ b/test/ttrace_sdk.m @@ -129,6 +129,40 @@ function testTraceIdRatioBasedSampler(testCase) end end + function testOtlpFileExporter(testCase) + % testOtlpFileExporter: use a file exporter to write to files + + testCase.assumeTrue(logical(exist("opentelemetry.exporters.otlp.OtlpFileSpanExporter", "class")), ... + "Otlp file exporter must be installed."); + + % create temporary folder to write the output files + folderfixture = testCase.applyFixture(... + matlab.unittest.fixtures.TemporaryFolderFixture); + + % create file exporter + output = fullfile(folderfixture.Folder,"output%n.json"); + alias = fullfile(folderfixture.Folder,"output_latest.json"); + exp = opentelemetry.exporters.otlp.OtlpFileSpanExporter(... + FileName=output, AliasName=alias); + + tp = opentelemetry.sdk.trace.TracerProvider(... + opentelemetry.sdk.trace.SimpleSpanProcessor(exp)); + + tracername = "foo"; + spanname = "bar"; + tr = getTracer(tp, tracername); + sp = startSpan(tr, spanname); + pause(1); + endSpan(sp); + + % perform test comparisons + results = jsondecode(fileread(alias)); + + % check span and tracer names + verifyEqual(testCase, string(results.resourceSpans.scopeSpans.spans.name), spanname); + verifyEqual(testCase, string(results.resourceSpans.scopeSpans.scope.name), tracername); + end + function testCustomResource(testCase) % testCustomResource: check custom resources are included in % emitted spans