From f13b78dce8e83c20afd8f41ca73d26e4e4e8a323 Mon Sep 17 00:00:00 2001
From: Lalit <labhas@microsoft.com>
Date: Tue, 17 May 2022 00:13:01 -0700
Subject: [PATCH 1/5] add attributes/dimensions to metric exporter

---
 .../exporters/ostream/common_utils.h          |  74 +++++++++++++
 .../exporters/ostream/log_exporter.h          |   3 +
 .../exporters/ostream/metric_exporter.h       |   1 +
 .../exporters/ostream/span_exporter.h         |  62 -----------
 exporters/ostream/src/log_exporter.cc         | 100 +++---------------
 exporters/ostream/src/metric_exporter.cc      |  20 +++-
 exporters/ostream/src/span_exporter.cc        |   4 +-
 exporters/ostream/test/ostream_log_test.cc    |  62 +++++------
 exporters/ostream/test/ostream_metric_test.cc |  19 +++-
 9 files changed, 162 insertions(+), 183 deletions(-)
 create mode 100644 exporters/ostream/include/opentelemetry/exporters/ostream/common_utils.h

diff --git a/exporters/ostream/include/opentelemetry/exporters/ostream/common_utils.h b/exporters/ostream/include/opentelemetry/exporters/ostream/common_utils.h
new file mode 100644
index 0000000000..3688c40a52
--- /dev/null
+++ b/exporters/ostream/include/opentelemetry/exporters/ostream/common_utils.h
@@ -0,0 +1,74 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace exporter
+{
+namespace ostream_common
+{
+/*
+  print_value is used to print out the value of an attribute within a vector.
+  These values are held in a variant which makes the process of printing them much more
+  complicated.
+*/
+
+template <typename T>
+void print_value(const T &item, std::ostream &sout)
+{
+  sout << item;
+}
+
+template <typename T>
+void print_value(const std::vector<T> &vec, std::ostream &sout)
+{
+  sout << '[';
+  size_t i  = 1;
+  size_t sz = vec.size();
+  for (auto v : vec)
+  {
+    sout << v;
+    if (i != sz)
+      sout << ',';
+    i++;
+  };
+  sout << ']';
+}
+
+// Prior to C++14, generic lambda is not available so fallback to functor.
+#if __cplusplus < 201402L
+
+class OwnedAttributeValueVisitor
+{
+public:
+  OwnedAttributeValueVisitor(std::ostream &sout) : sout_(sout) {}
+
+  template <typename T>
+  void operator()(T &&arg)
+  {
+    print_value(arg, sout_);
+  }
+
+private:
+  std::ostream &sout_;
+};
+
+#endif
+
+void print_value(const opentelemetry::sdk::common::OwnedAttributeValue &value, std::ostream &sout)
+{
+#if __cplusplus < 201402L
+  opentelemetry::nostd::visit(OwnedAttributeValueVisitor(sout), value);
+#else
+  opentelemetry::nostd::visit(
+      [&sout](auto &&arg) {
+        /* explicit this is needed by some gcc versions (observed with v5.4.0)*/
+        print_value(arg, sout);
+      },
+      value);
+#endif
+}
+
+}  // namespace ostream_common
+}  // namespace exporter
+OPENTELEMETRY_END_NAMESPACE
\ No newline at end of file
diff --git a/exporters/ostream/include/opentelemetry/exporters/ostream/log_exporter.h b/exporters/ostream/include/opentelemetry/exporters/ostream/log_exporter.h
index ad1d54a215..2f6acbb486 100644
--- a/exporters/ostream/include/opentelemetry/exporters/ostream/log_exporter.h
+++ b/exporters/ostream/include/opentelemetry/exporters/ostream/log_exporter.h
@@ -52,6 +52,9 @@ class OStreamLogExporter final : public opentelemetry::sdk::logs::LogExporter
   bool is_shutdown_ = false;
   mutable opentelemetry::common::SpinLockMutex lock_;
   bool isShutdown() const noexcept;
