diff options
-rw-r--r-- | BUILD | 6 | ||||
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | build.json | 4 | ||||
-rw-r--r-- | gRPC.podspec | 4 | ||||
-rw-r--r-- | include/grpc/census.h | 210 | ||||
-rw-r--r-- | src/core/census/context.c | 13 | ||||
-rw-r--r-- | src/core/census/grpc_context.c | 15 | ||||
-rw-r--r-- | src/core/census/operation.c | 63 | ||||
-rw-r--r-- | src/core/census/tracing.c | 45 | ||||
m--------- | third_party/openssl | 0 | ||||
-rw-r--r-- | tools/doxygen/Doxyfile.core.internal | 2 | ||||
-rw-r--r-- | tools/run_tests/sources_and_headers.json | 4 | ||||
-rw-r--r-- | vsprojects/grpc/grpc.vcxproj | 4 | ||||
-rw-r--r-- | vsprojects/grpc/grpc.vcxproj.filters | 6 | ||||
-rw-r--r-- | vsprojects/grpc_unsecure/grpc_unsecure.vcxproj | 4 | ||||
-rw-r--r-- | vsprojects/grpc_unsecure/grpc_unsecure.vcxproj.filters | 6 |
16 files changed, 344 insertions, 46 deletions
@@ -386,7 +386,9 @@ cc_library( "src/core/transport/transport_op_string.c", "src/core/census/context.c", "src/core/census/initialize.c", + "src/core/census/operation.c", "src/core/census/record_stat.c", + "src/core/census/tracing.c", ], hdrs = [ "include/grpc/grpc_security.h", @@ -635,7 +637,9 @@ cc_library( "src/core/transport/transport_op_string.c", "src/core/census/context.c", "src/core/census/initialize.c", + "src/core/census/operation.c", "src/core/census/record_stat.c", + "src/core/census/tracing.c", ], hdrs = [ "include/grpc/byte_buffer.h", @@ -1144,7 +1148,9 @@ objc_library( "src/core/transport/transport_op_string.c", "src/core/census/context.c", "src/core/census/initialize.c", + "src/core/census/operation.c", "src/core/census/record_stat.c", + "src/core/census/tracing.c", ], hdrs = [ "include/grpc/grpc_security.h", @@ -4196,7 +4196,9 @@ LIBGRPC_SRC = \ src/core/transport/transport_op_string.c \ src/core/census/context.c \ src/core/census/initialize.c \ + src/core/census/operation.c \ src/core/census/record_stat.c \ + src/core/census/tracing.c \ PUBLIC_HEADERS_C += \ include/grpc/grpc_security.h \ @@ -4470,7 +4472,9 @@ LIBGRPC_UNSECURE_SRC = \ src/core/transport/transport_op_string.c \ src/core/census/context.c \ src/core/census/initialize.c \ + src/core/census/operation.c \ src/core/census/record_stat.c \ + src/core/census/tracing.c \ PUBLIC_HEADERS_C += \ include/grpc/byte_buffer.h \ diff --git a/build.json b/build.json index 54cae41546..c02febbae3 100644 --- a/build.json +++ b/build.json @@ -24,7 +24,9 @@ "src": [ "src/core/census/context.c", "src/core/census/initialize.c", - "src/core/census/record_stat.c" + "src/core/census/operation.c", + "src/core/census/record_stat.c", + "src/core/census/tracing.c" ] }, { diff --git a/gRPC.podspec b/gRPC.podspec index f6d09dbaa6..48a91cbae4 100644 --- a/gRPC.podspec +++ b/gRPC.podspec @@ -395,7 +395,9 @@ Pod::Spec.new do |s| 'src/core/transport/transport_op_string.c', 'src/core/census/context.c', 'src/core/census/initialize.c', - 'src/core/census/record_stat.c' + 'src/core/census/operation.c', + 'src/core/census/record_stat.c', + 'src/core/census/tracing.c' ss.private_header_files = 'src/core/support/env.h', 'src/core/support/file.h', diff --git a/include/grpc/census.h b/include/grpc/census.h index a18b997b79..ef6275fe58 100644 --- a/include/grpc/census.h +++ b/include/grpc/census.h @@ -69,12 +69,14 @@ int census_supported(void); /** Return the census features currently enabled. */ int census_enabled(void); -/* Internally, Census relies on a context, which should be propagated across - * RPC's. From the RPC subsystems viewpoint, this is an opaque data structure. - * A context must be used as the first argument to all other census - * functions. Conceptually, contexts should be thought of as specific to - * single RPC/thread. The context can be serialized for passing across the - * wire. */ +/** + Context is a handle used by census to represent the current tracing and + tagging information. Contexts should be propagated across RPC's. Contexts + are created by any of the census_start_*_op() functions. A context is + typically used as argument to most census functions. Conceptually, contexts + should be thought of as specific to single RPC/thread. The context can be + serialized for passing across the wire, via census_context_serialize(). +*/ typedef struct census_context census_context; /* This function is called by the RPC subsystem whenever it needs to get a @@ -91,18 +93,192 @@ typedef struct census_context census_context; size_t census_context_serialize(const census_context *context, char *buffer, size_t buf_size); -/* Create a new census context, possibly from a serialized buffer. If 'buffer' - * is non-NULL, it is assumed that it is a buffer encoded by - * census_context_serialize(). If `buffer` is NULL, a new, empty context is - * created. The decoded/new contest is returned in 'context'. - * - * Returns 0 if no errors, non-zero if buffer is incorrectly formatted, in - * which case a new empty context will be returned. */ -int census_context_deserialize(const char *buffer, census_context **context); +/* Distributed traces can have a number of options. */ +enum census_trace_mask_values { + CENSUS_TRACE_MASK_NONE = 0, /* Default, empty flags */ + CENSUS_TRACE_MASK_IS_SAMPLED = 1 /* RPC tracing enabled for this context. */ +}; + +/** Get the current trace mask associated with this context. The value returned + will be the logical or of census_trace_mask_values values. */ +int census_trace_mask(const census_context *context); + +/** Set the trace mask associated with a context. */ +void census_set_trace_mask(int trace_mask); + +/* The concept of "operation" is a fundamental concept for Census. In an RPC + system, and operation typcially represents a single RPC, or a significant + sub-part thereof (e.g. a single logical "read" RPC to a distributed storage + system might do several other actions in parallel, from looking up metadata + indices to making requests of other services - each of these could be a + sub-operation with the larger RPC operation). Census uses operations for the + following: + + CPU accounting: If enabled, census will measure the thread CPU time + consumed between operation start and end times. + + Active operations: Census will maintain information on all currently + active operations. + + Distributed tracing: Each operation serves as a logical trace span. + + Stats collection: Stats are broken down by operation (e.g. latency + breakdown for each unique RPC path). + + The following functions serve to delineate the start and stop points for + each logical operation. */ + +/** + This structure represents a timestamp as used by census to record the time + at which an operation begins. +*/ +typedef struct { + /* Use gpr_timespec for default implementation. High performance + * implementations should use a cycle-counter based timestamp. */ + gpr_timespec ts; +} census_timestamp; + +/** + Mark the beginning of an RPC operation. The information required to call the + functions to record the start of RPC operations (both client and server) may + not be callable at the true start time of the operation, due to information + not being available (e.g. the census context data will not be available in a + server RPC until at least initial metadata has been processed). To ensure + correct CPU accounting and latency recording, RPC systems can call this + function to get the timestamp of operation beginning. This can later be used + as an argument to census_start_{client,server}_rpc_op(). NB: for correct + CPU accounting, the system must guarantee that the same thread is used + for all request processing after this function is called. + + @return A timestamp representing the operation start time. +*/ +census_timestamp census_start_rpc_op_timestamp(void); + +/** + Represent functions to map RPC name ID to service/method names. Census + breaks down all RPC stats by service and method names. We leave the + definition and format of these to the RPC system. For efficiency purposes, + we encode these as a single 64 bit identifier, and allow the RPC system to + provide a structure for functions that can convert these to service and + method strings. + + TODO(aveitch): Instead of providing this as an argument to the rpc_start_op() + functions, maybe it should be set once at census initialization. +*/ +typedef struct { + const char *(*get_rpc_service_name)(gpr_int64 id); + const char *(*get_rpc_method_name)(gpr_int64 id); +} census_rpc_name_info; + +/** + Start a client rpc operation. This function should be called as early in the + client RPC path as possible. This function will create a new context. If + the context argument is non-null, then the new context will inherit all + its properties, with the following changes: + - create a new operation ID for the new context, marking it as a child of + the previous operation. + - use the new RPC path and peer information for tracing and stats + collection purposes, rather than those from the original context + + If the context argument is NULL, then a new root context is created. This + is particularly important for tracing purposes (the trace spans generated + will be unassociated with any other trace spans, except those + downstream). The trace_mask will be used for tracing operations associated + with the new context. + + In some RPC systems (e.g. where load balancing is used), peer information + may not be available at the time the operation starts. In this case, use a + NULL value for peer, and set it later using the + census_set_rpc_client_peer() function. + + @param context The parent context. Can be NULL. + @param rpc_name_id The rpc name identifier to be associated with this RPC. + @param rpc_name_info Used to decode rpc_name_id. + @param peer RPC peer. If not available at the time, NULL can be used, + and a later census_set_rpc_client_peer() call made. + @param trace_mask An OR of census_trace_mask_values values. Only used in + the creation of a new root context (context == NULL). + @param start_time A timestamp returned from census_start_rpc_op_timestamp(). + Can be NULL. Used to set the true time the operation + begins. + + @return A new census context. + */ +census_context *census_start_client_rpc_op( + const census_context *context, gpr_int64 rpc_name_id, + const census_rpc_name_info *rpc_name_info, const char *peer, int trace_mask, + const census_timestamp *start_time); + +/** + Add peer information to a context representing a client RPC operation. +*/ +void census_set_rpc_client_peer(census_context *context, const char *peer); + +/** + Start a server RPC operation. Returns a new context to be used in future + census calls. If buffer is non-NULL, then the buffer contents should + represent the client context, as generated by census_context_serialize(). + If buffer is NULL, a new root context is created. + + @param buffer Buffer containing bytes output from census_context_serialize(). + @param rpc_name_id The rpc name identifier to be associated with this RPC. + @param rpc_name_info Used to decode rpc_name_id. + @param peer RPC peer. + @param trace_mask An OR of census_trace_mask_values values. Only used in + the creation of a new root context (buffer == NULL). + @param start_time A timestamp returned from census_start_rpc_op_timestamp(). + Can be NULL. Used to set the true time the operation + begins. + + @return A new census context. + */ +census_context *census_start_server_rpc_op( + const char *buffer, gpr_int64 rpc_name_id, + const census_rpc_name_info *rpc_name_info, const char *peer, int trace_mask, + census_timestamp *start_time); + +/** + Start a new, non-RPC operation. In general, this function works very + similarly to census_start_client_rpc_op, with the primary difference being + the replacement of host/path information with the more generic family/name + tags. If the context argument is non-null, then the new context will + inherit all its properties, with the following changes: + - create a new operation ID for the new context, marking it as a child of + the previous operation. + - use the family and name information for tracing and stats collection + purposes, rather than those from the original context + + If the context argument is NULL, then a new root context is created. This + is particularly important for tracing purposes (the trace spans generated + will be unassociated with any other trace spans, except those + downstream). The trace_mask will be used for tracing + operations associated with the new context. + + @param context The base context. Can be NULL. + @param family Family name to associate with the trace + @param name Name within family to associated with traces/stats + @param trace_mask An OR of census_trace_mask_values values. Only used if + context is NULL. + + @return A new census context. + */ +census_context *census_start_op(census_context *context, const char *family, + const char *name, int trace_mask); + +/** + End an operation started by any of the census_start_*_op*() calls. The + context used in this call will no longer be valid once this function + completes. + + @param context Context associated with operation which is ending. + @param status status associated with the operation. Not interpreted by + census. +*/ +void census_end_op(census_context *context, int status); -/* The given context is destroyed. Once destroyed, using the context in - * future census calls will result in undefined behavior. */ -void census_context_destroy(census_context *context); +/** Insert a trace record into the trace stream. The record consists of an + * arbitrary size buffer, the size of which is provided in 'n'. */ +void census_trace_print(census_context *context, const char *buffer, size_t n); /* Max number of characters in tag key */ #define CENSUS_MAX_TAG_KEY_LENGTH 20 diff --git a/src/core/census/context.c b/src/core/census/context.c index df238ec98c..cab58b653c 100644 --- a/src/core/census/context.c +++ b/src/core/census/context.c @@ -44,16 +44,3 @@ size_t census_context_serialize(const census_context *context, char *buffer, /* TODO(aveitch): implement serialization */ return 0; } - -int census_context_deserialize(const char *buffer, census_context **context) { - int ret = 0; - if (buffer != NULL) { - /* TODO(aveitch): implement deserialization. */ - ret = 1; - } - *context = gpr_malloc(sizeof(census_context)); - memset(*context, 0, sizeof(census_context)); - return ret; -} - -void census_context_destroy(census_context *context) { gpr_free(context); } diff --git a/src/core/census/grpc_context.c b/src/core/census/grpc_context.c index 11f1eb3d5d..429f3ec9db 100644 --- a/src/core/census/grpc_context.c +++ b/src/core/census/grpc_context.c @@ -35,24 +35,11 @@ #include <grpc/grpc.h> #include "src/core/surface/call.h" -static void grpc_census_context_destroy(void *context) { - census_context_destroy((census_context *)context); -} - void grpc_census_call_set_context(grpc_call *call, census_context *context) { if (census_enabled() == CENSUS_FEATURE_NONE) { return; } - if (context == NULL) { - if (grpc_call_is_client(call)) { - census_context *context_ptr; - census_context_deserialize(NULL, &context_ptr); - grpc_call_context_set(call, GRPC_CONTEXT_TRACING, context_ptr, - grpc_census_context_destroy); - } else { - /* TODO(aveitch): server side context code to be implemented. */ - } - } else { + if (context != NULL) { grpc_call_context_set(call, GRPC_CONTEXT_TRACING, context, NULL); } } diff --git a/src/core/census/operation.c b/src/core/census/operation.c new file mode 100644 index 0000000000..118eb0a47a --- /dev/null +++ b/src/core/census/operation.c @@ -0,0 +1,63 @@ +/* + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include <grpc/census.h> + +/* TODO(aveitch): These are all placeholder implementations. */ + +census_timestamp census_start_rpc_op_timestamp(void) { + census_timestamp ct; + /* TODO(aveitch): assumes gpr_timespec implementation of census_timestamp. */ + ct.ts = gpr_now(GPR_CLOCK_MONOTONIC); + return ct; +} + +census_context *census_start_client_rpc_op( + const census_context *context, gpr_int64 rpc_name_id, + const census_rpc_name_info *rpc_name_info, const char *peer, int trace_mask, + const census_timestamp *start_time) { + return NULL; +} + +census_context *census_start_server_rpc_op( + const char *buffer, gpr_int64 rpc_name_id, + const census_rpc_name_info *rpc_name_info, const char *peer, int trace_mask, + census_timestamp *start_time) { + return NULL; +} + +census_context *census_start_op(census_context *context, const char *family, + const char *name, int trace_mask) { + return NULL; +} + +void census_end_op(census_context *context, int status) {} diff --git a/src/core/census/tracing.c b/src/core/census/tracing.c new file mode 100644 index 0000000000..44db95653c --- /dev/null +++ b/src/core/census/tracing.c @@ -0,0 +1,45 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include <grpc/census.h> + +/* TODO(aveitch): These are all placeholder implementations. */ + +int census_trace_mask(const census_context *context) { + return CENSUS_TRACE_MASK_NONE; +} + +void census_set_trace_mask(int trace_mask) {} + +void census_trace_print(census_context *context, const char *buffer, size_t n) { +} diff --git a/third_party/openssl b/third_party/openssl -Subproject 33dd08320648ac71d7d9d732be774ed3818dccc +Subproject 3df69d3aefde7671053d4e3c242b228e5d79c83 diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 06f0f4ee83..e34aff2614 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -1023,7 +1023,9 @@ src/core/transport/transport.c \ src/core/transport/transport_op_string.c \ src/core/census/context.c \ src/core/census/initialize.c \ +src/core/census/operation.c \ src/core/census/record_stat.c \ +src/core/census/tracing.c \ include/grpc/support/alloc.h \ include/grpc/support/atm.h \ include/grpc/support/atm_gcc_atomic.h \ diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json index c7df23a7c4..1dbe8b781a 100644 --- a/tools/run_tests/sources_and_headers.json +++ b/tools/run_tests/sources_and_headers.json @@ -12397,8 +12397,10 @@ "src/core/census/grpc_filter.c", "src/core/census/grpc_filter.h", "src/core/census/initialize.c", + "src/core/census/operation.c", "src/core/census/record_stat.c", "src/core/census/rpc_stat_id.h", + "src/core/census/tracing.c", "src/core/channel/channel_args.c", "src/core/channel/channel_args.h", "src/core/channel/channel_stack.c", @@ -12862,8 +12864,10 @@ "src/core/census/grpc_filter.c", "src/core/census/grpc_filter.h", "src/core/census/initialize.c", + "src/core/census/operation.c", "src/core/census/record_stat.c", "src/core/census/rpc_stat_id.h", + "src/core/census/tracing.c", "src/core/channel/channel_args.c", "src/core/channel/channel_args.h", "src/core/channel/channel_stack.c", diff --git a/vsprojects/grpc/grpc.vcxproj b/vsprojects/grpc/grpc.vcxproj index b17eea9235..9811e62c9b 100644 --- a/vsprojects/grpc/grpc.vcxproj +++ b/vsprojects/grpc/grpc.vcxproj @@ -626,8 +626,12 @@ </ClCompile> <ClCompile Include="..\..\src\core\census\initialize.c"> </ClCompile> + <ClCompile Include="..\..\src\core\census\operation.c"> + </ClCompile> <ClCompile Include="..\..\src\core\census\record_stat.c"> </ClCompile> + <ClCompile Include="..\..\src\core\census\tracing.c"> + </ClCompile> </ItemGroup> <ItemGroup> <ProjectReference Include="..\gpr\gpr.vcxproj"> diff --git a/vsprojects/grpc/grpc.vcxproj.filters b/vsprojects/grpc/grpc.vcxproj.filters index a955e9e993..34b6580e4e 100644 --- a/vsprojects/grpc/grpc.vcxproj.filters +++ b/vsprojects/grpc/grpc.vcxproj.filters @@ -418,9 +418,15 @@ <ClCompile Include="..\..\src\core\census\initialize.c"> <Filter>src\core\census</Filter> </ClCompile> + <ClCompile Include="..\..\src\core\census\operation.c"> + <Filter>src\core\census</Filter> + </ClCompile> <ClCompile Include="..\..\src\core\census\record_stat.c"> <Filter>src\core\census</Filter> </ClCompile> + <ClCompile Include="..\..\src\core\census\tracing.c"> + <Filter>src\core\census</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="..\..\include\grpc\grpc_security.h"> diff --git a/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj index a692c48f81..9de9c47f6b 100644 --- a/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj +++ b/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj @@ -569,8 +569,12 @@ </ClCompile> <ClCompile Include="..\..\src\core\census\initialize.c"> </ClCompile> + <ClCompile Include="..\..\src\core\census\operation.c"> + </ClCompile> <ClCompile Include="..\..\src\core\census\record_stat.c"> </ClCompile> + <ClCompile Include="..\..\src\core\census\tracing.c"> + </ClCompile> </ItemGroup> <ItemGroup> <ProjectReference Include="..\gpr\gpr.vcxproj"> diff --git a/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj.filters index 1c4036d464..41fedd737e 100644 --- a/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj.filters +++ b/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj.filters @@ -358,9 +358,15 @@ <ClCompile Include="..\..\src\core\census\initialize.c"> <Filter>src\core\census</Filter> </ClCompile> + <ClCompile Include="..\..\src\core\census\operation.c"> + <Filter>src\core\census</Filter> + </ClCompile> <ClCompile Include="..\..\src\core\census\record_stat.c"> <Filter>src\core\census</Filter> </ClCompile> + <ClCompile Include="..\..\src\core\census\tracing.c"> + <Filter>src\core\census</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="..\..\include\grpc\byte_buffer.h"> |