1+ //  Copyright The OpenTelemetry Authors
2+ //  SPDX-License-Identifier: Apache-2.0
3+ 
4+ #pragma  once
5+ 
6+ #include  " opentelemetry/common/spin_lock_mutex.h" 
7+ #include  " opentelemetry/common/timestamp.h" 
8+ #include  " opentelemetry/exporters/geneva/metrics/connection_string_parser.h" 
9+ #include  " opentelemetry/exporters/geneva/metrics/data_transport.h" 
10+ #include  " opentelemetry/exporters/geneva/metrics/exporter_options.h" 
11+ #include  " opentelemetry/sdk/metrics/push_metric_exporter.h" 
12+ #include  " opentelemetry/sdk/metrics/data/metric_data.h" 
13+ 
14+ 
15+ OPENTELEMETRY_BEGIN_NAMESPACE
16+ namespace  exporter  {
17+ namespace  geneva  {
18+ namespace  metrics  {
19+ 
20+ constexpr  size_t  kBufferSize  = 65360 ; //  the maximum ETW payload (inclusive)
21+ constexpr  size_t  kMaxDimensionNameSize  = 256 ;
22+ constexpr  size_t  kMaxDimensionValueSize  = 1024 ;
23+ constexpr  size_t  kBinaryHeaderSize  = 4 ; //  event_id (2) + body_length (2)
24+ constexpr  size_t  kMetricPayloadSize  =
25+     24 ; //  count_dimension (2)  + reserverd_word (2) + reserverd_dword(4) +
26+         //  timestamp_utc (8) + metric_data (8)
27+ constexpr  size_t  kExternalPayloadSize  =
28+     40 ; //  count_dimension (2) + reserverd_word (2) + count (4) + timestamp_utc
29+         //  (8) + metric_data_sum (8) + metric_data_min(8) + metric_data_max(8)
30+ 
31+ //  time conversion constants
32+ constexpr  uint32_t  kWindowsTicksPerSecond  =
33+     10000000 ; //  windows ticks are in 100 ns
34+ constexpr  uint64_t  kSecondsToUnixTime  =
35+     11644473600L ; //  number of seconds between windows epoch start
36+                   //  1601-01-01T00:00:00Z and UNIX/Linux epoch
37+                   //  (1970-01-01T00:00:00Z)
38+ 
39+ const  std::string kAttributeNamespaceKey  = " _microsoft_metrics_namespace" 
40+ const  std::string kAttributeAccountKey  = " _microsoft_metrics_account" 
41+ 
42+ using  ValueType = nostd::variant<int64_t , double >;
43+ 
44+ /* *
45+  * The Geneva metrics exporter exports metrics data to Geneva 
46+  */  
47+ class  Exporter  final  : public opentelemetry::sdk::metrics::PushMetricExporter {
48+ public: 
49+   Exporter (const  ExporterOptions &options);
50+ 
51+   opentelemetry::sdk::common::ExportResult
52+   Export (const  opentelemetry::sdk::metrics::ResourceMetrics &data) noexcept 
53+       override ;
54+ 
55+   sdk::metrics::AggregationTemporality GetAggregationTemporality (
56+       sdk::metrics::InstrumentType instrument_type) const  noexcept  override ;
57+ 
58+   bool  ForceFlush (std::chrono::microseconds timeout =
59+                       (std::chrono::microseconds::max)()) noexcept  override ;
60+ 
61+   bool  Shutdown (std::chrono::microseconds timeout =
62+                     (std::chrono::microseconds::max)()) noexcept  override ;
63+ 
64+ private: 
65+   const  ExporterOptions options_;
66+   ConnectionStringParser connection_string_parser_;
67+   const  sdk::metrics::AggregationTemporalitySelector
68+       aggregation_temporality_selector_;
69+   bool  is_shutdown_ = false ;
70+   mutable  opentelemetry::common::SpinLockMutex lock_;
71+   std::unique_ptr<DataTransport> data_transport_;
72+ 
73+   //  metrics storage
74+   char  buffer_[kBufferSize ];
75+ 
76+   size_t  SerializeNonHistogramMetrics (sdk::metrics::AggregationType,
77+                                       MetricsEventType,
78+                                       const  sdk::metrics::ValueType &,
79+                                       common::SystemTimestamp,
80+                                       const  std::string &,
81+                                       const  sdk::metrics::PointAttributes &);
82+   size_t  SerializeHistogramMetrics (
83+       sdk::metrics::AggregationType, MetricsEventType, uint64_t ,
84+       const  sdk::metrics::ValueType &, const  sdk::metrics::ValueType &,
85+       const  sdk::metrics::ValueType &, const  std::vector<double > &boundaries,
86+       const  std::vector<uint64_t > &counts, common::SystemTimestamp,
87+       const  std::string &, const  sdk::metrics::PointAttributes &);
88+ };
89+ 
90+ template  <class  T >
91+ static  void  SerializeInt (char  *buffer, size_t  &index, T value) {
92+   *(reinterpret_cast <T *>(buffer + index)) = value;
93+   index += sizeof (T);
94+ }
95+ 
96+ static  void  SerializeString (char  *buffer, size_t  &index,
97+                             const  std::string &str) {
98+   auto  size = str.size ();
99+   SerializeInt<uint16_t >(buffer, index, static_cast <uint16_t >(size));
100+   if  (size > 0 ) {
101+     memcpy (buffer + index, str.c_str (), size);
102+   }
103+   index += size;
104+ }
105+ 
106+ static  std::string AttributeValueToString (
107+     const  opentelemetry::sdk::common::OwnedAttributeValue &value) {
108+   std::string result;
109+   if  (nostd::holds_alternative<bool >(value)) {
110+     result = nostd::get<bool >(value) ? " true" " false" 
111+   } else  if  (nostd::holds_alternative<int >(value)) {
112+     result = std::to_string (nostd::get<int >(value));
113+   } else  if  (nostd::holds_alternative<int64_t >(value)) {
114+     result = std::to_string (nostd::get<int64_t >(value));
115+   } else  if  (nostd::holds_alternative<unsigned  int >(value)) {
116+     result = std::to_string (nostd::get<unsigned  int >(value));
117+   } else  if  (nostd::holds_alternative<uint64_t >(value)) {
118+     result = std::to_string (nostd::get<uint64_t >(value));
119+   } else  if  (nostd::holds_alternative<double >(value)) {
120+     result = std::to_string (nostd::get<double >(value));
121+   } else  if  (nostd::holds_alternative<std::string>(value)) {
122+     result = nostd::get<std::string>(value);
123+   } else  {
124+     LOG_WARN (" [Geneva Metrics Exporter] AttributeValueToString - " 
125+              "  Nested attributes not supported - ignored" 
126+   }
127+   return  result;
128+ }
129+ 
130+ static  uint64_t  UnixTimeToWindowsTicks (uint64_t  unix_epoch_secs) {
131+   uint64_t  secs_since_windows_epoch = unix_epoch_secs + kSecondsToUnixTime ;
132+   return  (secs_since_windows_epoch * (uint64_t )kWindowsTicksPerSecond );
133+ }
134+ 
135+ } //  namespace metrics
136+ } //  namespace geneva
137+ } //  namespace exporter
138+ OPENTELEMETRY_END_NAMESPACE
0 commit comments