| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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. |
| */ |
| #ifdef ENABLE_TRACING |
| #include "TracingUtility.h" |
| #include <utility> |
| |
| ROCKETMQ_NAMESPACE_BEGIN |
| |
| TracingUtility& TracingUtility::get() { |
| static TracingUtility tracing_utility; |
| return tracing_utility; |
| } |
| |
| const std::string TracingUtility::INVALID_TRACE_ID = "00000000000000000000000000000000"; |
| const std::string TracingUtility::INVALID_SPAN_ID = "0000000000000000"; |
| |
| uint8_t TracingUtility::hexToInt(char c) { |
| if (c >= '0' && c <= '9') { |
| return (int)(c - '0'); |
| } else if (c >= 'a' && c <= 'f') { |
| return (int)(c - 'a' + 10); |
| } else if (c >= 'A' && c <= 'F') { |
| return (int)(c - 'A' + 10); |
| } else { |
| return -1; |
| } |
| } |
| |
| void TracingUtility::generateHexFromString(const std::string& string, int bytes, uint8_t* buf) { |
| const char* str_id = string.data(); |
| for (int i = 0; i < bytes; i++) { |
| int tmp = hexToInt(str_id[i]); |
| if (tmp < 0) { |
| for (int j = 0; j < bytes / 2; j++) { |
| buf[j] = 0; |
| } |
| return; |
| } |
| if (i % 2 == 0) { |
| buf[i / 2] = tmp * 16; |
| } else { |
| buf[i / 2] += tmp; |
| } |
| } |
| } |
| |
| trace::TraceId TracingUtility::generateTraceIdFromString(const std::string& trace_id) { |
| int trace_id_len = kHeaderElementLengths[1]; |
| uint8_t buf[kTraceIdBytes / 2]; |
| uint8_t* b_ptr = buf; |
| TracingUtility::generateHexFromString(trace_id, trace_id_len, b_ptr); |
| return trace::TraceId(buf); |
| } |
| |
| bool TracingUtility::isValidHex(const std::string& str) { |
| for (char i : str) { |
| if (!(i >= '0' && i <= '9') && !(i >= 'a' && i <= 'f')) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| trace::SpanId TracingUtility::generateSpanIdFromString(const std::string& span_id) { |
| int span_id_len = kHeaderElementLengths[2]; |
| uint8_t buf[kSpanIdBytes / 2]; |
| uint8_t* b_ptr = buf; |
| generateHexFromString(span_id, span_id_len, b_ptr); |
| return trace::SpanId(buf); |
| } |
| |
| trace::TraceFlags TracingUtility::generateTraceFlagsFromString(std::string trace_flags) { |
| if (trace_flags.length() > 2) { |
| return trace::TraceFlags(0); // check for invalid length of flags |
| } |
| int tmp1 = hexToInt(trace_flags[0]); |
| int tmp2 = hexToInt(trace_flags[1]); |
| if (tmp1 < 0 || tmp2 < 0) { |
| return trace::TraceFlags(0); // check for invalid char |
| } |
| uint8_t buf = tmp1 * 16 + tmp2; |
| return trace::TraceFlags(buf); |
| } |
| |
| std::string TracingUtility::injectSpanContextToTraceParent(const trace::SpanContext& span_context) { |
| char trace_id[32]; |
| trace::TraceId(span_context.trace_id()).ToLowerBase16(trace_id); |
| char span_id[16]; |
| trace::SpanId(span_context.span_id()).ToLowerBase16(span_id); |
| char trace_flags[2]; |
| trace::TraceFlags(span_context.trace_flags()).ToLowerBase16(trace_flags); |
| // Note: This is only temporary replacement for appendable string |
| std::string hex_string = "00-"; |
| for (char i : trace_id) { |
| hex_string.push_back(i); |
| } |
| hex_string.push_back('-'); |
| for (char i : span_id) { |
| hex_string.push_back(i); |
| } |
| hex_string.push_back('-'); |
| for (char trace_flag : trace_flags) { |
| hex_string.push_back(trace_flag); |
| } |
| return hex_string; |
| } |
| |
| // Assumed that all span context is remote. |
| trace::SpanContext TracingUtility::extractContextFromTraceParent(const std::string& trace_parent) { |
| if (trace_parent.length() != kHeaderSize || trace_parent[kHeaderElementLengths[0]] != '-' || |
| trace_parent[kHeaderElementLengths[0] + kHeaderElementLengths[1] + 1] != '-' || |
| trace_parent[kHeaderElementLengths[0] + kHeaderElementLengths[1] + kHeaderElementLengths[2] + 2] != '-') { |
| // Unresolvable trace_parent header. Returning INVALID span context. |
| return trace::SpanContext(false, false); |
| } |
| std::string version = trace_parent.substr(0, kHeaderElementLengths[0]); |
| std::string trace_id = trace_parent.substr(kHeaderElementLengths[0] + 1, kHeaderElementLengths[1]); |
| std::string span_id = |
| trace_parent.substr(kHeaderElementLengths[0] + kHeaderElementLengths[1] + 2, kHeaderElementLengths[2]); |
| std::string trace_flags = |
| trace_parent.substr(kHeaderElementLengths[0] + kHeaderElementLengths[1] + kHeaderElementLengths[2] + 3); |
| |
| if (version == "ff" || trace_id == INVALID_TRACE_ID || span_id == INVALID_SPAN_ID) { |
| return trace::SpanContext(false, false); |
| } |
| |
| // validate ids |
| if (!TracingUtility::isValidHex(version) || !TracingUtility::isValidHex(trace_id) || |
| !TracingUtility::isValidHex(span_id) || !TracingUtility::isValidHex(trace_flags)) { |
| return trace::SpanContext(false, false); |
| } |
| |
| trace::TraceId trace_id_obj = TracingUtility::generateTraceIdFromString(trace_id); |
| trace::SpanId span_id_obj = TracingUtility::generateSpanIdFromString(span_id); |
| trace::TraceFlags trace_flags_obj = generateTraceFlagsFromString(trace_flags); |
| return trace::SpanContext(trace_id_obj, span_id_obj, trace_flags_obj, true); |
| } |
| |
| ROCKETMQ_NAMESPACE_END |
| #endif |