Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions include/istio/control/http/report_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ class ReportData {
// Get response HTTP headers.
virtual std::map<std::string, std::string> GetResponseHeaders() const = 0;

// Get tracing headers from HTTP request headers.
virtual void GetTracingHeaders(
std::map<std::string, std::string> &) const = 0;

// Get additional report info.
struct ReportInfo {
uint64_t response_total_size;
Expand Down
13 changes: 13 additions & 0 deletions include/istio/utils/attributes_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,19 @@ class AttributesBuilder {
}
}

void InsertStringMap(const std::string &key,
const std::map<std::string, std::string> &string_map) {
if (string_map.size() == 0) {
return;
}
auto entries = (*attributes_->mutable_attributes())[key]
.mutable_string_map_value()
->mutable_entries();
for (const auto &map_it : string_map) {
(*entries)[map_it.first] = map_it.second;
}
}

void AddProtoStructStringMap(const std::string &key,
const google::protobuf::Struct &struct_map) {
if (struct_map.fields().empty()) {
Expand Down
4 changes: 2 additions & 2 deletions src/envoy/http/mixer/filter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -232,8 +232,8 @@ void Filter::log(const HeaderMap* request_headers,
CheckData check_data(*request_headers, stream_info.dynamicMetadata(),
decoder_callbacks_->connection());
// response trailer header is not counted to response total size.
ReportData report_data(response_headers, response_trailers, stream_info,
request_total_size_);
ReportData report_data(request_headers, response_headers, response_trailers,
stream_info, request_total_size_);
handler_->Report(&check_data, &report_data);
}

Expand Down
28 changes: 20 additions & 8 deletions src/envoy/http/mixer/report_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "extensions/filters/http/well_known_names.h"
#include "google/protobuf/struct.pb.h"
#include "include/istio/control/http/controller.h"
#include "src/envoy/utils/trace_headers.h"
#include "src/envoy/utils/utils.h"

namespace Envoy {
Expand Down Expand Up @@ -52,22 +53,26 @@ bool ExtractGrpcStatus(const HeaderMap *headers,

class ReportData : public ::istio::control::http::ReportData,
public Logger::Loggable<Logger::Id::filter> {
const HeaderMap *headers_;
const HeaderMap *request_headers_;
const HeaderMap *response_headers_;
const HeaderMap *trailers_;
const StreamInfo::StreamInfo &info_;
uint64_t response_total_size_;
uint64_t request_total_size_;

public:
ReportData(const HeaderMap *headers, const HeaderMap *response_trailers,
ReportData(const HeaderMap *request_headers,
const HeaderMap *response_headers,
const HeaderMap *response_trailers,
const StreamInfo::StreamInfo &info, uint64_t request_total_size)
: headers_(headers),
: request_headers_(request_headers),
response_headers_(response_headers),
trailers_(response_trailers),
info_(info),
response_total_size_(info.bytesSent()),
request_total_size_(request_total_size) {
if (headers != nullptr) {
response_total_size_ += headers->byteSize();
if (response_headers != nullptr) {
response_total_size_ += response_headers->byteSize();
}
if (response_trailers != nullptr) {
response_total_size_ += response_trailers->byteSize();
Expand All @@ -76,15 +81,22 @@ class ReportData : public ::istio::control::http::ReportData,

std::map<std::string, std::string> GetResponseHeaders() const override {
std::map<std::string, std::string> header_map;
if (headers_) {
Utils::ExtractHeaders(*headers_, ResponseHeaderExclusives, header_map);
if (response_headers_) {
Utils::ExtractHeaders(*response_headers_, ResponseHeaderExclusives,
header_map);
}
if (trailers_) {
Utils::ExtractHeaders(*trailers_, ResponseHeaderExclusives, header_map);
}
return header_map;
}

void GetTracingHeaders(
std::map<std::string, std::string> &tracing_headers) const override {
Utils::FindHeaders(*request_headers_, Utils::TracingHeaderSet,
tracing_headers);
}

void GetReportInfo(
::istio::control::http::ReportData::ReportInfo *data) const override {
data->request_body_size = info_.bytesReceived();
Expand Down Expand Up @@ -119,7 +131,7 @@ class ReportData : public ::istio::control::http::ReportData,
// Check trailer first.
// If not response body, grpc-status is in response headers.
return ExtractGrpcStatus(trailers_, status) ||
ExtractGrpcStatus(headers_, status);
ExtractGrpcStatus(response_headers_, status);
}

// Get Rbac related attributes.
Expand Down
1 change: 1 addition & 0 deletions src/envoy/utils/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ envoy_cc_library(
"header_update.h",
"mixer_control.h",
"stats.h",
"trace_headers.h",
"utils.h",
],
repository = "@envoy",
Expand Down
37 changes: 37 additions & 0 deletions src/envoy/utils/trace_headers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/* Copyright 2019 Istio Authors. All Rights Reserved.
*
* 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.
*/

#pragma once

#include <string>

namespace Envoy {
namespace Utils {

// Zipkin B3 headers
const std::string kTraceID = "x-b3-traceid";
const std::string kSpanID = "x-b3-spanid";
const std::string kParentSpanID = "x-b3-parentspanid";
const std::string kSampled = "x-b3-sampled";

const std::set<std::string> TracingHeaderSet = {
kTraceID,
kSpanID,
kParentSpanID,
kSampled,
};

} // namespace Utils
} // namespace Envoy
23 changes: 23 additions & 0 deletions src/envoy/utils/utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,29 @@ void ExtractHeaders(const Http::HeaderMap& header_map,
&ctx);
}

void FindHeaders(const Http::HeaderMap& header_map,
const std::set<std::string>& inclusives,
std::map<std::string, std::string>& headers) {
struct Context {
Context(const std::set<std::string>& inclusives,
std::map<std::string, std::string>& headers)
: inclusives(inclusives), headers(headers) {}
const std::set<std::string>& inclusives;
std::map<std::string, std::string>& headers;
};
Context ctx(inclusives, headers);
header_map.iterate(
[](const Http::HeaderEntry& header,
void* context) -> Http::HeaderMap::Iterate {
Context* ctx = static_cast<Context*>(context);
if (ctx->inclusives.count(header.key().c_str()) != 0) {
ctx->headers[header.key().c_str()] = header.value().c_str();
}
return Http::HeaderMap::Iterate::Continue;
},
&ctx);
}

bool GetIpPort(const Network::Address::Ip* ip, std::string* str_ip, int* port) {
if (ip) {
*port = ip->port();
Expand Down
6 changes: 6 additions & 0 deletions src/envoy/utils/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ void ExtractHeaders(const Http::HeaderMap& header_map,
const std::set<std::string>& exclusives,
std::map<std::string, std::string>& headers);

// Find the given headers from the header map and extract them out to the string
// map.
void FindHeaders(const Http::HeaderMap& header_map,
const std::set<std::string>& inclusives,
std::map<std::string, std::string>& headers);

// Get ip and port from Envoy ip.
bool GetIpPort(const Network::Address::Ip* ip, std::string* str_ip, int* port);

Expand Down
5 changes: 5 additions & 0 deletions src/istio/control/http/attributes_builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,11 @@ void AttributesBuilder::ExtractReportAttributes(
report_data->GetResponseHeaders();
builder.AddStringMap(utils::AttributeName::kResponseHeaders, headers);

std::map<std::string, std::string> tracing_headers;
report_data->GetTracingHeaders(tracing_headers);
builder.InsertStringMap(utils::AttributeName::kRequestHeaders,
tracing_headers);

builder.AddTimestamp(utils::AttributeName::kResponseTime,
std::chrono::system_clock::now());

Expand Down
25 changes: 25 additions & 0 deletions src/istio/control/http/attributes_builder_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,21 @@ attributes {
int64_value: 8080
}
}
attributes {
key: "request.headers"
value {
string_map_value {
entries {
key: "x-b3-traceid"
value: "abc"
}
entries {
key: "x-b3-spanid"
value: "def"
}
}
}
}
attributes {
key: "response.headers"
value {
Expand Down Expand Up @@ -765,6 +780,11 @@ TEST(AttributesBuilderTest, TestReportAttributes) {
map["server"] = "my-server";
return map;
}));
EXPECT_CALL(mock_data, GetTracingHeaders(_))
.WillOnce(Invoke([](std::map<std::string, std::string> &m) {
Comment thread
bianpengyuan marked this conversation as resolved.
m["x-b3-traceid"] = "abc";
m["x-b3-spanid"] = "def";
}));
EXPECT_CALL(mock_data, GetReportInfo(_))
.WillOnce(Invoke([](ReportData::ReportInfo *info) {
info->request_body_size = 100;
Expand Down Expand Up @@ -845,6 +865,11 @@ TEST(AttributesBuilderTest, TestReportAttributesWithDestIP) {
map["server"] = "my-server";
return map;
}));
EXPECT_CALL(mock_data, GetTracingHeaders(_))
.WillOnce(Invoke([](std::map<std::string, std::string> &m) {
m["x-b3-traceid"] = "abc";
m["x-b3-spanid"] = "def";
}));
EXPECT_CALL(mock_data, GetReportInfo(_))
.WillOnce(Invoke([](ReportData::ReportInfo *info) {
info->request_body_size = 100;
Expand Down
2 changes: 2 additions & 0 deletions src/istio/control/http/mock_report_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ namespace http {
class MockReportData : public ReportData {
public:
MOCK_CONST_METHOD0(GetResponseHeaders, std::map<std::string, std::string>());
MOCK_CONST_METHOD1(GetTracingHeaders,
void(std::map<std::string, std::string> &));
MOCK_CONST_METHOD1(GetReportInfo, void(ReportInfo *info));
MOCK_CONST_METHOD2(GetDestinationIpPort, bool(std::string *ip, int *port));
MOCK_CONST_METHOD1(GetDestinationUID, bool(std::string *ip));
Expand Down