+  void printAttributes(
+      const std::unordered_map<std::string, opentelemetry::sdk::common::OwnedAttributeValue> &map,
+      const std::string prefix = "\n\t");
 };
 }  // namespace logs
 }  // namespace exporter
diff --git a/exporters/ostream/include/opentelemetry/exporters/ostream/metric_exporter.h b/exporters/ostream/include/opentelemetry/exporters/ostream/metric_exporter.h
index 56b6c577b0..e34332d77c 100644
--- a/exporters/ostream/include/opentelemetry/exporters/ostream/metric_exporter.h
+++ b/exporters/ostream/include/opentelemetry/exporters/ostream/metric_exporter.h
@@ -59,6 +59,7 @@ class OStreamMetricExporter final : public opentelemetry::sdk::metrics::MetricEx
   void printInstrumentationInfoMetricData(
       const sdk::metrics::InstrumentationInfoMetrics &info_metrics);
   void printPointData(const opentelemetry::sdk::metrics::PointType &point_data);
+  void printPointAttributes(const opentelemetry::sdk::metrics::PointAttributes &point_attributes);
 };
 }  // namespace metrics
 }  // namespace exporter
diff --git a/exporters/ostream/include/opentelemetry/exporters/ostream/span_exporter.h b/exporters/ostream/include/opentelemetry/exporters/ostream/span_exporter.h
index 8122b6777a..c8603db027 100644
--- a/exporters/ostream/include/opentelemetry/exporters/ostream/span_exporter.h
+++ b/exporters/ostream/include/opentelemetry/exporters/ostream/span_exporter.h
@@ -50,68 +50,6 @@ class OStreamSpanExporter final : public opentelemetry::sdk::trace::SpanExporter
   // Mapping status number to the string from api/include/opentelemetry/trace/canonical_code.h
   std::map<int, std::string> statusMap{{0, "Unset"}, {1, "Ok"}, {2, "Error"}};
 
