Merge pull request #3134 from nathanielmanistaatgoogle/beta

The rest of the Python Beta API
diff --git a/BUILD b/BUILD
index d612d9c..c30fd5b 100644
--- a/BUILD
+++ b/BUILD
@@ -386,7 +386,9 @@
     "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",
@@ -634,7 +636,9 @@
     "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 @@
     "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",
diff --git a/INSTALL b/INSTALL
index d183fce..de13d65 100644
--- a/INSTALL
+++ b/INSTALL
@@ -11,12 +11,12 @@
 
 On Linux (Debian):
 
- Note: you will need to add the Debian 'unstable' distribution to your sources
+ Note: you will need to add the Debian 'testing' distribution to your sources
  file first.
 
  Add the following line to your `/etc/apt/sources.list` file:
 
-   deb http://ftp.us.debian.org/debian unstable main contrib non-free
+   deb http://ftp.us.debian.org/debian testing main contrib non-free
 
  Install the gRPC library:
 
diff --git a/Makefile b/Makefile
index 135d38c..1d1ce18 100644
--- a/Makefile
+++ b/Makefile
@@ -4149,7 +4149,9 @@
     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 \
@@ -4423,7 +4425,9 @@
     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 a451fc3..cec692b 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 55f72c9..0349d04 100644
--- a/gRPC.podspec
+++ b/gRPC.podspec
@@ -395,7 +395,9 @@
                       '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 a18b997..d1a2978 100644
--- a/include/grpc/census.h
+++ b/include/grpc/census.h
@@ -69,12 +69,14 @@
 /** 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,236 @@
 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. */
+};
 
