-
Notifications
You must be signed in to change notification settings - Fork 447
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WIP] W3C tracecontext #9
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
/* this file will be removed once we have unit test and CI */ | ||
|
||
#include <stdio.h> | ||
|
||
#include "traceparent.h" | ||
#include "tracestate.h" | ||
|
||
int main(int argc, char* argv[]) | ||
{ | ||
TraceParent trace_parent; | ||
status_t retval = trace_parent_from_string(&trace_parent, "00-12345678901234567890123456789012-1234567890123456-01"); | ||
printf("Hello, World! %d\n", retval); | ||
return 0; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
/* Copyright 2019, OpenTelemetry Authors | ||
|
||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
|
||
http://www.apache.org/licenses/LICENSE-2.0 | ||
|
||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
#include "traceparent.h" | ||
|
||
status_t _uint_from_hex_string(unsigned int* value, const char* s) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Technically "status_t" not a POSIX standard type.. I think many good open source libraries don't necessarily follow that rule, e.g.
But the best practice would probably either avoid using t suffix, or ensure that all C-API types have a unique prefix, such as otel or at least ot There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I vote for not using *_t suffix on our datatypes. I'd prefer There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Length check is covered here (by checking if c is not
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
char c = s[0]; | ||
unsigned int result; | ||
|
||
if (c >= '0' && c <= '9') | ||
{ | ||
result = c - '0'; | ||
} | ||
else if (c >= 'a' && c <= 'f') | ||
{ | ||
result = c - 'a' + 10; | ||
} | ||
else | ||
{ | ||
return STATUS_ERROR_INPUT_ILLEGAL; | ||
} | ||
result <<= 4; | ||
c = s[1]; | ||
if (c >= '0' && c <= '9') | ||
{ | ||
result += c - '0'; | ||
} | ||
else if (c >= 'a' && c <= 'f') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Traceparent only allows lower case hex digits: https://www.w3.org/TR/trace-context/#traceparent-header-field-values
Good idea. I was originally trying to see if we want to target C89 (which doesn't have inline). |
||
{ | ||
result += c - 'a' + 10; | ||
} | ||
else | ||
{ | ||
return STATUS_ERROR_INPUT_ILLEGAL; | ||
} | ||
*value = result; | ||
|
||
return STATUS_OK; | ||
} | ||
|
||
status_t _trace_parent_from_string(TraceParent* trace_parent, const char* s) | ||
{ | ||
unsigned int value; | ||
/* if this function failed, trace_parent could be polluted, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should establish the convention across APIs. |
||
do we want to take a copy (perf sucks)? | ||
*/ | ||
IF_ERROR_RETURN(_uint_from_hex_string(&value, s)); | ||
trace_parent->version = value; | ||
s += 2; | ||
IF_FALSE_RETURN('-' == *s, STATUS_ERROR_INPUT_ILLEGAL) | ||
s += 1; | ||
for (int i = 0; i < 16; i++) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd use |
||
{ | ||
IF_ERROR_RETURN(_uint_from_hex_string(&value, s)); | ||
trace_parent->trace_id[i] = value; | ||
s += 2; | ||
} | ||
IF_FALSE_RETURN('-' == *s, STATUS_ERROR_INPUT_ILLEGAL) | ||
s += 1; | ||
for (int i = 0; i < 8; i++) | ||
{ | ||
IF_ERROR_RETURN(_uint_from_hex_string(&value, s)); | ||
trace_parent->parent_id[i] = value; | ||
s += 2; | ||
} | ||
IF_FALSE_RETURN('-' == *s, STATUS_ERROR_INPUT_ILLEGAL) | ||
s += 1; | ||
IF_ERROR_RETURN(_uint_from_hex_string(&value, s)); | ||
trace_parent->trace_flags = value; | ||
s += 2; | ||
IF_FALSE_RETURN(('-' == *s || ('\0' == *s)), STATUS_ERROR_INPUT_ILLEGAL) | ||
return STATUS_OK; | ||
} | ||
|
||
status_t _trace_parent_to_string(const TraceParent* trace_parent, char* s) | ||
{ | ||
return STATUS_ERROR_UNKNOWN; | ||
} | ||
|
||
status_t trace_parent_from_string(TraceParent* trace_parent, const char* s) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Personally I'm in favor of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should base these functions off of a back-ported string_view instead of using null terminated strings (i.e. we copy an implementation of string_view that's compatible with c++17's string_view; we can even opt in to std::string_view like absl if they're using c++17+). Lots of systems don't use null terminated strings (for example nginx, lua) So having the api require a null-terminated c-style string would require users to make a copy before calling the function. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Instead of debating convention on a case-by-case basis, could we use #5 to adopt one of the standard naming conventions globally and then redo the code to match that. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm very much in favor of string_view. Also in favor of PascalCase, we can discuss that in #5 if it's more appropriate. |
||
{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this intended to be the public version which checks the input arguments? I don't see length checks for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Length check is covered by detecting |
||
IF_FALSE_RETURN(trace_parent, STATUS_ERROR_INPUT_NULL_PTR) | ||
IF_FALSE_RETURN(s, STATUS_ERROR_INPUT_NULL_PTR) | ||
|
||
return _trace_parent_from_string(trace_parent, s); | ||
} | ||
|
||
status_t trace_parent_to_string(const TraceParent* trace_parent, char* s) | ||
{ | ||
IF_FALSE_RETURN(trace_parent, STATUS_ERROR_INPUT_NULL_PTR) | ||
IF_FALSE_RETURN(s, STATUS_ERROR_INPUT_NULL_PTR) | ||
|
||
return _trace_parent_to_string(trace_parent, s); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
/* Copyright 2019, OpenTelemetry Authors | ||
|
||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
|
||
http://www.apache.org/licenses/LICENSE-2.0 | ||
|
||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
#ifndef OPENTELEMETRY_CONTEXT_TRACEPARENT_H_ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (this came up in the meeting) At least Ryan and I are fans of Do we need to support older compilers where we need to use the header guard? If so, which ones? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've never seen a compiler that doesn't support it. Looking at the portability section of https://en.wikipedia.org/wiki/Pragma_once even old Sun and IBM compilers work with it. I'd say adopt it -- you can always change to include guards if someone complains. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I vote for the pragma then. :) |
||
#define OPENTELEMETRY_CONTEXT_TRACEPARENT_H_ | ||
|
||
#include "../status.h" | ||
|
||
#ifdef __cplusplus | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would like the headers to be C++. The C wrapper should live somewhere else. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Re. headers - there is no official Cpp Core Guideline on how to name the headers (some people even prefer .h for c++ code). But I personally find it easier to navigate thru source code directory when the filename is telling what compiler it's gonna be compiled with: like .c|.h for C, .cpp|.hpp for C++ (or .cc|.hh, or .cxx|.hxx, depending on one's personal preference). I agree that the headers must be c++ by default, with an optional pure C projection of some sort. And the header filename should explicitly express what language it is for.. |
||
namespace opentelemetry { | ||
namespace context { | ||
extern "C" { | ||
#endif | ||
|
||
#pragma pack(push, 1) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This might not work with some compilers. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we shouldn't rely on This shouldn't be an issue since no-one should be serializing data by There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's purpose of packing TraceParent struct? |
||
typedef struct | ||
{ | ||
uint8_t version; | ||
uint8_t trace_id[16]; | ||
uint8_t parent_id[8]; | ||
uint8_t trace_flags; | ||
} TraceParent; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this should be a
|
||
#pragma pack(pop) | ||
|
||
/* unchecked version */ | ||
status_t _trace_parent_from_string(TraceParent* trace_parent, const char* s); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The unchecked version doesn't validate input (e.g. nullptr), which gives perf benefit when used internally (e.g. the caller already validated the input). |
||
status_t _trace_parent_to_string(const TraceParent* trace_parent, char* s); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My understanding is that function names starting with underscore are reserved (by naming convention) for "standard library" functions. |
||
|
||
/* checked version */ | ||
status_t trace_parent_from_string(TraceParent* trace_parent, const char* s); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would suggest keeping the public API small and only having the checked version. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Makes sense. All the public API should validate input. |
||
status_t trace_parent_to_string(const TraceParent* trace_parent, char* s); | ||
|
||
#ifdef __cplusplus | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wasn't there a decision that this is going to be a C++ library and a C library can be implemented later which will wrap this one? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It was unclear at the moment I was preparing the PR. |
||
} /* extern "C" */ | ||
} /* namespace context */ | ||
} /* namespace opentelemetry */ | ||
#endif | ||
|
||
#endif /* OPENTELEMETRY_CONTEXT_TRACEPARENT_H_ */ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
/* Copyright 2019, OpenTelemetry Authors | ||
|
||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
|
||
http://www.apache.org/licenses/LICENSE-2.0 | ||
|
||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
#include "tracestate.h" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
/* Copyright 2019, OpenTelemetry Authors | ||
|
||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
|
||
http://www.apache.org/licenses/LICENSE-2.0 | ||
|
||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
#ifndef OPENTELEMETRY_CONTEXT_TRACESTATE_H_ | ||
#define OPENTELEMETRY_CONTEXT_TRACESTATE_H_ | ||
|
||
#include "../status.h" | ||
|
||
#ifdef __cplusplus | ||
namespace opentelemetry { | ||
namespace context { | ||
extern "C" { | ||
#endif | ||
|
||
#ifdef __cplusplus | ||
} /* extern "C" */ | ||
} /* namespace context */ | ||
} /* namespace opentelemetry */ | ||
#endif | ||
|
||
#endif /* OPENTELEMETRY_CONTEXT_TRACESTATE_H_ */ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
/* Copyright 2019, OpenTelemetry Authors | ||
|
||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
|
||
http://www.apache.org/licenses/LICENSE-2.0 | ||
|
||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
#ifndef OPENTELEMETRY_STATUS_H_ | ||
#define OPENTELEMETRY_STATUS_H_ | ||
|
||
#include <stdint.h> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think |
||
|
||
typedef int32_t status_t; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we're going to use error codes, I'd rather use the standard library's std::error_code. It's somewhat of a pain to work with, but IMO it's still better than rolling your own |
||
|
||
enum { | ||
STATUS_OK = 0, | ||
STATUS_ERROR_UNKNOWN = 0x00010000, | ||
STATUS_ERROR_INPUT_NULL_PTR = 0x00010001, | ||
STATUS_ERROR_INPUT_ILLEGAL = 0x00010002, | ||
}; | ||
|
||
#define IF_ERROR_RETURN(expr) { \ | ||
status_t status = (expr); \ | ||
if (STATUS_OK != status) \ | ||
return status; \ | ||
} | ||
|
||
#define IF_FALSE_RETURN(expr, retval) { \ | ||
if (!(expr)) \ | ||
return (retval); \ | ||
} | ||
|
||
#endif /* OPENTELEMETRY_STATUS_H_ */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would like the implementation to be in C++, not C.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree. This is C++ SIG and implementations should preferably be in C++.