-  /*
-    print_value is used to print out the value of an attribute within a vector.
-    These values are held in a variant which makes the process of printing them much more
-    complicated.
-  */
-
-  template <typename T>
-  void print_value(const T &item)
-  {
-    sout_ << item;
-  }
-
-  template <typename T>
-  void print_value(const std::vector<T> &vec)
-  {
-    sout_ << '[';
-    size_t i  = 1;
-    size_t sz = vec.size();
-    for (auto v : vec)
-    {
-      sout_ << v;
-      if (i != sz)
-        sout_ << ',';
-      i++;
-    };
-    sout_ << ']';
-  }
-
-// Prior to C++14, generic lambda is not available so fallback to functor.
-#if __cplusplus < 201402L
-
-  class OwnedAttributeValueVisitor
-  {
-  public:
-    OwnedAttributeValueVisitor(OStreamSpanExporter &exporter) : exporter_(exporter) {}
-
-    template <typename T>
-    void operator()(T &&arg)
-    {
-      exporter_.print_value(arg);
-    }
-
-  private:
-    OStreamSpanExporter &exporter_;
-  };
-
-#endif
-
-  void print_value(const opentelemetry::sdk::common::OwnedAttributeValue &value)
-  {
-#if __cplusplus < 201402L
-    opentelemetry::nostd::visit(OwnedAttributeValueVisitor(*this), value);
-#else
-    opentelemetry::nostd::visit(
-        [this](auto &&arg) {
-          /* explicit this is needed by some gcc versions (observed with v5.4.0)*/
-          this->print_value(arg);
-        },
-        value);
-#endif
-  }
-
   // various print helpers
   void printAttributes(
       const std::unordered_map<std::string, opentelemetry::sdk::common::OwnedAttributeValue> &map,
diff --git a/exporters/ostream/src/log_exporter.cc b/exporters/ostream/src/log_exporter.cc
index ef103bb6b2..ace6fd8d96 100644
--- a/exporters/ostream/src/log_exporter.cc
+++ b/exporters/ostream/src/log_exporter.cc
@@ -4,97 +4,20 @@
 #ifdef ENABLE_LOGS_PREVIEW
 #  include "opentelemetry/exporters/ostream/log_exporter.h"
 #  include <mutex>
+#  include "opentelemetry/exporters/ostream/common_utils.h"
 #  include "opentelemetry/sdk_config.h"
 
 #  include <iostream>
 #  include <type_traits>
 
-namespace nostd   = opentelemetry::nostd;
-namespace sdklogs = opentelemetry::sdk::logs;
-
+namespace nostd     = opentelemetry::nostd;
+namespace sdklogs   = opentelemetry::sdk::logs;
+namespace sdkcommon = opentelemetry::sdk::common;
 OPENTELEMETRY_BEGIN_NAMESPACE
 namespace exporter
 {
 namespace logs
 {
-/*********************** Helper functions ************************/
-
-/*
-  print_value is used to print out the value of an attribute within a vector.
-  These values are held in a variant which makes the process of printing them much more
-  complicated.
-*/
-
-template <typename T>
-void print_value(const T &item, std::ostream &sout)
-{
-  sout << item;
-}
-
-template <typename T>
-void print_value(const std::vector<T> &vec, std::ostream &sout)
-{
-  sout << '[';
-  size_t i  = 1;
-  size_t sz = vec.size();
-  for (auto v : vec)
-  {
-    sout << v;
-    if (i != sz)
-      sout << ',' << ' ';
-    i++;
-  };
-  sout << ']';
-}
-
-// Prior to C++14, generic lambda is not available so fallback to functor.
-#  if __cplusplus < 201402L
-
-class OwnedAttributeValueVisitor
-{
-public:
-  OwnedAttributeValueVisitor(std::ostream &sout) : sout_(sout) {}
-
-  template <typename T>
-  void operator()(T &&arg)
-  {
-    print_value(arg, sout_);
-  }
-
-private:
-  // The OStream to send the logs to
-  std::ostream &sout_;
-};
-
-#  endif
-
-void print_value(sdk::common::OwnedAttributeValue &value, std::ostream &sout)
-{
-#  if __cplusplus < 201402L
-  nostd::visit(OwnedAttributeValueVisitor(sout), value);
-#  else
-  nostd::visit([&sout](auto &&arg) { print_value(arg, sout); }, value);
-#  endif
-}
-
-void printMap(std::unordered_map<std::string, sdk::common::OwnedAttributeValue> map,
-              std::ostream &sout)
-{
-  sout << "{";
-  size_t size = map.size();
-  size_t i    = 1;
-  for (auto kv : map)
-  {
-    sout << "{" << kv.first << ": ";
-    print_value(kv.second, sout);
-    sout << "}";
-
-    if (i != size)
-      sout << ", ";
-    i++;
-  }
-  sout << "}";
-}
 
 /*********************** Constructor ***********************/
 
@@ -163,12 +86,12 @@ sdk::common::ExportResult OStreamLogExporter::Export(
           << "  body          : " << log_record->GetBody() << "\n"
           << "  resource      : ";
 
-    printMap(log_record->GetResource().GetAttributes(), sout_);
+    printAttributes(log_record->GetResource().GetAttributes());
 
     sout_ << "\n"
           << "  attributes    : ";
 
-    printMap(log_record->GetAttributes(), sout_);
+    printAttributes(log_record->GetAttributes());
 
     sout_ << "\n"
           << "  trace_id      : " << std::string(trace_id, trace_id_len) << "\n"
@@ -193,6 +116,17 @@ bool OStreamLogExporter::isShutdown() const noexcept
   return is_shutdown_;
 }
 
+void OStreamLogExporter::printAttributes(
+    const std::unordered_map<std::string, sdkcommon::OwnedAttributeValue> &map,
+    const std::string prefix)
+{
+  for (const auto &kv : map)
+  {
+    sout_ << prefix << kv.first << ": ";
+    opentelemetry::exporter::ostream_common::print_value(kv.second, sout_);
+  }
+}
+
 }  // namespace logs
 }  // namespace exporter
 OPENTELEMETRY_END_NAMESPACE
diff --git a/exporters/ostream/src/metric_exporter.cc b/exporters/ostream/src/metric_exporter.cc
index 18e73a310c..2e90e0845b 100644
--- a/exporters/ostream/src/metric_exporter.cc
+++ b/exporters/ostream/src/metric_exporter.cc
@@ -4,6 +4,7 @@
 #include <chrono>
 #ifndef ENABLE_METRICS_PREVIEW
 #  include <algorithm>
+#  include "opentelemetry/exporters/ostream/common_utils.h"
 #  include "opentelemetry/exporters/ostream/metric_exporter.h"
 #  include "opentelemetry/sdk/metrics/aggregation/default_aggregation.h"
 #  include "opentelemetry/sdk/metrics/aggregation/histogram_aggregation.h"
@@ -102,7 +103,11 @@ void OStreamMetricExporter::printInstrumentationInfoMetricData(
 
     for (const auto &pd : record.point_data_attr_)
     {
-      printPointData(pd.point_data);
+      if (!nostd::holds_alternative<sdk::metrics::DropPointData>(pd.point_data))
+      {
+        printPointData(pd.point_data);
+        printPointAttributes(pd.attributes);
+      }
     }
   }
   sout_ << "\n}\n";
@@ -171,8 +176,17 @@ void OStreamMetricExporter::printPointData(const opentelemetry::sdk::metrics::Po
       sout_ << nostd::get<long>(last_point_data.value_);
     }
   }