-/* 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);
+/** 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);
+
+#define CENSUS_TRACE_RECORD_START_OP ((gpr_uint32)0)
+#define CENSUS_TRACE_RECORD_END_OP ((gpr_uint32)1)
+
+/** Insert a trace record into the trace stream. The record consists of an
+    arbitrary size buffer, the size of which is provided in 'n'.
+    @param context Trace context
+    @param type User-defined type to associate with trace entry.
+    @param buffer Pointer to buffer to use
+    @param n Number of bytes in buffer
+*/
+void census_trace_print(census_context *context, gpr_uint32 type,
+                        const char *buffer, size_t n);
+
+/** Trace record. */
+typedef struct {
+  census_timestamp timestamp; /* Time of record creation */
+  gpr_uint64 trace_id;        /* Trace ID associated with record */
+  gpr_uint64 op_id;           /* Operation ID associated with record */
+  gpr_uint32 type;            /* Type (as used in census_trace_print() */
+  const char *buffer;         /* Buffer (from census_trace_print() */
+  size_t buf_size;            /* Number of bytes inside buffer */
+} census_trace_record;
+
+/** Start a scan of existing trace records. While a scan is ongoing, addition
+    of new trace records will be blocked if the underlying trace buffers
+    fill up, so trace processing systems should endeavor to complete
+    reading as soon as possible.
+  @param consume if non-zero, indicates that reading records also "consumes"
+         the previously read record - i.e. releases space in the trace log
+         while scanning is ongoing.
+  @returns 0 on success, non-zero on failure (e.g. if a scan is already ongoing)
+*/
+int census_trace_scan_start(int consume);
+
+/** Get a trace record. The data pointed to by the trace buffer is guaranteed
+    stable until the next census_get_trace_record() call (if the consume
+    argument to census_trace_scan_start was non-zero) or census_trace_scan_end()
+    is called (otherwise).
+  @param trace_record structure that will be filled in with oldest trace record.
+  @returns -1 if an error occurred (e.g. no previous call to
+           census_trace_scan_start()), 0 if there is no more trace data (and
+           trace_record will not be modified) or 1 otherwise.
+*/
+int census_get_trace_record(census_trace_record *trace_record);
+
+/** End a scan previously started by census_trace_scan_start() */
+void census_trace_scan_end();
 
 /* 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 df238ec..cab58b6 100644
--- a/src/core/census/context.c
+++ b/src/core/census/context.c
@@ -44,16 +44,3 @@
   /* 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 11f1eb3..429f3ec 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 0000000..118eb0a
--- /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 0000000..ae38773
--- /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, gpr_uint32 type,
+                        const char *buffer, size_t n) {}
diff --git a/src/node/README.md b/src/node/README.md
index b641153..c96bc96 100644
--- a/src/node/README.md
+++ b/src/node/README.md
@@ -11,10 +11,10 @@
 
 **Linux (Debian):**
 
-Add [Debian unstable][] to your `sources.list` file. Example:
+Add [Debian testing][] to your `sources.list` file. Example:
 
 ```sh
-echo "deb http://ftp.us.debian.org/debian unstable main contrib non-free" | \
+echo "deb http://ftp.us.debian.org/debian testing main contrib non-free" | \
 sudo tee -a /etc/apt/sources.list
 ```
 
@@ -113,4 +113,4 @@
 
 [homebrew]:http://brew.sh
 [gRPC install script]:https://raw.githubusercontent.com/grpc/homebrew-grpc/master/scripts/install
-[Debian unstable]:https://www.debian.org/releases/sid/
+[Debian testing]:https://www.debian.org/releases/stretch/
diff --git a/src/php/README.md b/src/php/README.md
index f432935..afa09d7 100644
--- a/src/php/README.md
+++ b/src/php/README.md
@@ -32,10 +32,10 @@
 
 **Linux (Debian):**
 
-Add [Debian unstable][] to your `sources.list` file. Example:
+Add [Debian testing][] to your `sources.list` file. Example:
 
 ```sh
-echo "deb http://ftp.us.debian.org/debian unstable main contrib non-free" | \
+echo "deb http://ftp.us.debian.org/debian testing main contrib non-free" | \
 sudo tee -a /etc/apt/sources.list
 ```
 
@@ -73,31 +73,26 @@
 
 Clone this repository
 
-```
+```sh
 $ git clone https://github.com/grpc/grpc.git
 ```
 
-Build and install the Protocol Buffers compiler (protoc)
-
-```
-$ cd grpc
-$ git pull --recurse-submodules && git submodule update --init --recursive
-$ cd third_party/protobuf
-$ ./autogen.sh
-$ ./configure
-$ make
-$ make check
-$ sudo make install
-```
-
 Build and install the gRPC C core libraries
 
 ```sh
 $ cd grpc
+$ git pull --recurse-submodules && git submodule update --init --recursive
 $ make
 $ sudo make install
 ```
 
+Note: you may encounter a warning about the Protobuf compiler `protoc` 3.0.0+ not being installed. The following might help, and will be useful later on when we need to compile the `protoc-gen-php` tool.
+
+```sh
+$ cd grpc/third_party/protobuf
+$ sudo make install   # 'make' should have been run by core grpc
+```
+
 Install the gRPC PHP extension
 
 ```sh
@@ -172,4 +167,4 @@
 [homebrew]:http://brew.sh
 [gRPC install script]:https://raw.githubusercontent.com/grpc/homebrew-grpc/master/scripts/install
 [Node]:https://github.com/grpc/grpc/tree/master/src/node/examples
-[Debian unstable]:https://www.debian.org/releases/sid/
+[Debian testing]:https://www.debian.org/releases/stretch/
diff --git a/src/python/README.md b/src/python/README.md
index affce64..a21deb3 100644
--- a/src/python/README.md
+++ b/src/python/README.md
@@ -16,10 +16,10 @@
 
 **Linux (Debian):**
 
-Add [Debian unstable][] to your `sources.list` file. Example:
+Add [Debian testing][] to your `sources.list` file. Example:
 
 ```sh
-echo "deb http://ftp.us.debian.org/debian unstable main contrib non-free" | \
+echo "deb http://ftp.us.debian.org/debian testing main contrib non-free" | \
 sudo tee -a /etc/apt/sources.list
 ```
 
@@ -92,4 +92,4 @@
 [gRPC install script]:https://raw.githubusercontent.com/grpc/homebrew-grpc/master/scripts/install
 [Quick Start]:http://www.grpc.io/docs/tutorials/basic/python.html
 [detailed example]:http://www.grpc.io/docs/installation/python.html
-[Debian unstable]:https://www.debian.org/releases/sid/
+[Debian testing]:https://www.debian.org/releases/stretch/
diff --git a/src/ruby/README.md b/src/ruby/README.md
index f8902e3..7f75c0e 100644
--- a/src/ruby/README.md
+++ b/src/ruby/README.md
@@ -19,10 +19,10 @@
 
 **Linux (Debian):**
 
-Add [Debian unstable][] to your `sources.list` file. Example:
+Add [Debian testing][] to your `sources.list` file. Example:
 
 ```sh
-echo "deb http://ftp.us.debian.org/debian unstable main contrib non-free" | \
+echo "deb http://ftp.us.debian.org/debian testing main contrib non-free" | \
 sudo tee -a /etc/apt/sources.list
 ```
 
@@ -99,4 +99,4 @@
 [ruby extensions]:http://guides.rubygems.org/gems-with-extensions/
 [rubydoc]: http://www.rubydoc.info/gems/grpc
 [grpc.io]: http://www.grpc.io/docs/installation/ruby.html
-[Debian unstable]:https://www.debian.org/releases/sid/
+[Debian testing]:https://www.debian.org/releases/stretch/
diff --git a/src/ruby/bin/math_client.rb b/src/ruby/bin/math_client.rb
index 6319cda..0ebd26f 100755
--- a/src/ruby/bin/math_client.rb
+++ b/src/ruby/bin/math_client.rb
@@ -50,7 +50,7 @@
   GRPC.logger.info('----------------')
   req = Math::DivArgs.new(dividend: 7, divisor: 3)
   GRPC.logger.info("div(7/3): req=#{req.inspect}")
-  resp = stub.div(req, INFINITE_FUTURE)
+  resp = stub.div(req, timeout: INFINITE_FUTURE)
   GRPC.logger.info("Answer: #{resp.inspect}")
   GRPC.logger.info('----------------')
 end
@@ -71,7 +71,7 @@
   GRPC.logger.info('----------------')
   req = Math::FibArgs.new(limit: 11)
   GRPC.logger.info("fib(11): req=#{req.inspect}")
-  resp = stub.fib(req, INFINITE_FUTURE)
+  resp = stub.fib(req, timeout: INFINITE_FUTURE)
   resp.each do |r|
     GRPC.logger.info("Answer: #{r.inspect}")
   end
@@ -86,7 +86,7 @@
   reqs << Math::DivArgs.new(dividend: 5, divisor: 2)
   reqs << Math::DivArgs.new(dividend: 7, divisor: 2)
   GRPC.logger.info("div(7/3), div(5/2), div(7/2): reqs=#{reqs.inspect}")
-  resp = stub.div_many(reqs, 10)
+  resp = stub.div_many(reqs, timeout: INFINITE_FUTURE)
   resp.each do |r|
     GRPC.logger.info("Answer: #{r.inspect}")
   end
diff --git a/src/ruby/bin/math_server.rb b/src/ruby/bin/math_server.rb
index b41ccf6..9a921b1 100755
--- a/src/ruby/bin/math_server.rb
+++ b/src/ruby/bin/math_server.rb
@@ -41,9 +41,25 @@
 
 require 'forwardable'
 require 'grpc'
+require 'logger'
 require 'math_services'
 require 'optparse'
 
+# RubyLogger defines a logger for gRPC based on the standard ruby logger.
+module RubyLogger
+  def logger
+    LOGGER
+  end
+
+  LOGGER = Logger.new(STDOUT)
+end
+
+# GRPC is the general RPC module
+module GRPC
+  # Inject the noop #logger if no module-level logger method has been injected.
+  extend RubyLogger
+end
+
 # Holds state for a fibonacci series
 class Fibber
   def initialize(limit)
diff --git a/src/ruby/ext/grpc/rb_server.c b/src/ruby/ext/grpc/rb_server.c
index 7e76349..bd19b2f 100644
--- a/src/ruby/ext/grpc/rb_server.c
+++ b/src/ruby/ext/grpc/rb_server.c
@@ -234,6 +234,7 @@
                grpc_call_error_detail_of(err), err);
       return Qnil;
     }
+
     ev = grpc_rb_completion_queue_pluck_event(cqueue, tag_new, timeout);
     if (ev.type == GRPC_QUEUE_TIMEOUT) {
       grpc_request_call_stack_cleanup(&st);
@@ -298,36 +299,15 @@
   if (s->wrapped != NULL) {
     grpc_server_shutdown_and_notify(s->wrapped, cq, NULL);
     ev = grpc_rb_completion_queue_pluck_event(cqueue, Qnil, timeout);
-
     if (!ev.success) {
-      rb_warn("server shutdown failed, there will be a LEAKED object warning");
-      return Qnil;
-      /*
-         TODO: renable the rb_raise below.
-
-         At the moment if the timeout is INFINITE_FUTURE as recommended, the
-         pluck blocks forever, even though
-
-         the outstanding server_request_calls correctly fail on the other
-         thread that they are running on.
-
-         it's almost as if calls that fail on the other thread do not get
-         cleaned up by shutdown request, even though it caused htem to
-         terminate.
-
-         rb_raise(rb_eRuntimeError, "grpc server shutdown did not succeed");
-         return Qnil;
-
-         The workaround is just to use a timeout and return without really
-         shutting down the server, and rely on the grpc core garbage collection
-         it down as a 'LEAKED OBJECT'.
-
-      */
+      rb_warn("server shutdown failed, cancelling the calls, objects may leak");
+      grpc_server_cancel_all_calls(s->wrapped);
+      return Qfalse;
     }
     grpc_server_destroy(s->wrapped);
     s->wrapped = NULL;
   }
