]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/jaegertracing/opentelemetry-cpp/exporters/ostream/test/ostream_log_test.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / jaegertracing / opentelemetry-cpp / exporters / ostream / test / ostream_log_test.cc
diff --git a/ceph/src/jaegertracing/opentelemetry-cpp/exporters/ostream/test/ostream_log_test.cc b/ceph/src/jaegertracing/opentelemetry-cpp/exporters/ostream/test/ostream_log_test.cc
new file mode 100644 (file)
index 0000000..91d8fbf
--- /dev/null
@@ -0,0 +1,330 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#ifdef ENABLE_LOGS_PREVIEW
+
+#  include <array>
+#  include "opentelemetry/exporters/ostream/log_exporter.h"
+#  include "opentelemetry/logs/provider.h"
+#  include "opentelemetry/nostd/span.h"
+#  include "opentelemetry/sdk/logs/logger_provider.h"
+#  include "opentelemetry/sdk/logs/simple_log_processor.h"
+
+#  include <gtest/gtest.h>
+#  include <iostream>
+
+namespace sdklogs      = opentelemetry::sdk::logs;
+namespace logs_api     = opentelemetry::logs;
+namespace nostd        = opentelemetry::nostd;
+namespace exporterlogs = opentelemetry::exporter::logs;
+namespace common       = opentelemetry::common;
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace exporter
+{
+namespace logs
+{
+
+// Test that when OStream Log exporter is shutdown, no logs should be sent to stream
+TEST(OStreamLogExporter, Shutdown)
+{
+  auto exporter = std::unique_ptr<sdklogs::LogExporter>(new exporterlogs::OStreamLogExporter);
+
+  // Save cout's original buffer here
+  std::streambuf *original = std::cout.rdbuf();
+
+  // Redirect cout to our stringstream buffer
+  std::stringstream output;
+  std::cout.rdbuf(output.rdbuf());
+
+  EXPECT_TRUE(exporter->Shutdown());
+
+  // After processor/exporter is shutdown, no logs should be sent to stream
+  auto record = exporter->MakeRecordable();
+  record->SetBody("Log record not empty");
+  exporter->Export(nostd::span<std::unique_ptr<sdklogs::Recordable>>(&record, 1));
+
+  // Restore original stringstream buffer
+  std::cout.rdbuf(original);
+  std::string err_message =
+      "[Ostream Log Exporter] Exporting 1 log(s) failed, exporter is shutdown";
+  EXPECT_TRUE(output.str().find(err_message) != std::string::npos);
+}
+
+// ---------------------------------- Print to cout -------------------------
+
+// Testing what a default log record that has no values changed will print out
+// This function tests MakeRecordable() as well as Export().
+TEST(OstreamLogExporter, DefaultLogRecordToCout)
+{
+  auto exporter =
+      std::unique_ptr<sdklogs::LogExporter>(new exporterlogs::OStreamLogExporter(std::cout));
+
+  // Save cout's original buffer here
+  std::streambuf *original = std::cout.rdbuf();
+
+  // Redirect cout to our stringstream buffer
+  std::stringstream output;
+  std::cout.rdbuf(output.rdbuf());
+
+  // Pass a default recordable created by the exporter to be exported
+  auto log_record = exporter->MakeRecordable();
+  exporter->Export(nostd::span<std::unique_ptr<sdklogs::Recordable>>(&log_record, 1));
+
+  // Restore cout's original stringstream
+  std::cout.rdbuf(original);
+
+  std::vector<std::string> expected_output{
+      "{\n"
+      "  timestamp     : 0\n"
+      "  severity_num  : 0\n"
+      "  severity_text : INVALID\n"
+      "  body          : \n",
+      "  resource      : \n",
+      "telemetry.sdk.version: " OPENTELEMETRY_VERSION "\n",
+      "telemetry.sdk.name: opentelemetry\n",
+      "telemetry.sdk.language: cpp\n",
+      "  attributes    : \n"
+      "  trace_id      : 00000000000000000000000000000000\n"
+      "  span_id       : 0000000000000000\n"
+      "  trace_flags   : 00\n"
+      "}\n"};
+
+  for (auto &expected : expected_output)
+  {
+    ASSERT_NE(output.str().find(expected), std::string::npos);
+  }
+}
+
+// Testing what a log record with only the "timestamp", "severity", "name" and "message" fields set,
+// will print out
+TEST(OStreamLogExporter, SimpleLogToCout)
+{
+  // Initialize an Ostream exporter to std::cout
+  auto exporter =
+      std::unique_ptr<sdklogs::LogExporter>(new exporterlogs::OStreamLogExporter(std::cout));
+
+  // Save original stream buffer, then redirect cout to our new stream buffer
+  std::streambuf *original = std::cout.rdbuf();
+  std::stringstream output;
+  std::cout.rdbuf(output.rdbuf());
+
+  // Pass a default recordable created by the exporter to be exported
+  // Create a log record and manually timestamp, severity, name, message
+  common::SystemTimestamp now(std::chrono::system_clock::now());
+
+  auto record = std::unique_ptr<sdklogs::Recordable>(new sdklogs::LogRecord());
+  record->SetTimestamp(now);
+  record->SetSeverity(logs_api::Severity::kTrace);  // kTrace has enum value of 1
+  record->SetBody("Message");
+
+  // Log a record to cout
+  exporter->Export(nostd::span<std::unique_ptr<sdklogs::Recordable>>(&record, 1));
+
+  // Reset cout's original stringstream buffer
+  std::cout.rdbuf(original);
+
+  std::vector<std::string> expected_output{
+      "{\n"
+      "  timestamp     : " +
+          std::to_string(now.time_since_epoch().count()) +
+          "\n"
+          "  severity_num  : 1\n"
+          "  severity_text : TRACE\n"
+          "  body          : Message\n",
+      "  resource      : \n",
+      "telemetry.sdk.version: " OPENTELEMETRY_VERSION "\n",
+      "telemetry.sdk.name: opentelemetry\n",
+      "telemetry.sdk.language: cpp\n",
+      "  attributes    : \n"
+      "  trace_id      : 00000000000000000000000000000000\n"
+      "  span_id       : 0000000000000000\n"
+      "  trace_flags   : 00\n"
+      "}\n"};
+
+  for (auto &expected : expected_output)
+  {
+    ASSERT_NE(output.str().find(expected), std::string::npos);
+  }
+}
+
+// ---------------------------------- Print to cerr --------------------------
+
+// Testing what a log record with only the "resource" and "attributes" fields
+// (i.e. KeyValueIterable types) set with primitive types, will print out
+TEST(OStreamLogExporter, LogWithStringAttributesToCerr)
+{
+  // Initialize an Ostream exporter to cerr
+  auto exporter =
+      std::unique_ptr<sdklogs::LogExporter>(new exporterlogs::OStreamLogExporter(std::cerr));
+
+  // Save original stream buffer, then redirect cout to our new stream buffer
+  std::streambuf *original = std::cerr.rdbuf();
+  std::stringstream stdcerrOutput;
+  std::cerr.rdbuf(stdcerrOutput.rdbuf());
+
+  // Pass a recordable created by the exporter to be exported
+  auto record = exporter->MakeRecordable();
+
+  // Set resources for this log record only of type <string, string>
+  auto resource = opentelemetry::sdk::resource::Resource::Create({{"key1", "val1"}});
+  record->SetResource(resource);
+
+  // Set attributes to this log record of type <string, AttributeValue>
+  record->SetAttribute("a", true);
+
+  // Log record to cerr
+  exporter->Export(nostd::span<std::unique_ptr<sdklogs::Recordable>>(&record, 1));
+
+  // Reset cerr's original stringstream buffer
+  std::cerr.rdbuf(original);
+
+  std::vector<std::string> expected_output{
+      "{\n"
+      "  timestamp     : 0\n"
+      "  severity_num  : 0\n"
+      "  severity_text : INVALID\n"
+      "  body          : \n",
+      "  resource      : \n",
+      "telemetry.sdk.version: " OPENTELEMETRY_VERSION "\n",
+      "telemetry.sdk.name: opentelemetry\n",
+      "telemetry.sdk.language: cpp\n",
+      "service.name: unknown_service\n",
+      "key1: val1\n",
+      "  attributes    : \n",
+      "\ta: 1\n",
+      "  trace_id      : 00000000000000000000000000000000\n"
+      "  span_id       : 0000000000000000\n"
+      "  trace_flags   : 00\n"
+      "}\n"};
+
+  for (auto &expected : expected_output)
+  {
+    ASSERT_NE(stdcerrOutput.str().find(expected), std::string::npos);
+  }
+}
+
+// ---------------------------------- Print to clog -------------------------
+
+// Testing what a log record with only the "resource", and "attributes" fields
+// (i.e. KeyValueIterable types), set with 2D arrays as values, will print out
+TEST(OStreamLogExporter, LogWithVariantTypesToClog)
+{
+
+  // Initialize an Ostream exporter to cerr
+  auto exporter =
+      std::unique_ptr<sdklogs::LogExporter>(new exporterlogs::OStreamLogExporter(std::clog));
+
+  // Save original stream buffer, then redirect cout to our new stream buffer
+  std::streambuf *original = std::clog.rdbuf();
+  std::stringstream stdclogOutput;
+  std::clog.rdbuf(stdclogOutput.rdbuf());
+
+  // Pass a recordable created by the exporter to be exported
+  auto record = exporter->MakeRecordable();
+
+  // Set resources for this log record of only integer types as the value
+  std::array<int, 3> array1 = {1, 2, 3};
+  nostd::span<int> data1{array1.data(), array1.size()};
+
+  auto resource = opentelemetry::sdk::resource::Resource::Create({{"res1", data1}});
+  record->SetResource(resource);
+
+  // Set resources for this log record of bool types as the value
+  // e.g. key/value is a par of type <string, array of bools>
+  std::array<bool, 3> array = {false, true, false};
+  record->SetAttribute("attr1", nostd::span<bool>{array.data(), array.size()});
+
+  // Log a record to clog
+  exporter->Export(nostd::span<std::unique_ptr<sdklogs::Recordable>>(&record, 1));
+
+  // Reset clog's original stringstream buffer
+  std::clog.rdbuf(original);
+
+  std::vector<std::string> expected_output{
+      "{\n"
+      "  timestamp     : 0\n"
+      "  severity_num  : 0\n"
+      "  severity_text : INVALID\n"
+      "  body          : \n",
+      "  resource      : \n",
+      "service.name: unknown_service\n",
+      "telemetry.sdk.version: " OPENTELEMETRY_VERSION "\n",
+      "telemetry.sdk.name: opentelemetry\n",
+      "telemetry.sdk.language: cpp\n",
+      "res1: [1,2,3]\n",
+      "attributes    : \n",
+      "\tattr1: [0,1,0]\n"
+      "  trace_id      : 00000000000000000000000000000000\n"
+      "  span_id       : 0000000000000000\n"
+      "  trace_flags   : 00\n"
+      "}\n"};
+
+  for (auto &expected : expected_output)
+  {
+    ASSERT_NE(stdclogOutput.str().find(expected), std::string::npos);
+  }
+}
+
+// // ---------------------------------- Integration Tests -------------------------
+
+// Test using the simple log processor and ostream exporter to cout
+// and use the rest of the logging pipeline (Logger, LoggerProvider, Provider) as well
+TEST(OStreamLogExporter, IntegrationTest)
+{
+  // Initialize a logger
+  auto exporter    = std::unique_ptr<sdklogs::LogExporter>(new exporterlogs::OStreamLogExporter);
+  auto sdkProvider = std::shared_ptr<sdklogs::LoggerProvider>(new sdklogs::LoggerProvider());
+  sdkProvider->AddProcessor(
+      std::unique_ptr<sdklogs::LogProcessor>(new sdklogs::SimpleLogProcessor(std::move(exporter))));
+  auto apiProvider = nostd::shared_ptr<logs_api::LoggerProvider>(sdkProvider);
+  auto provider    = nostd::shared_ptr<logs_api::LoggerProvider>(apiProvider);
+  logs_api::Provider::SetLoggerProvider(provider);
+  const std::string schema_url{"https://opentelemetry.io/schemas/1.11.0"};
+  auto logger = logs_api::Provider::GetLoggerProvider()->GetLogger(
+      "Logger", "", "opentelelemtry_library", "", schema_url);
+
+  // Back up cout's streambuf
+  std::streambuf *original = std::cout.rdbuf();
+
+  // Redirect cout to our string stream
+  std::stringstream stdcoutOutput;
+  std::cout.rdbuf(stdcoutOutput.rdbuf());
+
+  // Write a log to ostream exporter
+  common::SystemTimestamp now(std::chrono::system_clock::now());
+  logger->Log(logs_api::Severity::kDebug, "Hello", {}, {}, {}, {}, now);
+
+  // Restore cout's original streambuf
+  std::cout.rdbuf(original);
+
+  // Compare actual vs expected outputs
+  std::vector<std::string> expected_output{
+      "{\n"
+      "  timestamp     : " +
+          std::to_string(now.time_since_epoch().count()) +
+          "\n"
+          "  severity_num  : 5\n"
+          "  severity_text : DEBUG\n"
+          "  body          : Hello\n",
+      "  resource      : \n",
+      "telemetry.sdk.version: " OPENTELEMETRY_VERSION "\n",
+      "service.name: unknown_service\n",
+      "telemetry.sdk.name: opentelemetry\n",
+      "telemetry.sdk.language: cpp\n",
+      "  attributes    : \n"
+      "  trace_id      : 00000000000000000000000000000000\n"
+      "  span_id       : 0000000000000000\n"
+      "  trace_flags   : 00\n"
+      "}\n"};
+
+  for (auto &expected : expected_output)
+  {
+    ASSERT_NE(stdcoutOutput.str().find(expected), std::string::npos);
+  }
+}
+
+}  // namespace logs
+}  // namespace exporter
+OPENTELEMETRY_END_NAMESPACE
+#endif