-  else if (nostd::holds_alternative<sdk::metrics::DropPointData>(point_data))
-  {}
+}
+
+void OStreamMetricExporter::printPointAttributes(
+    const opentelemetry::sdk::metrics::PointAttributes &point_attributes)
+{
+  sout_ << "\n  attributes\t\t: ";
+  for (const auto &kv : point_attributes)
+  {
+    sout_ << "\n\t" << kv.first << ": ";
+    opentelemetry::exporter::ostream_common::print_value(kv.second, sout_);
+  }
 }
 
 bool OStreamMetricExporter::ForceFlush(std::chrono::microseconds timeout) noexcept
diff --git a/exporters/ostream/src/span_exporter.cc b/exporters/ostream/src/span_exporter.cc
index dea72f57f8..226f987378 100644
--- a/exporters/ostream/src/span_exporter.cc
+++ b/exporters/ostream/src/span_exporter.cc
@@ -2,6 +2,8 @@
 // SPDX-License-Identifier: Apache-2.0
 
 #include "opentelemetry/exporters/ostream/span_exporter.h"
+#include "opentelemetry/exporters/ostream/common_utils.h"
+
 #include <iostream>
 #include <mutex>
 #include "opentelemetry/sdk_config.h"
@@ -115,7 +117,7 @@ void OStreamSpanExporter::printAttributes(
   for (const auto &kv : map)
   {
     sout_ << prefix << kv.first << ": ";
-    print_value(kv.second);
+    opentelemetry::exporter::ostream_common::print_value(kv.second, sout_);
   }
 }
 
diff --git a/exporters/ostream/test/ostream_log_test.cc b/exporters/ostream/test/ostream_log_test.cc
index e5eaa7ef67..b689035da0 100644
--- a/exporters/ostream/test/ostream_log_test.cc
+++ b/exporters/ostream/test/ostream_log_test.cc
@@ -81,11 +81,11 @@ TEST(OstreamLogExporter, DefaultLogRecordToCout)
       "  severity_text : INVALID\n"
       "  name          : \n"
       "  body          : \n",
-      "  resource      : {",
-      "{telemetry.sdk.version: " OPENTELEMETRY_VERSION "}",
-      "{telemetry.sdk.name: opentelemetry}",
-      "{telemetry.sdk.language: cpp}",
-      "  attributes    : {}\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"
@@ -135,11 +135,11 @@ TEST(OStreamLogExporter, SimpleLogToCout)
           "  severity_text : TRACE\n"
           "  name          : Name\n"
           "  body          : Message\n",