-  return Qnil;
+  return Qtrue;
 }
 
 /*
diff --git a/src/ruby/lib/grpc/generic/rpc_server.rb b/src/ruby/lib/grpc/generic/rpc_server.rb
index 67bf35c..38ea333 100644
--- a/src/ruby/lib/grpc/generic/rpc_server.rb
+++ b/src/ruby/lib/grpc/generic/rpc_server.rb
@@ -277,10 +277,11 @@
       @stop_mutex.synchronize do
         @stopped = true
       end
-      @pool.stop
       deadline = from_relative_time(@poll_period)
-
+      return if @server.close(@cq, deadline)
+      deadline = from_relative_time(@poll_period)
       @server.close(@cq, deadline)
+      @pool.stop
     end
 
     # determines if the server has been stopped
@@ -383,7 +384,6 @@
       @pool.start
       @server.start
       loop_handle_server_calls
-      @running = false
     end
 
     # Sends UNAVAILABLE if there are too many unprocessed jobs
@@ -414,14 +414,13 @@
       fail 'not running' unless @running
       loop_tag = Object.new
       until stopped?
-        deadline = from_relative_time(@poll_period)
         begin
-          an_rpc = @server.request_call(@cq, loop_tag, deadline)
+          an_rpc = @server.request_call(@cq, loop_tag, INFINITE_FUTURE)
           c = new_active_server_call(an_rpc)
         rescue Core::CallError, RuntimeError => e
           # these might happen for various reasonse.  The correct behaviour of
-          # the server is to log them and continue.
-          GRPC.logger.warn("server call failed: #{e}")
+          # the server is to log them and continue, if it's not shutting down.
+          GRPC.logger.warn("server call failed: #{e}") unless stopped?
           next
         end
         unless c.nil?
@@ -431,6 +430,8 @@
           end
         end
       end
+      @running = false
+      GRPC.logger.info("stopped: #{self}")
     end
 
     def new_active_server_call(an_rpc)
diff --git a/tools/dockerfile/grpc_php_base/Dockerfile b/tools/dockerfile/grpc_php_base/Dockerfile
index 23e95ba..aa20d6a 100644
--- a/tools/dockerfile/grpc_php_base/Dockerfile
+++ b/tools/dockerfile/grpc_php_base/Dockerfile
@@ -75,7 +75,7 @@
 
 # Download the patched PHP protobuf so that PHP gRPC clients can be generated
 # from proto3 schemas.
-RUN git clone https://github.com/murgatroid99/Protobuf-PHP.git /var/local/git/protobuf-php
+RUN git clone https://github.com/stanley-cheung/Protobuf-PHP.git /var/local/git/protobuf-php
 
 # Install ruby (via RVM) as ruby tools are dependencies for building Protobuf
 # PHP extensions.
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index 7d5df66..0b7f89f 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -1022,7 +1022,9 @@
 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 0585b82..7ce66de 100644
--- a/tools/run_tests/sources_and_headers.json
+++ b/tools/run_tests/sources_and_headers.json
@@ -12362,8 +12362,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", 
@@ -12825,8 +12827,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 1fa7e4b..f852161 100644
--- a/vsprojects/grpc/grpc.vcxproj
+++ b/vsprojects/grpc/grpc.vcxproj
@@ -625,8 +625,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 b22818a..835aa1b 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 3883a32..ca73b56 100644
--- a/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj
+++ b/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj
@@ -568,8 +568,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 d12abc0..994539c 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">