User agent string support

pull/2370/head
Craig Tiller 10 years ago
parent 8bf2dcab4e
commit 0dc5e6cf16
  1. 12
      include/grpc++/channel_arguments.h
  2. 6
      include/grpc/grpc.h
  3. 12
      include/grpc/support/port_platform.h
  4. 61
      src/core/channel/http_client_filter.c
  5. 2
      src/core/transport/chttp2/parsing.c
  6. 38
      src/cpp/client/channel_arguments.cc
  7. 9
      src/cpp/client/create_channel.cc
  8. 4
      test/core/end2end/dualstack_socket_test.c
  9. 7
      test/cpp/end2end/end2end_test.cc
  10. 10
      test/cpp/qps/qps_test.cc

@ -54,6 +54,14 @@ class ChannelArguments {
ChannelArguments() {}
~ChannelArguments() {}
ChannelArguments(const ChannelArguments& other);
ChannelArguments& operator=(ChannelArguments other) {
Swap(other);
return *this;
}
void Swap(ChannelArguments& other);
// grpc specific channel argument setters
// Set target name override for SSL host name checking.
void SetSslTargetNameOverride(const grpc::string& name);
@ -73,10 +81,6 @@ class ChannelArguments {
friend class SecureCredentials;
friend class testing::ChannelArgumentsTest;
// TODO(yangg) implement copy and assign
ChannelArguments(const ChannelArguments&);
ChannelArguments& operator=(const ChannelArguments&);
// Returns empty string when it is not set.
grpc::string GetSslTargetNameOverride() const;

@ -117,6 +117,12 @@ typedef struct {
/* Initial sequence number for http2 transports */
#define GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER \
"grpc.http2.initial_sequence_number"
/** Primary user agent: goes at the start of the user-agent metadata
sent on each request */
#define GRPC_ARG_PRIMARY_USER_AGENT_STRING "grpc.primary_user_agent"
/** Secondary user agent: goes at the end of the user-agent metadata
sent on each request */
#define GRPC_ARG_SECONDARY_USER_AGENT_STRING "grpc.secondary_user_agent"
/** Connectivity state of a channel. */
typedef enum {

@ -71,6 +71,7 @@
#if !defined(GPR_NO_AUTODETECT_PLATFORM)
#if defined(_WIN64) || defined(WIN64)
#define GPR_PLATFORM_STRING "windows"
#define GPR_WIN32 1
#define GPR_ARCH_64 1
#define GPR_GETPID_IN_PROCESS_H 1
@ -84,6 +85,7 @@
#endif
#define GPR_WINDOWS_CRASH_HANDLER 1
#elif defined(_WIN32) || defined(WIN32)
#define GPR_PLATFORM_STRING "windows"
#define GPR_ARCH_32 1
#define GPR_WIN32 1
#define GPR_GETPID_IN_PROCESS_H 1
@ -97,6 +99,7 @@
#endif
#define GPR_WINDOWS_CRASH_HANDLER 1
#elif defined(ANDROID) || defined(__ANDROID__)
#define GPR_PLATFORM_STRING "android"
#define GPR_ANDROID 1
#define GPR_ARCH_32 1
#define GPR_CPU_LINUX 1
@ -117,6 +120,7 @@
#define GPR_GETPID_IN_UNISTD_H 1
#define GPR_HAVE_MSG_NOSIGNAL 1
#elif defined(__linux__)
#define GPR_PLATFORM_STRING "linux"
#ifndef _BSD_SOURCE
#define _BSD_SOURCE
#endif
@ -173,9 +177,11 @@
#define _BSD_SOURCE
#endif
#if TARGET_OS_IPHONE
#define GPR_PLATFORM_STRING "ios"
#define GPR_CPU_IPHONE 1
#define GPR_PTHREAD_TLS 1
#else /* TARGET_OS_IPHONE */
#define GPR_PLATFORM_STRING "osx"
#define GPR_CPU_POSIX 1
#define GPR_GCC_TLS 1
#endif
@ -201,6 +207,7 @@
#define GPR_ARCH_32 1
#endif /* _LP64 */
#elif defined(__FreeBSD__)
#define GPR_PLATFORM_STRING "freebsd"
#ifndef _BSD_SOURCE
#define _BSD_SOURCE
#endif
@ -232,6 +239,11 @@
#endif
#endif /* GPR_NO_AUTODETECT_PLATFORM */
#ifndef GPR_PLATFORM_STRING
#warning "GPR_PLATFORM_STRING not auto-detected"
#define GPR_PLATFORM_STRING "unknown"
#endif
/* For a common case, assume that the platform has a C99-like stdint.h */
#include <stdint.h>

@ -32,13 +32,17 @@
#include "src/core/channel/http_client_filter.h"
#include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include "src/core/support/string.h"
typedef struct call_data {
grpc_linked_mdelem method;
grpc_linked_mdelem scheme;
grpc_linked_mdelem te_trailers;
grpc_linked_mdelem content_type;
grpc_linked_mdelem user_agent;
int sent_initial_metadata;
int got_initial_metadata;
@ -58,6 +62,8 @@ typedef struct channel_data {
grpc_mdelem *scheme;
grpc_mdelem *content_type;
grpc_mdelem *status;
/** complete user agent mdelem */
grpc_mdelem *user_agent;
} channel_data;
/* used to silence 'variable not used' warnings */
@ -115,6 +121,8 @@ static void hc_mutate_op(grpc_call_element *elem,
GRPC_MDELEM_REF(channeld->te_trailers));
grpc_metadata_batch_add_tail(&op->data.metadata, &calld->content_type,
GRPC_MDELEM_REF(channeld->content_type));
grpc_metadata_batch_add_tail(&op->data.metadata, &calld->user_agent,
GRPC_MDELEM_REF(channeld->user_agent));
break;
}
}
@ -169,6 +177,55 @@ static const char *scheme_from_args(const grpc_channel_args *args) {
return "http";
}
static grpc_mdstr *user_agent_from_args(grpc_mdctx *mdctx,
const grpc_channel_args *args) {
gpr_strvec v;
size_t i;
int is_first = 1;
char *tmp;
grpc_mdstr *result;
gpr_strvec_init(&v);
for (i = 0; args && i < args->num_args; i++) {
if (0 == strcmp(args->args[i].key, GRPC_ARG_PRIMARY_USER_AGENT_STRING)) {
if (args->args[i].type != GRPC_ARG_STRING) {
gpr_log(GPR_ERROR, "Channel argument '%s' should be a string",
GRPC_ARG_PRIMARY_USER_AGENT_STRING);
} else {
if (!is_first) gpr_strvec_add(&v, gpr_strdup(" "));
is_first = 0;
gpr_strvec_add(&v, gpr_strdup(args->args[i].value.string));
}
}
}
gpr_asprintf(&tmp, "%sgrpc-c/%s (%s)", is_first ? "" : " ",
grpc_version_string(), GPR_PLATFORM_STRING);
is_first = 0;
gpr_strvec_add(&v, tmp);
for (i = 0; args && i < args->num_args; i++) {
if (0 == strcmp(args->args[i].key, GRPC_ARG_SECONDARY_USER_AGENT_STRING)) {
if (args->args[i].type != GRPC_ARG_STRING) {
gpr_log(GPR_ERROR, "Channel argument '%s' should be a string",
GRPC_ARG_SECONDARY_USER_AGENT_STRING);
} else {
if (!is_first) gpr_strvec_add(&v, gpr_strdup(" "));
is_first = 0;
gpr_strvec_add(&v, gpr_strdup(args->args[i].value.string));
}
}
}
tmp = gpr_strvec_flatten(&v, NULL);
gpr_strvec_destroy(&v);
result = grpc_mdstr_from_string(mdctx, tmp);
gpr_free(tmp);
return result;
}
/* Constructor for channel_data */
static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
const grpc_channel_args *args, grpc_mdctx *mdctx,
@ -189,6 +246,9 @@ static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
channeld->content_type =
grpc_mdelem_from_strings(mdctx, "content-type", "application/grpc");
channeld->status = grpc_mdelem_from_strings(mdctx, ":status", "200");
channeld->user_agent = grpc_mdelem_from_metadata_strings(
mdctx, grpc_mdstr_from_string(mdctx, "user-agent"),
user_agent_from_args(mdctx, args));
}
/* Destructor for channel data */
@ -201,6 +261,7 @@ static void destroy_channel_elem(grpc_channel_element *elem) {
GRPC_MDELEM_UNREF(channeld->scheme);
GRPC_MDELEM_UNREF(channeld->content_type);
GRPC_MDELEM_UNREF(channeld->status);
GRPC_MDELEM_UNREF(channeld->user_agent);
}
const grpc_channel_filter grpc_http_client_filter = {

@ -588,7 +588,7 @@ static void on_header(void *tp, grpc_mdelem *md) {
GPR_ASSERT(stream_parsing);
GRPC_CHTTP2_IF_TRACING(gpr_log(
GPR_INFO, "HTTP:%d:HDR: %s: %s", stream_parsing->id,
GPR_INFO, "HTTP:%d:HDR:%s: %s: %s", stream_parsing->id,
transport_parsing->is_client ? "CLI" : "SVR",
grpc_mdstr_as_c_string(md->key), grpc_mdstr_as_c_string(md->value)));

@ -33,10 +33,48 @@
#include <grpc++/channel_arguments.h>
#include <grpc/support/log.h>
#include "src/core/channel/channel_args.h"
namespace grpc {
ChannelArguments::ChannelArguments(const ChannelArguments& other)
: strings_(other.strings_) {
args_.reserve(other.args_.size());
auto list_it_dst = strings_.begin();
auto list_it_src = other.strings_.begin();
for (auto a = other.args_.begin(); a != other.args_.end(); ++a) {
grpc_arg ap;
ap.type = a->type;
GPR_ASSERT(list_it_src->c_str() == a->key);
ap.key = const_cast<char*>(list_it_dst->c_str());
++list_it_src;
++list_it_dst;
switch (a->type) {
case GRPC_ARG_INTEGER:
ap.value.integer = a->value.integer;
break;
case GRPC_ARG_STRING:
GPR_ASSERT(list_it_src->c_str() == a->value.string);
ap.value.string = const_cast<char*>(list_it_dst->c_str());
++list_it_src;
++list_it_dst;
break;
case GRPC_ARG_POINTER:
ap.value.pointer = a->value.pointer;
ap.value.pointer.p = a->value.pointer.copy(ap.value.pointer.p);
break;
}
args_.push_back(ap);
}
}
void ChannelArguments::Swap(ChannelArguments& other) {
args_.swap(other.args_);
strings_.swap(other.strings_);
}
void ChannelArguments::SetCompressionLevel(grpc_compression_level level) {
SetInt(GRPC_COMPRESSION_LEVEL_ARG, level);
}

@ -32,9 +32,11 @@
*/
#include <memory>
#include <sstream>
#include "src/cpp/client/channel.h"
#include <grpc++/channel_interface.h>
#include <grpc++/channel_arguments.h>
#include <grpc++/create_channel.h>
namespace grpc {
@ -43,7 +45,12 @@ class ChannelArguments;
std::shared_ptr<ChannelInterface> CreateChannel(
const grpc::string& target, const std::shared_ptr<Credentials>& creds,
const ChannelArguments& args) {
return creds ? creds->CreateChannel(target, args)
ChannelArguments cp_args = args;
std::ostringstream user_agent_prefix;
user_agent_prefix << "grpc-c++/" << grpc_version_string();
cp_args.SetString(GRPC_ARG_PRIMARY_USER_AGENT_STRING,
user_agent_prefix.str());
return creds ? creds->CreateChannel(target, cp_args)
: std::shared_ptr<ChannelInterface>(
new Channel(target, grpc_lame_client_channel_create()));
}

@ -211,6 +211,10 @@ void test_connect(const char *server_host, const char *client_host, int port,
drain_cq(cq);
grpc_completion_queue_destroy(cq);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv);
grpc_call_details_destroy(&call_details);
gpr_free(details);
}

@ -249,9 +249,10 @@ class End2endTest : public ::testing::Test {
void TearDown() GRPC_OVERRIDE { server_->Shutdown(); }
void ResetStub() {
std::shared_ptr<ChannelInterface> channel =
CreateChannel(server_address_.str(), FakeTransportSecurityCredentials(),
ChannelArguments());
ChannelArguments args;
args.SetString(GRPC_ARG_SECONDARY_USER_AGENT_STRING, "end2end_test");
std::shared_ptr<ChannelInterface> channel = CreateChannel(
server_address_.str(), FakeTransportSecurityCredentials(), args);
stub_ = std::move(grpc::cpp::test::util::TestService::NewStub(channel));
}

@ -44,8 +44,8 @@
namespace grpc {
namespace testing {
static const int WARMUP = 5;
static const int BENCHMARK = 10;
static const int WARMUP = 20;
static const int BENCHMARK = 40;
static void RunQPS() {
gpr_log(GPR_INFO, "Running QPS test");
@ -53,8 +53,8 @@ static void RunQPS() {
ClientConfig client_config;
client_config.set_client_type(ASYNC_CLIENT);
client_config.set_enable_ssl(false);
client_config.set_outstanding_rpcs_per_channel(1000);
client_config.set_client_channels(8);
client_config.set_outstanding_rpcs_per_channel(10);
client_config.set_client_channels(800);
client_config.set_payload_size(1);
client_config.set_async_client_threads(8);
client_config.set_rpc_type(UNARY);
@ -62,7 +62,7 @@ static void RunQPS() {
ServerConfig server_config;
server_config.set_server_type(ASYNC_SERVER);
server_config.set_enable_ssl(false);
server_config.set_threads(4);
server_config.set_threads(8);
const auto result =
RunScenario(client_config, 1, server_config, 1, WARMUP, BENCHMARK, -2);

Loading…
Cancel
Save