-      "  resource      : {",
-      "{telemetry.sdk.version: " OPENTELEMETRY_VERSION "}",
-      "{telemetry.sdk.name: opentelemetry}",
-      "{telemetry.sdk.language: cpp}",
-      "  attributes    : {}\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"
@@ -189,13 +189,14 @@ TEST(OStreamLogExporter, LogWithStringAttributesToCerr)
       "  severity_text : INVALID\n"
       "  name          : \n"
       "  body          : \n",
-      "  resource      : {",
-      "{telemetry.sdk.version: " OPENTELEMETRY_VERSION "}",
-      "{telemetry.sdk.name: opentelemetry}",
-      "{telemetry.sdk.language: cpp}",
-      "{service.name: unknown_service}",
-      "{key1: val1}",
-      "  attributes    : {{a: 1}}\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",
+      "a: 1\n",
       "  trace_id      : 00000000000000000000000000000000\n"
       "  span_id       : 0000000000000000\n"
       "  trace_flags   : 00\n"
@@ -251,13 +252,14 @@ TEST(OStreamLogExporter, LogWithVariantTypesToClog)
       "  severity_text : INVALID\n"
       "  name          : \n"
       "  body          : \n",
-      "  resource      : {",
-      "{service.name: unknown_service}",
-      "{telemetry.sdk.version: " OPENTELEMETRY_VERSION "}",
-      "{telemetry.sdk.name: opentelemetry}",
-      "{telemetry.sdk.language: cpp}",
-      "{res1: [1, 2, 3]}",
-      "  attributes    : {{attr1: [0, 1, 0]}}\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",
+      "attr1: [0,1,0]\n"
       "  trace_id      : 00000000000000000000000000000000\n"
       "  span_id       : 0000000000000000\n"
       "  trace_flags   : 00\n"
@@ -311,12 +313,12 @@ TEST(OStreamLogExporter, IntegrationTest)
           "  severity_text : DEBUG\n"
           "  name          : \n"
           "  body          : Hello\n",
-      "  resource      : {",
-      "{telemetry.sdk.version: " OPENTELEMETRY_VERSION "}",
-      "{service.name: unknown_service}",
-      "{telemetry.sdk.name: opentelemetry}",
-      "{telemetry.sdk.language: cpp}",
-      "  attributes    : {}\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"
diff --git a/exporters/ostream/test/ostream_metric_test.cc b/exporters/ostream/test/ostream_metric_test.cc
index 82c1be2bc7..45d6d8f882 100644
--- a/exporters/ostream/test/ostream_metric_test.cc
+++ b/exporters/ostream/test/ostream_metric_test.cc
@@ -50,8 +50,8 @@ TEST(OStreamMetricsExporter, ExportSumPointData)
                                        metric_sdk::InstrumentValueType::kDouble},
       opentelemetry::common::SystemTimestamp{}, opentelemetry::common::SystemTimestamp{},
       std::vector<metric_sdk::PointDataAttributes>{
-          {metric_sdk::PointAttributes{}, sum_point_data},
-          {metric_sdk::PointAttributes{}, sum_point_data2}}};
+          {metric_sdk::PointAttributes{{"a1", "b1"}}, sum_point_data},
+          {metric_sdk::PointAttributes{{"a1", "b1"}}, sum_point_data2}}};
   data.instrumentation_info_metric_data_ = std::vector<metric_sdk::InstrumentationInfoMetrics>{
       {instrumentation_library.get(), std::vector<metric_sdk::MetricData>{metric_data}}};
 
@@ -75,8 +75,12 @@ TEST(OStreamMetricsExporter, ExportSumPointData)
       "\n  unit\t\t: unit"
       "\n  type\t\t: SumPointData"
       "\n  value\t\t: 10"
+      "\n  attributes\t\t: "
+      "\n\ta1: b1"
       "\n  type\t\t: SumPointData"
       "\n  value\t\t: 20"
