Skip to content

Commit afa2e79

Browse files
author
nikhil1511
authored
Refactoring trace_state to reuse common functionality in baggage (#638)
1 parent 2181b01 commit afa2e79

File tree

9 files changed

+773
-247
lines changed

9 files changed

+773
-247
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,270 @@
1+
// Copyright 2021, OpenTelemetry Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "opentelemetry/common/key_value_iterable_view.h"
16+
#include "opentelemetry/common/string_util.h"
17+
#include "opentelemetry/nostd/function_ref.h"
18+
#include "opentelemetry/nostd/shared_ptr.h"
19+
#include "opentelemetry/nostd/string_view.h"
20+
#include "opentelemetry/nostd/unique_ptr.h"
21+
#include "opentelemetry/version.h"
22+
23+
#include <string>
24+
#include <type_traits>
25+
26+
OPENTELEMETRY_BEGIN_NAMESPACE
27+
namespace common
28+
{
29+
30+
// Constructor parameter for KeyValueStringTokenizer
31+
struct KeyValueStringTokenizerOptions
32+
{
33+
char member_separator = ',';
34+
char key_value_separator = '=';
35+
bool ignore_empty_members = true;
36+
};
37+
38+
// Tokenizer for key-value headers
39+
class KeyValueStringTokenizer
40+
{
41+
public:
42+
KeyValueStringTokenizer(
43+
nostd::string_view str,
44+
const KeyValueStringTokenizerOptions &opts = KeyValueStringTokenizerOptions())
45+
: str_(str), opts_(opts), index_(0)
46+
{}
47+
48+
// Returns next key value in the string header
49+
// @param valid_kv : if the found kv pair is valid or not
50+
// @param key : key in kv pair
51+
// @param key : value in kv pair
52+
// @returns true if next kv pair was found, false otherwise.
53+
bool next(bool &valid_kv, nostd::string_view &key, nostd::string_view &value)
54+
{
55+
valid_kv = true;
56+
while (index_ < str_.size())
57+
{
58+
size_t end = str_.find(opts_.member_separator, index_);
59+
if (end == std::string::npos)
60+
{
61+
end = str_.size() - 1;
62+
}
63+
else
64+
{
65+
end--;
66+
}
67+
68+
auto list_member = StringUtil::Trim(str_, index_, end);
69+
if (list_member.size() == 0)
70+
{
71+
// empty list member
72+
index_ = end + 2;
73+
if (opts_.ignore_empty_members)
74+
{
75+
continue;
76+
}
77+
78+
valid_kv = true;
79+
key = "";
80+
value = "";
81+
return true;
82+
}
83+
84+
auto key_end_pos = list_member.find(opts_.key_value_separator);
85+
if (key_end_pos == std::string::npos)
86+
{
87+
// invalid member
88+
valid_kv = false;
89+
}
90+
else
91+
{
92+
key = list_member.substr(0, key_end_pos);
93+
value = list_member.substr(key_end_pos + 1);
94+
}
95+
96+
index_ = end + 2;
97+
98+
return true;
99+
}
100+
101+
// no more entries remaining
102+
return false;
103+
}
104+
105+
// Returns total number of tokens in header string
106+
size_t NumTokens() const noexcept
107+
{
108+
size_t cnt = 0, begin = 0;
109+
while (begin < str_.size())
110+
{
111+
++cnt;
112+
size_t end = str_.find(opts_.member_separator, begin);
113+
if (end == std::string::npos)
114+
{
115+
break;
116+
}
117+
118+
begin = end + 1;
119+
}
120+
121+
return cnt;
122+
}
123+
124+
// Resets the iterator
125+
void reset() noexcept { index_ = 0; }
126+
127+
private:
128+
nostd::string_view str_;
129+
KeyValueStringTokenizerOptions opts_;
130+
size_t index_;
131+
};
132+
133+
// Class to store fixed size array of key-value pairs of string type
134+
class KeyValueProperties
135+
{
136+
// Class to store key-value pairs of string types
137+
public:
138+
class Entry
139+
{
140+
public:
141+
Entry() : key_(nullptr), value_(nullptr) {}
142+
143+
// Copy constructor
144+
Entry(const Entry &copy)
145+
{
146+
key_ = CopyStringToPointer(copy.key_.get());
147+
value_ = CopyStringToPointer(copy.value_.get());
148+
}
149+
150+
// Copy assignment operator
151+
Entry &operator=(Entry &other)
152+
{
153+
key_ = CopyStringToPointer(other.key_.get());
154+
value_ = CopyStringToPointer(other.value_.get());
155+
return *this;
156+
}
157+
158+
// Move contructor and assignment operator
159+
Entry(Entry &&other) = default;
160+
Entry &operator=(Entry &&other) = default;
161+
162+
// Creates an Entry for a given key-value pair.
163+
Entry(nostd::string_view key, nostd::string_view value)
164+
{
165+
key_ = CopyStringToPointer(key);
166+
value_ = CopyStringToPointer(value);
167+
}
168+
169+
// Gets the key associated with this entry.
170+
nostd::string_view GetKey() const { return key_.get(); }
171+
172+
// Gets the value associated with this entry.
173+
nostd::string_view GetValue() const { return value_.get(); }
174+
175+
// Sets the value for this entry. This overrides the previous value.
176+
void SetValue(nostd::string_view value) { value_ = CopyStringToPointer(value); }
177+
178+
private:
179+
// Store key and value as raw char pointers to avoid using std::string.
180+
nostd::unique_ptr<const char[]> key_;
181+
nostd::unique_ptr<const char[]> value_;
182+
183+
// Copies string into a buffer and returns a unique_ptr to the buffer.
184+
// This is a workaround for the fact that memcpy doesn't accept a const destination.
185+
nostd::unique_ptr<const char[]> CopyStringToPointer(nostd::string_view str)
186+
{
187+
char *temp = new char[str.size() + 1];
188+
memcpy(temp, str.data(), str.size());
189+
temp[str.size()] = '\0';
190+
return nostd::unique_ptr<const char[]>(temp);
191+
}
192+
};
193+
194+
// Maintain the number of entries in entries_.
195+
size_t num_entries_;
196+
197+
// Max size of allocated array
198+
size_t max_num_entries_;
199+
200+
// Store entries in a C-style array to avoid using std::array or std::vector.
201+
nostd::unique_ptr<Entry[]> entries_;
202+
203+
public:
204+
// Create Key-value list of given size
205+
// @param size : Size of list.
206+
KeyValueProperties(size_t size)
207+
: num_entries_(0), max_num_entries_(size), entries_(new Entry[size])
208+
{}
209+
210+
// Create Empty Key-Value list
211+
KeyValueProperties() : num_entries_(0), max_num_entries_(0), entries_(nullptr) {}
212+
213+
template <class T, class = typename std::enable_if<detail::is_key_value_iterable<T>::value>::type>
214+
KeyValueProperties(const T &keys_and_values)
215+
: num_entries_(0),
216+
max_num_entries_(keys_and_values.size()),
217+
entries_(new Entry[max_num_entries_])
218+
{
219+
for (auto &e : keys_and_values)
220+
{
221+
Entry entry(e.first, e.second);
222+
(entries_.get())[num_entries_++] = std::move(entry);
223+
}
224+
}
225+
226+
// Adds new kv pair into kv properties
227+
void AddEntry(const nostd::string_view &key, const nostd::string_view &value)
228+
{
229+
if (num_entries_ < max_num_entries_)
230+
{
231+
Entry entry(key, value);
232+
(entries_.get())[num_entries_++] = std::move(entry);
233+
}
234+
}
235+
236+
// Returns all kv pair entries
237+
bool GetAllEntries(
238+
nostd::function_ref<bool(nostd::string_view, nostd::string_view)> callback) const
239+
{
240+
for (size_t i = 0; i < num_entries_; i++)
241+
{
242+
auto &entry = (entries_.get())[i];
243+
if (!callback(entry.GetKey(), entry.GetValue()))
244+
{
245+
return false;
246+
}
247+
}
248+
return true;
249+
}
250+
251+
// Return value for key if exists, return false otherwise
252+
bool GetValue(const nostd::string_view key, std::string &value) const
253+
{
254+
for (size_t i = 0; i < num_entries_; i++)
255+
{
256+
auto &entry = (entries_.get())[i];
257+
if (entry.GetKey() == key)
258+
{
259+
const auto &entry_value = entry.GetValue();
260+
value = std::string(entry_value.data(), entry_value.size());
261+
return true;
262+
}
263+
}
264+
return false;
265+
}
266+
267+
size_t Size() const noexcept { return num_entries_; }
268+
};
269+
} // namespace common
270+
OPENTELEMETRY_END_NAMESPACE
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright 2021, OpenTelemetry Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#pragma once
16+
17+
#include "opentelemetry/nostd/string_view.h"
18+
19+
OPENTELEMETRY_BEGIN_NAMESPACE
20+
namespace common
21+
{
22+
23+
class StringUtil
24+
{
25+
public:
26+
static nostd::string_view Trim(nostd::string_view str, size_t left, size_t right)
27+
{
28+
while (str[static_cast<std::size_t>(left)] == ' ' && left <= right)
29+
{
30+
left++;
31+
}
32+
while (str[static_cast<std::size_t>(right)] == ' ' && left <= right)
33+
{
34+
right--;
35+
}
36+
return str.substr(left, 1 + right - left);
37+
}
38+
};
39+
40+
} // namespace common
41+
42+
OPENTELEMETRY_END_NAMESPACE

0 commit comments

Comments
 (0)