+      "\n  attributes\t\t: "
+      "\n\ta1: b1"
       "\n}\n";
   ASSERT_EQ(stdoutOutput.str(), expected_output);
 }
@@ -109,8 +113,8 @@ TEST(OStreamMetricsExporter, ExportHistogramPointData)
                                        metric_sdk::InstrumentValueType::kDouble},
       opentelemetry::common::SystemTimestamp{}, opentelemetry::common::SystemTimestamp{},
       std::vector<metric_sdk::PointDataAttributes>{
-          {metric_sdk::PointAttributes{}, histogram_point_data},
-          {metric_sdk::PointAttributes{}, histogram_point_data2}}};
+          {metric_sdk::PointAttributes{{"a1", "b1"}, {"a2", "b2"}}, histogram_point_data},
+          {metric_sdk::PointAttributes{{"a1", "b1"}}, histogram_point_data2}}};
   data.instrumentation_info_metric_data_ = std::vector<metric_sdk::InstrumentationInfoMetrics>{
       {instrumentation_library.get(), std::vector<metric_sdk::MetricData>{metric_data}}};
 
@@ -137,11 +141,16 @@ TEST(OStreamMetricsExporter, ExportHistogramPointData)
       "\n  sum     : 900.5"
       "\n  buckets     : [10.1, 20.2, 30.2, ]"
       "\n  counts     : [200, 300, 400, 500, ]"
+      "\n  attributes\t\t: "
+      "\n\ta1: b1"
+      "\n\ta2: b2"
       "\n  type     : HistogramPointData"
       "\n  count     : 3"
       "\n  sum     : 900"
       "\n  buckets     : [10, 20, 30, ]"
       "\n  counts     : [200, 300, 400, 500, ]"
+      "\n  attributes\t\t: "
+      "\n\ta1: b1"
       "\n}\n";
   ASSERT_EQ(stdoutOutput.str(), expected_output);
 }
@@ -199,10 +208,12 @@ TEST(OStreamMetricsExporter, ExportLastValuePointData)
       "\n  timestamp     : 0"
       "\n  valid     : true"
       "\n  value     : 10"
+      "\n  attributes\t\t: "
       "\n  type     : LastValuePointData"
       "\n  timestamp     : 0"
       "\n  valid     : true"
       "\n  value     : 20"
+      "\n  attributes\t\t: "
       "\n}\n";
   ASSERT_EQ(stdoutOutput.str(), expected_output);
 }

From 4ba5752c0f759b07d4bbd9804757fc2a4caa23a6 Mon Sep 17 00:00:00 2001
From: Lalit Kumar Bhasin <lalit_fin@yahoo.com>
Date: Tue, 17 May 2022 10:42:46 -0700
Subject: [PATCH 2/5] fix header

---
 .../include/opentelemetry/exporters/ostream/common_utils.h  | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/exporters/ostream/include/opentelemetry/exporters/ostream/common_utils.h b/exporters/ostream/include/opentelemetry/exporters/ostream/common_utils.h
index 3688c40a52..cfebfe8fce 100644
--- a/exporters/ostream/include/opentelemetry/exporters/ostream/common_utils.h
+++ b/exporters/ostream/include/opentelemetry/exporters/ostream/common_utils.h
@@ -1,6 +1,12 @@
 // Copyright The OpenTelemetry Authors
 // SPDX-License-Identifier: Apache-2.0
 
+#include <sstream>
+#include <string>
+#include <vector>
+#include "opentelemetry/nostd/variant.h"
+#include "opentelemetry/sdk/common/attribute_utils.h"
+
 #pragma once
 OPENTELEMETRY_BEGIN_NAMESPACE
 namespace exporter

From e824ab7baa4fba0582fea487e4eb3904d41688e2 Mon Sep 17 00:00:00 2001
From: Lalit Kumar Bhasin <lalit_fin@yahoo.com>
Date: Tue, 17 May 2022 11:26:49 -0700
Subject: [PATCH 3/5] fix bazel

---
 exporters/ostream/BUILD | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/exporters/ostream/BUILD b/exporters/ostream/BUILD
index cca74d6693..917b70450f 100644
--- a/exporters/ostream/BUILD
+++ b/exporters/ostream/BUILD
@@ -6,6 +6,7 @@ cc_library(
         "src/log_exporter.cc",
     ],
     hdrs = [
+        "include/opentelemetry/exporters/ostream/common_utils.h",
         "include/opentelemetry/exporters/ostream/log_exporter.h",
     ],
     strip_include_prefix = "include",
@@ -49,6 +50,7 @@ cc_library(
         "src/metric_exporter.cc",
     ],
     hdrs = [
+        "include/opentelemetry/exporters/ostream/common_utils.h",
         "include/opentelemetry/exporters/ostream/metric_exporter.h",
     ],
     strip_include_prefix = "include",
@@ -93,6 +95,7 @@ cc_library(
         "src/span_exporter.cc",
     ],
     hdrs = [
+        "include/opentelemetry/exporters/ostream/common_utils.h",
         "include/opentelemetry/exporters/ostream/span_exporter.h",
     ],
     strip_include_prefix = "include",

From 6e0ec653e9d9e8c5d3285ebd7d0b144806012291 Mon Sep 17 00:00:00 2001
From: Lalit <labhas@microsoft.com>
Date: Mon, 6 Jun 2022 15:37:37 -0700
Subject: [PATCH 4/5] fix comment

---
 exporters/ostream/test/ostream_log_test.cc | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/exporters/ostream/test/ostream_log_test.cc b/exporters/ostream/test/ostream_log_test.cc
index 6daf3322df..ecbd858600 100644
--- a/exporters/ostream/test/ostream_log_test.cc
+++ b/exporters/ostream/test/ostream_log_test.cc
@@ -192,12 +192,13 @@ TEST(OStreamLogExporter, LogWithStringAttributesToCerr)
       "service.name: unknown_service\n",
       "key1: val1\n",
       "  attributes    : \n",
-      "a: 1\n",
+      "\ta: 1\n",
       "  trace_id      : 00000000000000000000000000000000\n"
       "  span_id       : 0000000000000000\n"
       "  trace_flags   : 00\n"
       "}\n"};
 
+  std::cout << "LALIT:::" << stdcerrOutput.str() << "\n";
   for (auto &expected : expected_output)
   {
     ASSERT_NE(stdcerrOutput.str().find(expected), std::string::npos);
@@ -254,7 +255,7 @@ TEST(OStreamLogExporter, LogWithVariantTypesToClog)
       "telemetry.sdk.language: cpp\n",
       "res1: [1,2,3]\n",
       "attributes    : \n",
-      "attr1: [0,1,0]\n"
+      "\tattr1: [0,1,0]\n"
       "  trace_id      : 00000000000000000000000000000000\n"
       "  span_id       : 0000000000000000\n"
       "  trace_flags   : 00\n"

From 1d473b8ab5dd08c16d2a14be19f41dace0cf2ca3 Mon Sep 17 00:00:00 2001
From: Lalit <labhas@microsoft.com>
Date: Mon, 6 Jun 2022 15:39:51 -0700
Subject: [PATCH 5/5] remove debug prints

---
 exporters/ostream/test/ostream_log_test.cc | 1 -
 1 file changed, 1 deletion(-)

diff --git a/exporters/ostream/test/ostream_log_test.cc b/exporters/ostream/test/ostream_log_test.cc
index ecbd858600..91d8fbf245 100644
--- a/exporters/ostream/test/ostream_log_test.cc
+++ b/exporters/ostream/test/ostream_log_test.cc
@@ -198,7 +198,6 @@ TEST(OStreamLogExporter, LogWithStringAttributesToCerr)
       "  trace_flags   : 00\n"
       "}\n"};
 
-  std::cout << "LALIT:::" << stdcerrOutput.str() << "\n";
   for (auto &expected : expected_output)
   {
     ASSERT_NE(stdcerrOutput.str().find(expected), std::string::npos);