Merge remote-tracking branch 'upstream/master' into http_connect
diff --git a/.gitignore b/.gitignore
index 09223fa..75a73a1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -99,3 +99,6 @@
 
 # Git generated files for conflicting
 *.orig
+
+# IDE specific folder for JetBrains IDEs
+.idea/
diff --git a/BUILD b/BUILD
index bbfa21a..730dd70 100644
--- a/BUILD
+++ b/BUILD
@@ -307,11 +307,13 @@
     "src/core/ext/load_reporting/load_reporting.h",
     "src/core/ext/load_reporting/load_reporting_filter.h",
     "src/core/ext/census/aggregation.h",
+    "src/core/ext/census/base_resources.h",
     "src/core/ext/census/census_interface.h",
     "src/core/ext/census/census_rpc_stats.h",
     "src/core/ext/census/gen/census.pb.h",
     "src/core/ext/census/grpc_filter.h",
     "src/core/ext/census/mlog.h",
+    "src/core/ext/census/resource.h",
     "src/core/ext/census/rpc_metric_id.h",
     "src/core/lib/surface/init.c",
     "src/core/lib/channel/channel_args.c",
@@ -488,6 +490,7 @@
     "src/core/ext/resolver/sockaddr/sockaddr_resolver.c",
     "src/core/ext/load_reporting/load_reporting.c",
     "src/core/ext/load_reporting/load_reporting_filter.c",
+    "src/core/ext/census/base_resources.c",
     "src/core/ext/census/context.c",
     "src/core/ext/census/gen/census.pb.c",
     "src/core/ext/census/grpc_context.c",
@@ -497,6 +500,7 @@
     "src/core/ext/census/mlog.c",
     "src/core/ext/census/operation.c",
     "src/core/ext/census/placeholders.c",
+    "src/core/ext/census/resource.c",
     "src/core/ext/census/tracing.c",
     "src/core/plugin_registry/grpc_plugin_registry.c",
   ],
@@ -1032,11 +1036,13 @@
     "src/core/ext/lb_policy/grpclb/load_balancer_api.h",
     "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h",
     "src/core/ext/census/aggregation.h",
+    "src/core/ext/census/base_resources.h",
     "src/core/ext/census/census_interface.h",
     "src/core/ext/census/census_rpc_stats.h",
     "src/core/ext/census/gen/census.pb.h",
     "src/core/ext/census/grpc_filter.h",
     "src/core/ext/census/mlog.h",
+    "src/core/ext/census/resource.h",
     "src/core/ext/census/rpc_metric_id.h",
     "src/core/lib/surface/init.c",
     "src/core/lib/surface/init_unsecure.c",
@@ -1184,6 +1190,7 @@
     "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c",
     "src/core/ext/lb_policy/pick_first/pick_first.c",
     "src/core/ext/lb_policy/round_robin/round_robin.c",
+    "src/core/ext/census/base_resources.c",
     "src/core/ext/census/context.c",
     "src/core/ext/census/gen/census.pb.c",
     "src/core/ext/census/grpc_context.c",
@@ -1193,6 +1200,7 @@
     "src/core/ext/census/mlog.c",
     "src/core/ext/census/operation.c",
     "src/core/ext/census/placeholders.c",
+    "src/core/ext/census/resource.c",
     "src/core/ext/census/tracing.c",
     "src/core/plugin_registry/grpc_unsecure_plugin_registry.c",
   ],
@@ -1976,6 +1984,7 @@
     "src/core/ext/resolver/sockaddr/sockaddr_resolver.c",
     "src/core/ext/load_reporting/load_reporting.c",
     "src/core/ext/load_reporting/load_reporting_filter.c",
+    "src/core/ext/census/base_resources.c",
     "src/core/ext/census/context.c",
     "src/core/ext/census/gen/census.pb.c",
     "src/core/ext/census/grpc_context.c",
@@ -1985,6 +1994,7 @@
     "src/core/ext/census/mlog.c",
     "src/core/ext/census/operation.c",
     "src/core/ext/census/placeholders.c",
+    "src/core/ext/census/resource.c",
     "src/core/ext/census/tracing.c",
     "src/core/plugin_registry/grpc_plugin_registry.c",
   ],
@@ -2167,11 +2177,13 @@
     "src/core/ext/load_reporting/load_reporting.h",
     "src/core/ext/load_reporting/load_reporting_filter.h",
     "src/core/ext/census/aggregation.h",
+    "src/core/ext/census/base_resources.h",
     "src/core/ext/census/census_interface.h",
     "src/core/ext/census/census_rpc_stats.h",
     "src/core/ext/census/gen/census.pb.h",
     "src/core/ext/census/grpc_filter.h",
     "src/core/ext/census/mlog.h",
+    "src/core/ext/census/resource.h",
     "src/core/ext/census/rpc_metric_id.h",
   ],
   includes = [
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d9c4eae..e1e2c7d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -455,6 +455,7 @@
   src/core/ext/resolver/sockaddr/sockaddr_resolver.c
   src/core/ext/load_reporting/load_reporting.c
   src/core/ext/load_reporting/load_reporting_filter.c
+  src/core/ext/census/base_resources.c
   src/core/ext/census/context.c
   src/core/ext/census/gen/census.pb.c
   src/core/ext/census/grpc_context.c
@@ -464,6 +465,7 @@
   src/core/ext/census/mlog.c
   src/core/ext/census/operation.c
   src/core/ext/census/placeholders.c
+  src/core/ext/census/resource.c
   src/core/ext/census/tracing.c
   src/core/plugin_registry/grpc_plugin_registry.c
 )
@@ -911,6 +913,7 @@
   third_party/nanopb/pb_encode.c
   src/core/ext/lb_policy/pick_first/pick_first.c
   src/core/ext/lb_policy/round_robin/round_robin.c
+  src/core/ext/census/base_resources.c
   src/core/ext/census/context.c
   src/core/ext/census/gen/census.pb.c
   src/core/ext/census/grpc_context.c
@@ -920,6 +923,7 @@
   src/core/ext/census/mlog.c
   src/core/ext/census/operation.c
   src/core/ext/census/placeholders.c
+  src/core/ext/census/resource.c
   src/core/ext/census/tracing.c
   src/core/plugin_registry/grpc_unsecure_plugin_registry.c
 )
diff --git a/Makefile b/Makefile
index 108e2b8..4d0bc2e 100644
--- a/Makefile
+++ b/Makefile
@@ -915,6 +915,7 @@
 bin_decoder_test: $(BINDIR)/$(CONFIG)/bin_decoder_test
 bin_encoder_test: $(BINDIR)/$(CONFIG)/bin_encoder_test
 census_context_test: $(BINDIR)/$(CONFIG)/census_context_test
+census_resource_test: $(BINDIR)/$(CONFIG)/census_resource_test
 channel_create_test: $(BINDIR)/$(CONFIG)/channel_create_test
 chttp2_hpack_encoder_test: $(BINDIR)/$(CONFIG)/chttp2_hpack_encoder_test
 chttp2_status_conversion_test: $(BINDIR)/$(CONFIG)/chttp2_status_conversion_test
@@ -1236,6 +1237,7 @@
   $(BINDIR)/$(CONFIG)/bin_decoder_test \
   $(BINDIR)/$(CONFIG)/bin_encoder_test \
   $(BINDIR)/$(CONFIG)/census_context_test \
+  $(BINDIR)/$(CONFIG)/census_resource_test \
   $(BINDIR)/$(CONFIG)/channel_create_test \
   $(BINDIR)/$(CONFIG)/chttp2_hpack_encoder_test \
   $(BINDIR)/$(CONFIG)/chttp2_status_conversion_test \
@@ -1543,6 +1545,8 @@
 	$(Q) $(BINDIR)/$(CONFIG)/bin_encoder_test || ( echo test bin_encoder_test failed ; exit 1 )
 	$(E) "[RUN]     Testing census_context_test"
 	$(Q) $(BINDIR)/$(CONFIG)/census_context_test || ( echo test census_context_test failed ; exit 1 )
+	$(E) "[RUN]     Testing census_resource_test"
+	$(Q) $(BINDIR)/$(CONFIG)/census_resource_test || ( echo test census_resource_test failed ; exit 1 )
 	$(E) "[RUN]     Testing channel_create_test"
 	$(Q) $(BINDIR)/$(CONFIG)/channel_create_test || ( echo test channel_create_test failed ; exit 1 )
 	$(E) "[RUN]     Testing chttp2_hpack_encoder_test"
@@ -2703,6 +2707,7 @@
     src/core/ext/resolver/sockaddr/sockaddr_resolver.c \
     src/core/ext/load_reporting/load_reporting.c \
     src/core/ext/load_reporting/load_reporting_filter.c \
+    src/core/ext/census/base_resources.c \
     src/core/ext/census/context.c \
     src/core/ext/census/gen/census.pb.c \
     src/core/ext/census/grpc_context.c \
@@ -2712,6 +2717,7 @@
     src/core/ext/census/mlog.c \
     src/core/ext/census/operation.c \
     src/core/ext/census/placeholders.c \
+    src/core/ext/census/resource.c \
     src/core/ext/census/tracing.c \
     src/core/plugin_registry/grpc_plugin_registry.c \
 
@@ -3408,6 +3414,7 @@
     third_party/nanopb/pb_encode.c \
     src/core/ext/lb_policy/pick_first/pick_first.c \
     src/core/ext/lb_policy/round_robin/round_robin.c \
+    src/core/ext/census/base_resources.c \
     src/core/ext/census/context.c \
     src/core/ext/census/gen/census.pb.c \
     src/core/ext/census/grpc_context.c \
@@ -3417,6 +3424,7 @@
     src/core/ext/census/mlog.c \
     src/core/ext/census/operation.c \
     src/core/ext/census/placeholders.c \
+    src/core/ext/census/resource.c \
     src/core/ext/census/tracing.c \
     src/core/plugin_registry/grpc_unsecure_plugin_registry.c \
 
@@ -6527,6 +6535,7 @@
     test/core/end2end/tests/default_host.c \
     test/core/end2end/tests/disappearing_server.c \
     test/core/end2end/tests/empty_batch.c \
+    test/core/end2end/tests/filter_call_init_fails.c \
     test/core/end2end/tests/filter_causes_close.c \
     test/core/end2end/tests/graceful_server_shutdown.c \
     test/core/end2end/tests/high_initial_seqno.c \
@@ -6606,6 +6615,7 @@
     test/core/end2end/tests/default_host.c \
     test/core/end2end/tests/disappearing_server.c \
     test/core/end2end/tests/empty_batch.c \
+    test/core/end2end/tests/filter_call_init_fails.c \
     test/core/end2end/tests/filter_causes_close.c \
     test/core/end2end/tests/graceful_server_shutdown.c \
     test/core/end2end/tests/high_initial_seqno.c \
@@ -6948,6 +6958,38 @@
 endif
 
 
+CENSUS_RESOURCE_TEST_SRC = \
+    test/core/census/resource_test.c \
+
+CENSUS_RESOURCE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CENSUS_RESOURCE_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/census_resource_test: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/census_resource_test: $(CENSUS_RESOURCE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS) $(CENSUS_RESOURCE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/census_resource_test
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/census/resource_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_census_resource_test: $(CENSUS_RESOURCE_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(CENSUS_RESOURCE_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
 CHANNEL_CREATE_TEST_SRC = \
     test/core/surface/channel_create_test.c \
 
diff --git a/binding.gyp b/binding.gyp
index 6e4e511..7768faa 100644
--- a/binding.gyp
+++ b/binding.gyp
@@ -740,6 +740,7 @@
         'src/core/ext/resolver/sockaddr/sockaddr_resolver.c',
         'src/core/ext/load_reporting/load_reporting.c',
         'src/core/ext/load_reporting/load_reporting_filter.c',
+        'src/core/ext/census/base_resources.c',
         'src/core/ext/census/context.c',
         'src/core/ext/census/gen/census.pb.c',
         'src/core/ext/census/grpc_context.c',
@@ -749,6 +750,7 @@
         'src/core/ext/census/mlog.c',
         'src/core/ext/census/operation.c',
         'src/core/ext/census/placeholders.c',
+        'src/core/ext/census/resource.c',
         'src/core/ext/census/tracing.c',
         'src/core/plugin_registry/grpc_plugin_registry.c',
       ],
diff --git a/build.yaml b/build.yaml
index 617fa71..ca406de 100644
--- a/build.yaml
+++ b/build.yaml
@@ -14,13 +14,16 @@
   - include/grpc/census.h
   headers:
   - src/core/ext/census/aggregation.h
+  - src/core/ext/census/base_resources.h
   - src/core/ext/census/census_interface.h
   - src/core/ext/census/census_rpc_stats.h
   - src/core/ext/census/gen/census.pb.h
   - src/core/ext/census/grpc_filter.h
   - src/core/ext/census/mlog.h
+  - src/core/ext/census/resource.h
   - src/core/ext/census/rpc_metric_id.h
   src:
+  - src/core/ext/census/base_resources.c
   - src/core/ext/census/context.c
   - src/core/ext/census/gen/census.pb.c
   - src/core/ext/census/grpc_context.c
@@ -30,6 +33,7 @@
   - src/core/ext/census/mlog.c
   - src/core/ext/census/operation.c
   - src/core/ext/census/placeholders.c
+  - src/core/ext/census/resource.c
   - src/core/ext/census/tracing.c
   plugin: census_grpc_plugin
   uses:
@@ -1305,6 +1309,16 @@
   - grpc
   - gpr_test_util
   - gpr
+- name: census_resource_test
+  build: test
+  language: c
+  src:
+  - test/core/census/resource_test.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
 - name: channel_create_test
   build: test
   language: c
diff --git a/config.m4 b/config.m4
index 3df7c6c..5cb8fbd 100644
--- a/config.m4
+++ b/config.m4
@@ -259,6 +259,7 @@
     src/core/ext/resolver/sockaddr/sockaddr_resolver.c \
     src/core/ext/load_reporting/load_reporting.c \
     src/core/ext/load_reporting/load_reporting_filter.c \
+    src/core/ext/census/base_resources.c \
     src/core/ext/census/context.c \
     src/core/ext/census/gen/census.pb.c \
     src/core/ext/census/grpc_context.c \
@@ -268,6 +269,7 @@
     src/core/ext/census/mlog.c \
     src/core/ext/census/operation.c \
     src/core/ext/census/placeholders.c \
+    src/core/ext/census/resource.c \
     src/core/ext/census/tracing.c \
     src/core/plugin_registry/grpc_plugin_registry.c \
     src/boringssl/err_data.c \
diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec
index 05ad3d7..505d8ae 100644
--- a/gRPC-Core.podspec
+++ b/gRPC-Core.podspec
@@ -404,11 +404,13 @@
                       'src/core/ext/load_reporting/load_reporting.h',
                       'src/core/ext/load_reporting/load_reporting_filter.h',
                       'src/core/ext/census/aggregation.h',
+                      'src/core/ext/census/base_resources.h',
                       'src/core/ext/census/census_interface.h',
                       'src/core/ext/census/census_rpc_stats.h',
                       'src/core/ext/census/gen/census.pb.h',
                       'src/core/ext/census/grpc_filter.h',
                       'src/core/ext/census/mlog.h',
+                      'src/core/ext/census/resource.h',
                       'src/core/ext/census/rpc_metric_id.h',
                       'src/core/lib/surface/init.c',
                       'src/core/lib/channel/channel_args.c',
@@ -588,6 +590,7 @@
                       'src/core/ext/resolver/sockaddr/sockaddr_resolver.c',
                       'src/core/ext/load_reporting/load_reporting.c',
                       'src/core/ext/load_reporting/load_reporting_filter.c',
+                      'src/core/ext/census/base_resources.c',
                       'src/core/ext/census/context.c',
                       'src/core/ext/census/gen/census.pb.c',
                       'src/core/ext/census/grpc_context.c',
@@ -597,6 +600,7 @@
                       'src/core/ext/census/mlog.c',
                       'src/core/ext/census/operation.c',
                       'src/core/ext/census/placeholders.c',
+                      'src/core/ext/census/resource.c',
                       'src/core/ext/census/tracing.c',
                       'src/core/plugin_registry/grpc_plugin_registry.c'
 
@@ -763,11 +767,13 @@
                               'src/core/ext/load_reporting/load_reporting.h',
                               'src/core/ext/load_reporting/load_reporting_filter.h',
                               'src/core/ext/census/aggregation.h',
+                              'src/core/ext/census/base_resources.h',
                               'src/core/ext/census/census_interface.h',
                               'src/core/ext/census/census_rpc_stats.h',
                               'src/core/ext/census/gen/census.pb.h',
                               'src/core/ext/census/grpc_filter.h',
                               'src/core/ext/census/mlog.h',
+                              'src/core/ext/census/resource.h',
                               'src/core/ext/census/rpc_metric_id.h'
   end
 
diff --git a/grpc.def b/grpc.def
index c2f83f5..e2255df 100644
--- a/grpc.def
+++ b/grpc.def
@@ -23,15 +23,10 @@
     census_trace_scan_start
     census_get_trace_record
     census_trace_scan_end
+    census_define_resource
+    census_delete_resource
+    census_resource_id
     census_record_values
-    census_view_create
-    census_view_delete
-    census_view_metric
-    census_view_naggregations
-    census_view_tags
-    census_view_aggregrations
-    census_view_get_data
-    census_view_reset
     grpc_compression_algorithm_parse
     grpc_compression_algorithm_name
     grpc_compression_algorithm_for_level
diff --git a/grpc.gemspec b/grpc.gemspec
index 15ad66f..06521ca 100755
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -323,11 +323,13 @@
   s.files += %w( src/core/ext/load_reporting/load_reporting.h )
   s.files += %w( src/core/ext/load_reporting/load_reporting_filter.h )
   s.files += %w( src/core/ext/census/aggregation.h )
+  s.files += %w( src/core/ext/census/base_resources.h )
   s.files += %w( src/core/ext/census/census_interface.h )
   s.files += %w( src/core/ext/census/census_rpc_stats.h )
   s.files += %w( src/core/ext/census/gen/census.pb.h )
   s.files += %w( src/core/ext/census/grpc_filter.h )
   s.files += %w( src/core/ext/census/mlog.h )
+  s.files += %w( src/core/ext/census/resource.h )
   s.files += %w( src/core/ext/census/rpc_metric_id.h )
   s.files += %w( src/core/lib/surface/init.c )
   s.files += %w( src/core/lib/channel/channel_args.c )
@@ -507,6 +509,7 @@
   s.files += %w( src/core/ext/resolver/sockaddr/sockaddr_resolver.c )
   s.files += %w( src/core/ext/load_reporting/load_reporting.c )
   s.files += %w( src/core/ext/load_reporting/load_reporting_filter.c )
+  s.files += %w( src/core/ext/census/base_resources.c )
   s.files += %w( src/core/ext/census/context.c )
   s.files += %w( src/core/ext/census/gen/census.pb.c )
   s.files += %w( src/core/ext/census/grpc_context.c )
@@ -516,6 +519,7 @@
   s.files += %w( src/core/ext/census/mlog.c )
   s.files += %w( src/core/ext/census/operation.c )
   s.files += %w( src/core/ext/census/placeholders.c )
+  s.files += %w( src/core/ext/census/resource.c )
   s.files += %w( src/core/ext/census/tracing.c )
   s.files += %w( src/core/plugin_registry/grpc_plugin_registry.c )
   s.files += %w( third_party/boringssl/crypto/aes/internal.h )
diff --git a/include/grpc++/impl/codegen/core_codegen.h b/include/grpc++/impl/codegen/core_codegen.h
index 9699abf..2586b94 100644
--- a/include/grpc++/impl/codegen/core_codegen.h
+++ b/include/grpc++/impl/codegen/core_codegen.h
@@ -31,6 +31,9 @@
  *
  */
 
+#ifndef GRPCXX_IMPL_CODEGEN_CORE_CODEGEN_H
+#define GRPCXX_IMPL_CODEGEN_CORE_CODEGEN_H
+
 // This file should be compiled as part of grpc++.
 
 #include <grpc++/impl/codegen/core_codegen_interface.h>
@@ -83,3 +86,5 @@
 };
 
 }  // namespace grpc
+
+#endif  // GRPCXX_IMPL_CODEGEN_CORE_CODEGEN_H
diff --git a/include/grpc/census.h b/include/grpc/census.h
index 39d87ba..62ff45d 100644
--- a/include/grpc/census.h
+++ b/include/grpc/census.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -56,9 +56,11 @@
 
 /** Shutdown and startup census subsystem. The 'features' argument should be
  * the OR (|) of census_features values. If census fails to initialize, then
- * census_initialize() will return a non-zero value. It is an error to call
- * census_initialize() more than once (without an intervening
- * census_shutdown()). */
+ * census_initialize() will return -1, otherwise the set of enabled features
+ * (which may be smaller than that provided in the `features` argument, see
+ * census_supported()) is returned. It is an error to call census_initialize()
+ * more than once (without an intervening census_shutdown()). These functions
+ * are not thread-safe. */
 CENSUSAPI int census_initialize(int features);
 CENSUSAPI void census_shutdown(void);
 
@@ -430,30 +432,44 @@
 CENSUSAPI void census_trace_scan_end();
 
 /* Core stats collection API's. The following concepts are used:
-   * Aggregation: A collection of values. Census supports the following
-       aggregation types:
-         Sum - a single summation type. Typically used for keeping (e.g.)
-           counts of events.
-         Distribution - statistical distribution information, used for
-           recording average, standard deviation etc.
-         Histogram - a histogram of measurements falling in defined bucket
-           boundaries.
-         Window - a count of events that happen in reolling time window.
-     New aggregation types can be added by the user, if desired (see
-     census_register_aggregation()).
-   * Metric: Each measurement is for a single metric. Examples include RPC
-     latency, CPU seconds consumed, and bytes transmitted.
-   * View: A view is a combination of a metric, a tag set (in which the tag
-     values are regular expressions) and a set of aggregations. When a
-     measurement for a metric matches the view tags, it is recorded (for each
-     unique set of tags) against each aggregation. Each metric can have an
-     arbitrary number of views by which it will be broken down.
+   * Resource: Users record measurements for a single resource. Examples
+     include RPC latency, CPU seconds consumed, and bytes transmitted.
+   * Aggregation: An aggregation of a set of measurements. Census supports the
+       following aggregation types:
+       * Distribution - statistical distribution information, used for
+         recording average, standard deviation etc. Can include a histogram.
+       * Interval - a count of events that happen in a rolling time window.
+   * View: A view is a combination of a Resource, a set of tag keys and an
+     Aggregation. When a measurement for a Resource matches the View tags, it is
+     recorded (for each unique set of tag values) using the Aggregation type.
+     Each resource can have an arbitrary number of views by which it will be
+     broken down.
+
+  Census uses protos to define each of the above, and output results. This
+  ensures unification across the different language and runtime
+  implementations. The proto definitions can be found in src/proto/census.
 */
 
+/* Define a new resource. `resource_pb` should contain an encoded Resource
+   protobuf, `resource_pb_size` being the size of the buffer. Returns a -ve
+   value on error, or a positive (>= 0) resource id (for use in
+   census_delete_resource() and census_record_values()). In order to be valid, a
+   resource must have a name, and at least one numerator in it's unit type. The
+   resource name must be unique, and an error will be returned if it is not. */
+CENSUSAPI int32_t census_define_resource(const uint8_t *resource_pb,
+                                         size_t resource_pb_size);
+
+/* Delete a resource created by census_define_resource(). */
+CENSUSAPI void census_delete_resource(int32_t resource_id);
+
+/* Determine the id of a resource, given it's name. returns -1 if the resource
+   does not exist. */
+CENSUSAPI int32_t census_resource_id(const char *name);
+
 /* A single value to be recorded comprises two parts: an ID for the particular
- * metric and the value to be recorded against it. */
+ * resource and the value to be recorded against it. */
 typedef struct {
-  uint32_t metric_id;
+  int32_t resource_id;
   double value;
 } census_value;
 
@@ -461,78 +477,6 @@
 CENSUSAPI void census_record_values(census_context *context,
                                     census_value *values, size_t nvalues);
 
-/** Type representing a particular aggregation */
-typedef struct census_aggregation_ops census_aggregation_ops;
-
-/* Predefined aggregation types, for use with census_view_create(). */
-extern census_aggregation_ops census_agg_sum;
-extern census_aggregation_ops census_agg_distribution;
-extern census_aggregation_ops census_agg_histogram;
-extern census_aggregation_ops census_agg_window;
-
-/** Information needed to instantiate a new aggregation. Used in view
-    construction via census_define_view(). */
-typedef struct {
-  const census_aggregation_ops *ops;
-  const void *create_arg; /* Aaggregation initialization argument. */
-} census_aggregation;
-
-/** A census view type. Opaque. */
-typedef struct census_view census_view;
-
-/** Create a new view.
-  @param metric_id Metric with which this view is associated.
-  @param tags tags that define the view.
-  @param aggregations aggregations to associate with the view
-  @param naggregations number of aggregations
-
-  @return A new census view
-*/
-
-/* TODO(aveitch): consider if context is the right argument type to pass in
-   tags. */
-CENSUSAPI census_view *census_view_create(
-    uint32_t metric_id, const census_context *tags,
-    const census_aggregation *aggregations, size_t naggregations);
-
-/** Destroy a previously created view. */
-CENSUSAPI void census_view_delete(census_view *view);
-
-/** Metric ID associated with a view */
-CENSUSAPI size_t census_view_metric(const census_view *view);
-
-/** Number of aggregations associated with view. */
-CENSUSAPI size_t census_view_naggregations(const census_view *view);
-
-/** Get tags associated with view. */
-CENSUSAPI const census_context *census_view_tags(const census_view *view);
-
-/** Get aggregation descriptors associated with a view. */
-CENSUSAPI const census_aggregation *census_view_aggregrations(
-    const census_view *view);
-
-/** Holds all the aggregation data for a particular view instantiation. Forms
-  part of the data returned by census_view_data(). */
-typedef struct {
-  const census_context *tags; /* Tags for this set of aggregations. */
-  const void **data; /* One data set for every aggregation in the view. */
-} census_view_aggregation_data;
-
-/** Census view data as returned by census_view_get_data(). */
-typedef struct {
-  size_t n_tag_sets; /* Number of unique tag sets that matched view. */
-  const census_view_aggregation_data *data; /* n_tag_sets entries */
-} census_view_data;
-
-/** Get data from aggregations associated with a view.
-  @param view View from which to get data.
-  @return Full set of data for all aggregations for the view.
-*/
-CENSUSAPI const census_view_data *census_view_get_data(const census_view *view);
-
-/** Reset all view data to zero for the specified view */
-CENSUSAPI void census_view_reset(census_view *view);
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/package.xml b/package.xml
index ceed850..ab778cb 100644
--- a/package.xml
+++ b/package.xml
@@ -331,11 +331,13 @@
     <file baseinstalldir="/" name="src/core/ext/load_reporting/load_reporting.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/load_reporting/load_reporting_filter.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/census/aggregation.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/census/base_resources.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/census/census_interface.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/census/census_rpc_stats.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/census/gen/census.pb.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/census/grpc_filter.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/census/mlog.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/census/resource.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/census/rpc_metric_id.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/init.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/channel/channel_args.c" role="src" />
@@ -515,6 +517,7 @@
     <file baseinstalldir="/" name="src/core/ext/resolver/sockaddr/sockaddr_resolver.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/load_reporting/load_reporting.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/load_reporting/load_reporting_filter.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/census/base_resources.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/census/context.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/census/gen/census.pb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/census/grpc_context.c" role="src" />
@@ -524,6 +527,7 @@
     <file baseinstalldir="/" name="src/core/ext/census/mlog.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/census/operation.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/census/placeholders.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/census/resource.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/census/tracing.c" role="src" />
     <file baseinstalldir="/" name="src/core/plugin_registry/grpc_plugin_registry.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl/crypto/aes/internal.h" role="src" />
diff --git a/src/core/ext/census/base_resources.c b/src/core/ext/census/base_resources.c
new file mode 100644
index 0000000..f9aa4bb
--- /dev/null
+++ b/src/core/ext/census/base_resources.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2016, 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 "src/core/ext/census/base_resources.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include <grpc/census.h>
+#include <grpc/support/log.h>
+
+#include "src/core/ext/census/resource.h"
+
+// Add base RPC resource definitions for use by RPC runtime.
+//
+// TODO(aveitch): All of these are currently hardwired definitions encoded in
+// the code in this file. These should be converted to use an external
+// configuration mechanism, in which these resources are defined in a text
+// file, which is compiled to .pb format and read by still-to-be-written
+// configuration functions.
+
+// Define all base resources. This should be called by census initialization.
+void define_base_resources() {
+  google_census_Resource_BasicUnit numerator =
+      google_census_Resource_BasicUnit_SECS;
+  resource r = {"client_rpc_latency",             // name
+                "Client RPC latency in seconds",  // description
+                0,                                // prefix
+                1,                                // n_numerators
+                &numerator,                       // numerators
+                0,                                // n_denominators
+                NULL};                            // denominators
+  define_resource(&r);
+  r = (resource){"server_rpc_latency",             // name
+                 "Server RPC latency in seconds",  // description
+                 0,                                // prefix
+                 1,                                // n_numerators
+                 &numerator,                       // numerators
+                 0,                                // n_denominators
+                 NULL};                            // denominators
+  define_resource(&r);
+}
diff --git a/src/core/ext/census/base_resources.h b/src/core/ext/census/base_resources.h
new file mode 100644
index 0000000..e5a7696
--- /dev/null
+++ b/src/core/ext/census/base_resources.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2016, 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.
+ *
+ */
+
+#ifndef GRPC_CORE_EXT_CENSUS_BASE_RESOURCES_H
+#define GRPC_CORE_EXT_CENSUS_BASE_RESOURCES_H
+
+/* Define all base resources. This should be called by census initialization. */
+void define_base_resources();
+
+#endif /* GRPC_CORE_EXT_CENSUS_BASE_RESOURCES_H */
diff --git a/src/core/ext/census/gen/census.pb.c b/src/core/ext/census/gen/census.pb.c
index d614636..647f063 100644
--- a/src/core/ext/census/gen/census.pb.c
+++ b/src/core/ext/census/gen/census.pb.c
@@ -53,29 +53,24 @@
     PB_LAST_FIELD
 };
 
-const pb_field_t google_census_Metric_fields[5] = {
-    PB_FIELD(  1, STRING  , OPTIONAL, CALLBACK, FIRST, google_census_Metric, name, name, 0),
-    PB_FIELD(  2, STRING  , OPTIONAL, CALLBACK, OTHER, google_census_Metric, description, name, 0),
-    PB_FIELD(  3, MESSAGE , OPTIONAL, STATIC  , OTHER, google_census_Metric, unit, description, &google_census_Metric_MeasurementUnit_fields),
-    PB_FIELD(  4, INT32   , OPTIONAL, STATIC  , OTHER, google_census_Metric, id, unit, 0),
+const pb_field_t google_census_Resource_fields[4] = {
+    PB_FIELD(  1, STRING  , OPTIONAL, CALLBACK, FIRST, google_census_Resource, name, name, 0),
+    PB_FIELD(  2, STRING  , OPTIONAL, CALLBACK, OTHER, google_census_Resource, description, name, 0),
+    PB_FIELD(  3, MESSAGE , OPTIONAL, STATIC  , OTHER, google_census_Resource, unit, description, &google_census_Resource_MeasurementUnit_fields),
     PB_LAST_FIELD
 };
 
-const pb_field_t google_census_Metric_BasicUnit_fields[2] = {
-    PB_FIELD(  1, UENUM   , OPTIONAL, STATIC  , FIRST, google_census_Metric_BasicUnit, type, type, 0),
+const pb_field_t google_census_Resource_MeasurementUnit_fields[4] = {
+    PB_FIELD(  1, INT32   , OPTIONAL, STATIC  , FIRST, google_census_Resource_MeasurementUnit, prefix, prefix, 0),
+    PB_FIELD(  2, UENUM   , REPEATED, CALLBACK, OTHER, google_census_Resource_MeasurementUnit, numerator, prefix, 0),
+    PB_FIELD(  3, UENUM   , REPEATED, CALLBACK, OTHER, google_census_Resource_MeasurementUnit, denominator, numerator, 0),
     PB_LAST_FIELD
 };
 
-const pb_field_t google_census_Metric_MeasurementUnit_fields[4] = {
-    PB_FIELD(  1, INT32   , OPTIONAL, STATIC  , FIRST, google_census_Metric_MeasurementUnit, prefix, prefix, 0),
-    PB_FIELD(  2, MESSAGE , REPEATED, CALLBACK, OTHER, google_census_Metric_MeasurementUnit, numerator, prefix, &google_census_Metric_BasicUnit_fields),
-    PB_FIELD(  3, MESSAGE , REPEATED, CALLBACK, OTHER, google_census_Metric_MeasurementUnit, denominator, numerator, &google_census_Metric_BasicUnit_fields),
-    PB_LAST_FIELD
-};
-
-const pb_field_t google_census_AggregationDescriptor_fields[3] = {
-    PB_ONEOF_FIELD(options,   1, MESSAGE , ONEOF, STATIC  , FIRST, google_census_AggregationDescriptor, bucket_boundaries, bucket_boundaries, &google_census_AggregationDescriptor_BucketBoundaries_fields),
-    PB_ONEOF_FIELD(options,   2, MESSAGE , ONEOF, STATIC  , FIRST, google_census_AggregationDescriptor, interval_boundaries, interval_boundaries, &google_census_AggregationDescriptor_IntervalBoundaries_fields),
+const pb_field_t google_census_AggregationDescriptor_fields[4] = {
+    PB_FIELD(  1, UENUM   , OPTIONAL, STATIC  , FIRST, google_census_AggregationDescriptor, type, type, 0),
+    PB_ONEOF_FIELD(options,   2, MESSAGE , ONEOF, STATIC  , OTHER, google_census_AggregationDescriptor, bucket_boundaries, type, &google_census_AggregationDescriptor_BucketBoundaries_fields),
+    PB_ONEOF_FIELD(options,   3, MESSAGE , ONEOF, STATIC  , OTHER, google_census_AggregationDescriptor, interval_boundaries, type, &google_census_AggregationDescriptor_IntervalBoundaries_fields),
     PB_LAST_FIELD
 };
 
@@ -124,25 +119,27 @@
 const pb_field_t google_census_View_fields[6] = {
     PB_FIELD(  1, STRING  , OPTIONAL, CALLBACK, FIRST, google_census_View, name, name, 0),
     PB_FIELD(  2, STRING  , OPTIONAL, CALLBACK, OTHER, google_census_View, description, name, 0),
-    PB_FIELD(  3, INT32   , OPTIONAL, STATIC  , OTHER, google_census_View, metric_id, description, 0),
-    PB_FIELD(  4, MESSAGE , OPTIONAL, STATIC  , OTHER, google_census_View, aggregation, metric_id, &google_census_AggregationDescriptor_fields),
+    PB_FIELD(  3, STRING  , OPTIONAL, CALLBACK, OTHER, google_census_View, resource_name, description, 0),
+    PB_FIELD(  4, MESSAGE , OPTIONAL, STATIC  , OTHER, google_census_View, aggregation, resource_name, &google_census_AggregationDescriptor_fields),
     PB_FIELD(  5, STRING  , REPEATED, CALLBACK, OTHER, google_census_View, tag_key, aggregation, 0),
     PB_LAST_FIELD
 };
 
-const pb_field_t google_census_Aggregation_fields[6] = {
+const pb_field_t google_census_Aggregation_fields[7] = {
     PB_FIELD(  1, STRING  , OPTIONAL, CALLBACK, FIRST, google_census_Aggregation, name, name, 0),
     PB_FIELD(  2, STRING  , OPTIONAL, CALLBACK, OTHER, google_census_Aggregation, description, name, 0),
-    PB_ONEOF_FIELD(data,   3, MESSAGE , ONEOF, STATIC  , OTHER, google_census_Aggregation, distribution, description, &google_census_Distribution_fields),
-    PB_ONEOF_FIELD(data,   4, MESSAGE , ONEOF, STATIC  , OTHER, google_census_Aggregation, interval_stats, description, &google_census_IntervalStats_fields),
-    PB_FIELD(  5, MESSAGE , REPEATED, CALLBACK, OTHER, google_census_Aggregation, tag, data.interval_stats, &google_census_Tag_fields),
+    PB_ONEOF_FIELD(data,   3, UINT64  , ONEOF, STATIC  , OTHER, google_census_Aggregation, count, description, 0),
+    PB_ONEOF_FIELD(data,   4, MESSAGE , ONEOF, STATIC  , OTHER, google_census_Aggregation, distribution, description, &google_census_Distribution_fields),
+    PB_ONEOF_FIELD(data,   5, MESSAGE , ONEOF, STATIC  , OTHER, google_census_Aggregation, interval_stats, description, &google_census_IntervalStats_fields),
+    PB_FIELD(  6, MESSAGE , REPEATED, CALLBACK, OTHER, google_census_Aggregation, tag, data.interval_stats, &google_census_Tag_fields),
     PB_LAST_FIELD
 };
 
-const pb_field_t google_census_ViewAggregations_fields[4] = {
-    PB_FIELD(  1, MESSAGE , REPEATED, CALLBACK, FIRST, google_census_ViewAggregations, aggregation, aggregation, &google_census_Aggregation_fields),
-    PB_FIELD(  2, MESSAGE , OPTIONAL, STATIC  , OTHER, google_census_ViewAggregations, start, aggregation, &google_census_Timestamp_fields),
-    PB_FIELD(  3, MESSAGE , OPTIONAL, STATIC  , OTHER, google_census_ViewAggregations, end, start, &google_census_Timestamp_fields),
+const pb_field_t google_census_Metric_fields[5] = {
+    PB_FIELD(  1, STRING  , OPTIONAL, CALLBACK, FIRST, google_census_Metric, view_name, view_name, 0),
+    PB_FIELD(  2, MESSAGE , REPEATED, CALLBACK, OTHER, google_census_Metric, aggregation, view_name, &google_census_Aggregation_fields),
+    PB_FIELD(  3, MESSAGE , OPTIONAL, STATIC  , OTHER, google_census_Metric, start, aggregation, &google_census_Timestamp_fields),
+    PB_FIELD(  4, MESSAGE , OPTIONAL, STATIC  , OTHER, google_census_Metric, end, start, &google_census_Timestamp_fields),
     PB_LAST_FIELD
 };
 
@@ -156,7 +153,7 @@
  * numbers or field sizes that are larger than what can fit in 8 or 16 bit
  * field descriptors.
  */
-PB_STATIC_ASSERT((pb_membersize(google_census_Metric, unit) < 65536 && pb_membersize(google_census_Metric_MeasurementUnit, numerator) < 65536 && pb_membersize(google_census_Metric_MeasurementUnit, denominator) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 65536 && pb_membersize(google_census_Metric, unit) < 65536 && pb_membersize(google_census_Metric_MeasurementUnit, numerator) < 65536 && pb_membersize(google_census_Metric_MeasurementUnit, denominator) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 65536 && pb_membersize(google_census_Distribution, range) < 65536 && pb_membersize(google_census_IntervalStats, window) < 65536 && pb_membersize(google_census_IntervalStats_Window, window_size) < 65536 && pb_membersize(google_census_View, aggregation) < 65536 && pb_membersize(google_census_Aggregation, data.distribution) < 65536 && pb_membersize(google_census_Aggregation, data.interval_stats) < 65536 && pb_membersize(google_census_Metric, unit) < 65536 && pb_membersize(google_census_Metric_MeasurementUnit, numerator) < 65536 && pb_membersize(google_census_Metric_MeasurementUnit, denominator) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 65536 && pb_membersize(google_census_Metric, unit) < 65536 && pb_membersize(google_census_Metric_MeasurementUnit, numerator) < 65536 && pb_membersize(google_census_Metric_MeasurementUnit, denominator) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 65536 && pb_membersize(google_census_Distribution, range) < 65536 && pb_membersize(google_census_IntervalStats, window) < 65536 && pb_membersize(google_census_IntervalStats_Window, window_size) < 65536 && pb_membersize(google_census_View, aggregation) < 65536 && pb_membersize(google_census_Aggregation, data.distribution) < 65536 && pb_membersize(google_census_Aggregation, data.interval_stats) < 65536 && pb_membersize(google_census_Aggregation, tag) < 65536 && pb_membersize(google_census_ViewAggregations, aggregation) < 65536 && pb_membersize(google_census_ViewAggregations, start) < 65536 && pb_membersize(google_census_ViewAggregations, end) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_google_census_Duration_google_census_Timestamp_google_census_Metric_google_census_Metric_BasicUnit_google_census_Metric_MeasurementUnit_google_census_AggregationDescriptor_google_census_AggregationDescriptor_BucketBoundaries_google_census_AggregationDescriptor_IntervalBoundaries_google_census_Distribution_google_census_Distribution_Range_google_census_IntervalStats_google_census_IntervalStats_Window_google_census_Tag_google_census_View_google_census_Aggregation_google_census_ViewAggregations)
+PB_STATIC_ASSERT((pb_membersize(google_census_Resource, unit) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 65536 && pb_membersize(google_census_Resource, unit) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 65536 && pb_membersize(google_census_Distribution, range) < 65536 && pb_membersize(google_census_IntervalStats, window) < 65536 && pb_membersize(google_census_IntervalStats_Window, window_size) < 65536 && pb_membersize(google_census_View, aggregation) < 65536 && pb_membersize(google_census_Aggregation, data.distribution) < 65536 && pb_membersize(google_census_Aggregation, data.interval_stats) < 65536 && pb_membersize(google_census_Resource, unit) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 65536 && pb_membersize(google_census_Resource, unit) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 65536 && pb_membersize(google_census_Distribution, range) < 65536 && pb_membersize(google_census_IntervalStats, window) < 65536 && pb_membersize(google_census_IntervalStats_Window, window_size) < 65536 && pb_membersize(google_census_View, aggregation) < 65536 && pb_membersize(google_census_Aggregation, data.distribution) < 65536 && pb_membersize(google_census_Aggregation, data.interval_stats) < 65536 && pb_membersize(google_census_Aggregation, tag) < 65536 && pb_membersize(google_census_Metric, aggregation) < 65536 && pb_membersize(google_census_Metric, start) < 65536 && pb_membersize(google_census_Metric, end) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_google_census_Duration_google_census_Timestamp_google_census_Resource_google_census_Resource_MeasurementUnit_google_census_AggregationDescriptor_google_census_AggregationDescriptor_BucketBoundaries_google_census_AggregationDescriptor_IntervalBoundaries_google_census_Distribution_google_census_Distribution_Range_google_census_IntervalStats_google_census_IntervalStats_Window_google_census_Tag_google_census_View_google_census_Aggregation_google_census_Metric)
 #endif
 
 #if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT)
@@ -167,7 +164,7 @@
  * numbers or field sizes that are larger than what can fit in the default
  * 8 bit descriptors.
  */
-PB_STATIC_ASSERT((pb_membersize(google_census_Metric, unit) < 256 && pb_membersize(google_census_Metric_MeasurementUnit, numerator) < 256 && pb_membersize(google_census_Metric_MeasurementUnit, denominator) < 256 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 256 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 256 && pb_membersize(google_census_Metric, unit) < 256 && pb_membersize(google_census_Metric_MeasurementUnit, numerator) < 256 && pb_membersize(google_census_Metric_MeasurementUnit, denominator) < 256 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 256 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 256 && pb_membersize(google_census_Distribution, range) < 256 && pb_membersize(google_census_IntervalStats, window) < 256 && pb_membersize(google_census_IntervalStats_Window, window_size) < 256 && pb_membersize(google_census_View, aggregation) < 256 && pb_membersize(google_census_Aggregation, data.distribution) < 256 && pb_membersize(google_census_Aggregation, data.interval_stats) < 256 && pb_membersize(google_census_Metric, unit) < 256 && pb_membersize(google_census_Metric_MeasurementUnit, numerator) < 256 && pb_membersize(google_census_Metric_MeasurementUnit, denominator) < 256 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 256 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 256 && pb_membersize(google_census_Metric, unit) < 256 && pb_membersize(google_census_Metric_MeasurementUnit, numerator) < 256 && pb_membersize(google_census_Metric_MeasurementUnit, denominator) < 256 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 256 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 256 && pb_membersize(google_census_Distribution, range) < 256 && pb_membersize(google_census_IntervalStats, window) < 256 && pb_membersize(google_census_IntervalStats_Window, window_size) < 256 && pb_membersize(google_census_View, aggregation) < 256 && pb_membersize(google_census_Aggregation, data.distribution) < 256 && pb_membersize(google_census_Aggregation, data.interval_stats) < 256 && pb_membersize(google_census_Aggregation, tag) < 256 && pb_membersize(google_census_ViewAggregations, aggregation) < 256 && pb_membersize(google_census_ViewAggregations, start) < 256 && pb_membersize(google_census_ViewAggregations, end) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_google_census_Duration_google_census_Timestamp_google_census_Metric_google_census_Metric_BasicUnit_google_census_Metric_MeasurementUnit_google_census_AggregationDescriptor_google_census_AggregationDescriptor_BucketBoundaries_google_census_AggregationDescriptor_IntervalBoundaries_google_census_Distribution_google_census_Distribution_Range_google_census_IntervalStats_google_census_IntervalStats_Window_google_census_Tag_google_census_View_google_census_Aggregation_google_census_ViewAggregations)
+PB_STATIC_ASSERT((pb_membersize(google_census_Resource, unit) < 256 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 256 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 256 && pb_membersize(google_census_Resource, unit) < 256 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 256 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 256 && pb_membersize(google_census_Distribution, range) < 256 && pb_membersize(google_census_IntervalStats, window) < 256 && pb_membersize(google_census_IntervalStats_Window, window_size) < 256 && pb_membersize(google_census_View, aggregation) < 256 && pb_membersize(google_census_Aggregation, data.distribution) < 256 && pb_membersize(google_census_Aggregation, data.interval_stats) < 256 && pb_membersize(google_census_Resource, unit) < 256 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 256 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 256 && pb_membersize(google_census_Resource, unit) < 256 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 256 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 256 && pb_membersize(google_census_Distribution, range) < 256 && pb_membersize(google_census_IntervalStats, window) < 256 && pb_membersize(google_census_IntervalStats_Window, window_size) < 256 && pb_membersize(google_census_View, aggregation) < 256 && pb_membersize(google_census_Aggregation, data.distribution) < 256 && pb_membersize(google_census_Aggregation, data.interval_stats) < 256 && pb_membersize(google_census_Aggregation, tag) < 256 && pb_membersize(google_census_Metric, aggregation) < 256 && pb_membersize(google_census_Metric, start) < 256 && pb_membersize(google_census_Metric, end) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_google_census_Duration_google_census_Timestamp_google_census_Resource_google_census_Resource_MeasurementUnit_google_census_AggregationDescriptor_google_census_AggregationDescriptor_BucketBoundaries_google_census_AggregationDescriptor_IntervalBoundaries_google_census_Distribution_google_census_Distribution_Range_google_census_IntervalStats_google_census_IntervalStats_Window_google_census_Tag_google_census_View_google_census_Aggregation_google_census_Metric)
 #endif
 
 
diff --git a/src/core/ext/census/gen/census.pb.h b/src/core/ext/census/gen/census.pb.h
index d040fe2..dae583f 100644
--- a/src/core/ext/census/gen/census.pb.h
+++ b/src/core/ext/census/gen/census.pb.h
@@ -45,14 +45,21 @@
 #endif
 
 /* Enum definitions */
-typedef enum _google_census_Metric_BasicUnit_Measure {
-    google_census_Metric_BasicUnit_Measure_UNKNOWN = 0,
-    google_census_Metric_BasicUnit_Measure_BITS = 1,
-    google_census_Metric_BasicUnit_Measure_BYTES = 2,
-    google_census_Metric_BasicUnit_Measure_SECS = 3,
-    google_census_Metric_BasicUnit_Measure_CORES = 4,
-    google_census_Metric_BasicUnit_Measure_MAX_UNITS = 5
-} google_census_Metric_BasicUnit_Measure;
+typedef enum _google_census_Resource_BasicUnit {
+    google_census_Resource_BasicUnit_UNKNOWN = 0,
+    google_census_Resource_BasicUnit_BITS = 1,
+    google_census_Resource_BasicUnit_BYTES = 2,
+    google_census_Resource_BasicUnit_SECS = 3,
+    google_census_Resource_BasicUnit_CORES = 4,
+    google_census_Resource_BasicUnit_MAX_UNITS = 5
+} google_census_Resource_BasicUnit;
+
+typedef enum _google_census_AggregationDescriptor_AggregationType {
+    google_census_AggregationDescriptor_AggregationType_UNKNOWN = 0,
+    google_census_AggregationDescriptor_AggregationType_COUNT = 1,
+    google_census_AggregationDescriptor_AggregationType_DISTRIBUTION = 2,
+    google_census_AggregationDescriptor_AggregationType_INTERVAL = 3
+} google_census_AggregationDescriptor_AggregationType;
 
 /* Struct definitions */
 typedef struct _google_census_AggregationDescriptor_BucketBoundaries {
@@ -68,6 +75,8 @@
 } google_census_IntervalStats;
 
 typedef struct _google_census_AggregationDescriptor {
+    bool has_type;
+    google_census_AggregationDescriptor_AggregationType type;
     pb_size_t which_options;
     union {
         google_census_AggregationDescriptor_BucketBoundaries bucket_boundaries;
@@ -89,17 +98,12 @@
     int32_t nanos;
 } google_census_Duration;
 
-typedef struct _google_census_Metric_BasicUnit {
-    bool has_type;
-    google_census_Metric_BasicUnit_Measure type;
-} google_census_Metric_BasicUnit;
-
-typedef struct _google_census_Metric_MeasurementUnit {
+typedef struct _google_census_Resource_MeasurementUnit {
     bool has_prefix;
     int32_t prefix;
     pb_callback_t numerator;
     pb_callback_t denominator;
-} google_census_Metric_MeasurementUnit;
+} google_census_Resource_MeasurementUnit;
 
 typedef struct _google_census_Tag {
     bool has_key;
@@ -135,37 +139,36 @@
 } google_census_IntervalStats_Window;
 
 typedef struct _google_census_Metric {
-    pb_callback_t name;
-    pb_callback_t description;
-    bool has_unit;
-    google_census_Metric_MeasurementUnit unit;
-    bool has_id;
-    int32_t id;
-} google_census_Metric;
-
-typedef struct _google_census_View {
-    pb_callback_t name;
-    pb_callback_t description;
-    bool has_metric_id;
-    int32_t metric_id;
-    bool has_aggregation;
-    google_census_AggregationDescriptor aggregation;
-    pb_callback_t tag_key;
-} google_census_View;
-
-typedef struct _google_census_ViewAggregations {
+    pb_callback_t view_name;
     pb_callback_t aggregation;
     bool has_start;
     google_census_Timestamp start;
     bool has_end;
     google_census_Timestamp end;
-} google_census_ViewAggregations;
+} google_census_Metric;
+
+typedef struct _google_census_Resource {
+    pb_callback_t name;
+    pb_callback_t description;
+    bool has_unit;
+    google_census_Resource_MeasurementUnit unit;
+} google_census_Resource;
+
+typedef struct _google_census_View {
+    pb_callback_t name;
+    pb_callback_t description;
+    pb_callback_t resource_name;
+    bool has_aggregation;
+    google_census_AggregationDescriptor aggregation;
+    pb_callback_t tag_key;
+} google_census_View;
 
 typedef struct _google_census_Aggregation {
     pb_callback_t name;
     pb_callback_t description;
     pb_size_t which_data;
     union {
+        uint64_t count;
         google_census_Distribution distribution;
         google_census_IntervalStats interval_stats;
     } data;
@@ -177,10 +180,9 @@
 /* Initializer values for message structs */
 #define google_census_Duration_init_default      {false, 0, false, 0}
 #define google_census_Timestamp_init_default     {false, 0, false, 0}
-#define google_census_Metric_init_default        {{{NULL}, NULL}, {{NULL}, NULL}, false, google_census_Metric_MeasurementUnit_init_default, false, 0}
-#define google_census_Metric_BasicUnit_init_default {false, (google_census_Metric_BasicUnit_Measure)0}
-#define google_census_Metric_MeasurementUnit_init_default {false, 0, {{NULL}, NULL}, {{NULL}, NULL}}
-#define google_census_AggregationDescriptor_init_default {0, {google_census_AggregationDescriptor_BucketBoundaries_init_default}}
+#define google_census_Resource_init_default      {{{NULL}, NULL}, {{NULL}, NULL}, false, google_census_Resource_MeasurementUnit_init_default}
+#define google_census_Resource_MeasurementUnit_init_default {false, 0, {{NULL}, NULL}, {{NULL}, NULL}}
+#define google_census_AggregationDescriptor_init_default {false, (google_census_AggregationDescriptor_AggregationType)0, 0, {google_census_AggregationDescriptor_BucketBoundaries_init_default}}
 #define google_census_AggregationDescriptor_BucketBoundaries_init_default {{{NULL}, NULL}}
 #define google_census_AggregationDescriptor_IntervalBoundaries_init_default {{{NULL}, NULL}}
 #define google_census_Distribution_init_default  {false, 0, false, 0, false, google_census_Distribution_Range_init_default, {{NULL}, NULL}}
@@ -188,15 +190,14 @@
 #define google_census_IntervalStats_init_default {{{NULL}, NULL}}
 #define google_census_IntervalStats_Window_init_default {false, google_census_Duration_init_default, false, 0, false, 0}
 #define google_census_Tag_init_default           {false, "", false, ""}
-#define google_census_View_init_default          {{{NULL}, NULL}, {{NULL}, NULL}, false, 0, false, google_census_AggregationDescriptor_init_default, {{NULL}, NULL}}
-#define google_census_Aggregation_init_default   {{{NULL}, NULL}, {{NULL}, NULL}, 0, {google_census_Distribution_init_default}, {{NULL}, NULL}}
-#define google_census_ViewAggregations_init_default {{{NULL}, NULL}, false, google_census_Timestamp_init_default, false, google_census_Timestamp_init_default}
+#define google_census_View_init_default          {{{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, false, google_census_AggregationDescriptor_init_default, {{NULL}, NULL}}
+#define google_census_Aggregation_init_default   {{{NULL}, NULL}, {{NULL}, NULL}, 0, {0}, {{NULL}, NULL}}
+#define google_census_Metric_init_default        {{{NULL}, NULL}, {{NULL}, NULL}, false, google_census_Timestamp_init_default, false, google_census_Timestamp_init_default}
 #define google_census_Duration_init_zero         {false, 0, false, 0}
 #define google_census_Timestamp_init_zero        {false, 0, false, 0}
-#define google_census_Metric_init_zero           {{{NULL}, NULL}, {{NULL}, NULL}, false, google_census_Metric_MeasurementUnit_init_zero, false, 0}
-#define google_census_Metric_BasicUnit_init_zero {false, (google_census_Metric_BasicUnit_Measure)0}
-#define google_census_Metric_MeasurementUnit_init_zero {false, 0, {{NULL}, NULL}, {{NULL}, NULL}}
-#define google_census_AggregationDescriptor_init_zero {0, {google_census_AggregationDescriptor_BucketBoundaries_init_zero}}
+#define google_census_Resource_init_zero         {{{NULL}, NULL}, {{NULL}, NULL}, false, google_census_Resource_MeasurementUnit_init_zero}
+#define google_census_Resource_MeasurementUnit_init_zero {false, 0, {{NULL}, NULL}, {{NULL}, NULL}}
+#define google_census_AggregationDescriptor_init_zero {false, (google_census_AggregationDescriptor_AggregationType)0, 0, {google_census_AggregationDescriptor_BucketBoundaries_init_zero}}
 #define google_census_AggregationDescriptor_BucketBoundaries_init_zero {{{NULL}, NULL}}
 #define google_census_AggregationDescriptor_IntervalBoundaries_init_zero {{{NULL}, NULL}}
 #define google_census_Distribution_init_zero     {false, 0, false, 0, false, google_census_Distribution_Range_init_zero, {{NULL}, NULL}}
@@ -204,25 +205,25 @@
 #define google_census_IntervalStats_init_zero    {{{NULL}, NULL}}
 #define google_census_IntervalStats_Window_init_zero {false, google_census_Duration_init_zero, false, 0, false, 0}
 #define google_census_Tag_init_zero              {false, "", false, ""}
-#define google_census_View_init_zero             {{{NULL}, NULL}, {{NULL}, NULL}, false, 0, false, google_census_AggregationDescriptor_init_zero, {{NULL}, NULL}}
-#define google_census_Aggregation_init_zero      {{{NULL}, NULL}, {{NULL}, NULL}, 0, {google_census_Distribution_init_zero}, {{NULL}, NULL}}
-#define google_census_ViewAggregations_init_zero {{{NULL}, NULL}, false, google_census_Timestamp_init_zero, false, google_census_Timestamp_init_zero}
+#define google_census_View_init_zero             {{{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, false, google_census_AggregationDescriptor_init_zero, {{NULL}, NULL}}
+#define google_census_Aggregation_init_zero      {{{NULL}, NULL}, {{NULL}, NULL}, 0, {0}, {{NULL}, NULL}}
+#define google_census_Metric_init_zero           {{{NULL}, NULL}, {{NULL}, NULL}, false, google_census_Timestamp_init_zero, false, google_census_Timestamp_init_zero}
 
 /* Field tags (for use in manual encoding/decoding) */
 #define google_census_AggregationDescriptor_BucketBoundaries_bounds_tag 1
 #define google_census_AggregationDescriptor_IntervalBoundaries_window_size_tag 1
 #define google_census_IntervalStats_window_tag   1
-#define google_census_AggregationDescriptor_bucket_boundaries_tag 1
+#define google_census_AggregationDescriptor_bucket_boundaries_tag 2
 
-#define google_census_AggregationDescriptor_interval_boundaries_tag 2
+#define google_census_AggregationDescriptor_interval_boundaries_tag 3
+#define google_census_AggregationDescriptor_type_tag 1
 #define google_census_Distribution_Range_min_tag 1
 #define google_census_Distribution_Range_max_tag 2
 #define google_census_Duration_seconds_tag       1
 #define google_census_Duration_nanos_tag         2
-#define google_census_Metric_BasicUnit_type_tag  1
-#define google_census_Metric_MeasurementUnit_prefix_tag 1
-#define google_census_Metric_MeasurementUnit_numerator_tag 2
-#define google_census_Metric_MeasurementUnit_denominator_tag 3
+#define google_census_Resource_MeasurementUnit_prefix_tag 1
+#define google_census_Resource_MeasurementUnit_numerator_tag 2
+#define google_census_Resource_MeasurementUnit_denominator_tag 3
 #define google_census_Tag_key_tag                1
 #define google_census_Tag_value_tag              2
 #define google_census_Timestamp_seconds_tag      1
@@ -234,32 +235,33 @@
 #define google_census_IntervalStats_Window_window_size_tag 1
 #define google_census_IntervalStats_Window_count_tag 2
 #define google_census_IntervalStats_Window_mean_tag 3
-#define google_census_Metric_name_tag            1
-#define google_census_Metric_description_tag     2
-#define google_census_Metric_unit_tag            3
-#define google_census_Metric_id_tag              4
+#define google_census_Metric_view_name_tag       1
+#define google_census_Metric_aggregation_tag     2
+#define google_census_Metric_start_tag           3
+#define google_census_Metric_end_tag             4
+#define google_census_Resource_name_tag          1
+#define google_census_Resource_description_tag   2
+#define google_census_Resource_unit_tag          3
 #define google_census_View_name_tag              1
 #define google_census_View_description_tag       2
-#define google_census_View_metric_id_tag         3
+#define google_census_View_resource_name_tag     3
 #define google_census_View_aggregation_tag       4
 #define google_census_View_tag_key_tag           5
-#define google_census_ViewAggregations_aggregation_tag 1
-#define google_census_ViewAggregations_start_tag 2
-#define google_census_ViewAggregations_end_tag   3
-#define google_census_Aggregation_distribution_tag 3
+#define google_census_Aggregation_count_tag      3
 
-#define google_census_Aggregation_interval_stats_tag 4
+#define google_census_Aggregation_distribution_tag 4
+
+#define google_census_Aggregation_interval_stats_tag 5
 #define google_census_Aggregation_name_tag       1
 #define google_census_Aggregation_description_tag 2
-#define google_census_Aggregation_tag_tag        5
+#define google_census_Aggregation_tag_tag        6
 
 /* Struct field encoding specification for nanopb */
 extern const pb_field_t google_census_Duration_fields[3];
 extern const pb_field_t google_census_Timestamp_fields[3];
-extern const pb_field_t google_census_Metric_fields[5];
-extern const pb_field_t google_census_Metric_BasicUnit_fields[2];
-extern const pb_field_t google_census_Metric_MeasurementUnit_fields[4];
-extern const pb_field_t google_census_AggregationDescriptor_fields[3];
+extern const pb_field_t google_census_Resource_fields[4];
+extern const pb_field_t google_census_Resource_MeasurementUnit_fields[4];
+extern const pb_field_t google_census_AggregationDescriptor_fields[4];
 extern const pb_field_t google_census_AggregationDescriptor_BucketBoundaries_fields[2];
 extern const pb_field_t google_census_AggregationDescriptor_IntervalBoundaries_fields[2];
 extern const pb_field_t google_census_Distribution_fields[5];
@@ -268,13 +270,12 @@
 extern const pb_field_t google_census_IntervalStats_Window_fields[4];
 extern const pb_field_t google_census_Tag_fields[3];
 extern const pb_field_t google_census_View_fields[6];
-extern const pb_field_t google_census_Aggregation_fields[6];
-extern const pb_field_t google_census_ViewAggregations_fields[4];
+extern const pb_field_t google_census_Aggregation_fields[7];
+extern const pb_field_t google_census_Metric_fields[5];
 
 /* Maximum encoded size of messages (where known) */
 #define google_census_Duration_size              22
 #define google_census_Timestamp_size             22
-#define google_census_Metric_BasicUnit_size      2
 #define google_census_Distribution_Range_size    18
 #define google_census_IntervalStats_Window_size  44
 #define google_census_Tag_size                   516
diff --git a/src/core/ext/census/grpc_filter.c b/src/core/ext/census/grpc_filter.c
index 3004a1f..9dacc17 100644
--- a/src/core/ext/census/grpc_filter.c
+++ b/src/core/ext/census/grpc_filter.c
@@ -127,13 +127,14 @@
   grpc_call_next_op(exec_ctx, elem, op);
 }
 
-static void client_init_call_elem(grpc_exec_ctx *exec_ctx,
-                                  grpc_call_element *elem,
-                                  grpc_call_element_args *args) {
+static grpc_error *client_init_call_elem(grpc_exec_ctx *exec_ctx,
+                                         grpc_call_element *elem,
+                                         grpc_call_element_args *args) {
   call_data *d = elem->call_data;
   GPR_ASSERT(d != NULL);
   memset(d, 0, sizeof(*d));
   d->start_ts = gpr_now(GPR_CLOCK_REALTIME);
+  return GRPC_ERROR_NONE;
 }
 
 static void client_destroy_call_elem(grpc_exec_ctx *exec_ctx,
@@ -145,15 +146,16 @@
   /* TODO(hongyu): record rpc client stats and census_rpc_end_op here */
 }
 
-static void server_init_call_elem(grpc_exec_ctx *exec_ctx,
-                                  grpc_call_element *elem,
-                                  grpc_call_element_args *args) {
+static grpc_error *server_init_call_elem(grpc_exec_ctx *exec_ctx,
+                                         grpc_call_element *elem,
+                                         grpc_call_element_args *args) {
   call_data *d = elem->call_data;
   GPR_ASSERT(d != NULL);
   memset(d, 0, sizeof(*d));
   d->start_ts = gpr_now(GPR_CLOCK_REALTIME);
   /* TODO(hongyu): call census_tracing_start_op here. */
   grpc_closure_init(&d->finish_recv, server_on_done_recv, elem);
+  return GRPC_ERROR_NONE;
 }
 
 static void server_destroy_call_elem(grpc_exec_ctx *exec_ctx,
diff --git a/src/core/ext/census/initialize.c b/src/core/ext/census/initialize.c
index 896276e..55cbbe8 100644
--- a/src/core/ext/census/initialize.c
+++ b/src/core/ext/census/initialize.c
@@ -32,19 +32,31 @@
  */
 
 #include <grpc/census.h>
+#include "src/core/ext/census/base_resources.h"
+#include "src/core/ext/census/resource.h"
 
 static int features_enabled = CENSUS_FEATURE_NONE;
 
 int census_initialize(int features) {
   if (features_enabled != CENSUS_FEATURE_NONE) {
     // Must have been a previous call to census_initialize; return error
-    return 1;
+    return -1;
   }
-  features_enabled = features;
-  return 0;
+  features_enabled = features & CENSUS_FEATURE_ALL;
+  if (features & CENSUS_FEATURE_STATS) {
+    initialize_resources();
+    define_base_resources();
+  }
+
+  return features_enabled;
 }
 
-void census_shutdown(void) { features_enabled = CENSUS_FEATURE_NONE; }
+void census_shutdown(void) {
+  if (features_enabled & CENSUS_FEATURE_STATS) {
+    shutdown_resources();
+  }
+  features_enabled = CENSUS_FEATURE_NONE;
+}
 
 int census_supported(void) {
   /* TODO(aveitch): improve this as we implement features... */
diff --git a/src/core/ext/census/placeholders.c b/src/core/ext/census/placeholders.c
index fe23d13..9f99c5b 100644
--- a/src/core/ext/census/placeholders.c
+++ b/src/core/ext/census/placeholders.c
@@ -62,48 +62,3 @@
   (void)consume;
   abort();
 }
-
-const census_aggregation *census_view_aggregrations(const census_view *view) {
-  (void)view;
-  abort();
-}
-
-census_view *census_view_create(uint32_t metric_id, const census_context *tags,
-                                const census_aggregation *aggregations,
-                                size_t naggregations) {
-  (void)metric_id;
-  (void)tags;
-  (void)aggregations;
-  (void)naggregations;
-  abort();
-}
-
-const census_context *census_view_tags(const census_view *view) {
-  (void)view;
-  abort();
-}
-
-void census_view_delete(census_view *view) {
-  (void)view;
-  abort();
-}
-
-const census_view_data *census_view_get_data(const census_view *view) {
-  (void)view;
-  abort();
-}
-
-size_t census_view_metric(const census_view *view) {
-  (void)view;
-  abort();
-}
-
-size_t census_view_naggregations(const census_view *view) {
-  (void)view;
-  abort();
-}
-
-void census_view_reset(census_view *view) {
-  (void)view;
-  abort();
-}
diff --git a/src/core/ext/census/resource.c b/src/core/ext/census/resource.c
new file mode 100644
index 0000000..ed44f00
--- /dev/null
+++ b/src/core/ext/census/resource.c
@@ -0,0 +1,312 @@
+/*
+ *
+ * Copyright 2016, 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 "src/core/ext/census/resource.h"
+#include "third_party/nanopb/pb_decode.h"
+
+#include <grpc/census.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/sync.h>
+
+#include <stdbool.h>
+#include <string.h>
+
+// Protect local resource data structures.
+static gpr_mu resource_lock;
+
+// Deleteing and creating resources are relatively rare events, and should not
+// be done in the critical path of performance sensitive code. We record
+// current resource id's used in a simple array, and just search it each time
+// we need to assign a new id, or look up a resource.
+static resource **resources = NULL;
+
+// Number of entries in *resources
+static size_t n_resources = 0;
+
+// Number of defined resources
+static size_t n_defined_resources = 0;
+
+void initialize_resources(void) {
+  gpr_mu_init(&resource_lock);
+  gpr_mu_lock(&resource_lock);
+  GPR_ASSERT(resources == NULL && n_resources == 0 && n_defined_resources == 0);
+  gpr_mu_unlock(&resource_lock);
+}
+
+// Delete a resource given it's ID. The ID must be a valid resource ID. Must be
+// called with resource_lock held.
+static void delete_resource_locked(size_t rid) {
+  GPR_ASSERT(resources[rid] != NULL);
+  gpr_free(resources[rid]->name);
+  gpr_free(resources[rid]->description);
+  gpr_free(resources[rid]->numerators);
+  gpr_free(resources[rid]->denominators);
+  gpr_free(resources[rid]);
+  resources[rid] = NULL;
+  n_defined_resources--;
+}
+
+void shutdown_resources(void) {
+  gpr_mu_lock(&resource_lock);
+  for (size_t i = 0; i < n_resources; i++) {
+    if (resources[i] != NULL) {
+      delete_resource_locked(i);
+    }
+  }
+  GPR_ASSERT(n_defined_resources == 0);
+  gpr_free(resources);
+  resources = NULL;
+  n_resources = 0;
+  gpr_mu_unlock(&resource_lock);
+}
+
+// Check the contents of string fields in a resource proto.
+static bool validate_string(pb_istream_t *stream, const pb_field_t *field,
+                            void **arg) {
+  resource *vresource = (resource *)*arg;
+  switch (field->tag) {
+    case google_census_Resource_name_tag:
+      // Name must have at least one character
+      if (stream->bytes_left == 0) {
+        gpr_log(GPR_INFO, "Zero-length Resource name.");
+        return false;
+      }
+      vresource->name = gpr_malloc(stream->bytes_left + 1);
+      vresource->name[stream->bytes_left] = '\0';
+      if (!pb_read(stream, (uint8_t *)vresource->name, stream->bytes_left)) {
+        return false;
+      }
+      // Can't have same name as an existing resource.
+      for (size_t i = 0; i < n_resources; i++) {
+        resource *compare = resources[i];
+        if (compare == vresource || compare == NULL) continue;
+        if (strcmp(compare->name, vresource->name) == 0) {
+          gpr_log(GPR_INFO, "Duplicate Resource name %s.", vresource->name);
+          return false;
+        }
+      }
+      break;
+    case google_census_Resource_description_tag:
+      if (stream->bytes_left == 0) {
+        return true;
+      }
+      vresource->description = gpr_malloc(stream->bytes_left + 1);
+      vresource->description[stream->bytes_left] = '\0';
+      if (!pb_read(stream, (uint8_t *)vresource->description,
+                   stream->bytes_left)) {
+        return false;
+      }
+      break;
+    default:
+      // No other string fields in Resource. Print warning and skip.
+      gpr_log(GPR_INFO, "Unknown string field type in Resource protobuf.");
+      if (!pb_read(stream, NULL, stream->bytes_left)) {
+        return false;
+      }
+      break;
+  }
+  return true;
+}
+
+// Decode numerators/denominators in a stream. The `count` and `bup`
+// (BasicUnit pointer) are pointers to the approriate fields in a resource
+// struct.
+static bool validate_units_helper(pb_istream_t *stream, int *count,
+                                  google_census_Resource_BasicUnit **bup) {
+  while (stream->bytes_left) {
+    (*count)++;
+    // Have to allocate a new array of values. Normal case is 0 or 1, so
+    // this should normally not be an issue.
+    google_census_Resource_BasicUnit *new_bup =
+        gpr_malloc((size_t)*count * sizeof(google_census_Resource_BasicUnit));
+    if (*count != 1) {
+      memcpy(new_bup, *bup,
+             (size_t)(*count - 1) * sizeof(google_census_Resource_BasicUnit));
+      gpr_free(*bup);
+    }
+    *bup = new_bup;
+    uint64_t value;
+    if (!pb_decode_varint(stream, &value)) {
+      return false;
+    }
+    *(*bup + *count - 1) = (google_census_Resource_BasicUnit)value;
+  }
+  return true;
+}
+
+// Validate units field of a Resource proto.
+static bool validate_units(pb_istream_t *stream, const pb_field_t *field,
+                           void **arg) {
+  resource *vresource = (resource *)(*arg);
+  switch (field->tag) {
+    case google_census_Resource_MeasurementUnit_numerator_tag:
+      return validate_units_helper(stream, &vresource->n_numerators,
+                                   &vresource->numerators);
+      break;
+    case google_census_Resource_MeasurementUnit_denominator_tag:
+      return validate_units_helper(stream, &vresource->n_denominators,
+                                   &vresource->denominators);
+      break;
+    default:
+      gpr_log(GPR_ERROR, "Unknown field type.");
+      return false;
+      break;
+  }
+  return true;
+}
+
+// Validate the contents of a Resource proto. `id` is the intended resource id.
+static bool validate_resource_pb(const uint8_t *resource_pb,
+                                 size_t resource_pb_size, size_t id) {
+  GPR_ASSERT(id < n_resources);
+  if (resource_pb == NULL) {
+    return false;
+  }
+  google_census_Resource vresource;
+  vresource.name.funcs.decode = &validate_string;
+  vresource.name.arg = resources[id];
+  vresource.description.funcs.decode = &validate_string;
+  vresource.description.arg = resources[id];
+  vresource.unit.numerator.funcs.decode = &validate_units;
+  vresource.unit.numerator.arg = resources[id];
+  vresource.unit.denominator.funcs.decode = &validate_units;
+  vresource.unit.denominator.arg = resources[id];
+
+  pb_istream_t stream =
+      pb_istream_from_buffer((uint8_t *)resource_pb, resource_pb_size);
+  if (!pb_decode(&stream, google_census_Resource_fields, &vresource)) {
+    return false;
+  }
+  // A Resource must have a name, a unit, with at least one numerator.
+  return (resources[id]->name != NULL && vresource.has_unit &&
+          resources[id]->n_numerators > 0);
+}
+
+// Allocate a blank resource, and return associated ID. Must be called with
+// resource_lock held.
+size_t allocate_resource(void) {
+  // use next_id to optimize expected placement of next new resource.
+  static size_t next_id = 0;
+  size_t id = n_resources;  // resource ID - initialize to invalid value.
+  // Expand resources if needed.
+  if (n_resources == n_defined_resources) {
+    size_t new_n_resources = n_resources ? n_resources * 2 : 2;
+    resource **new_resources = gpr_malloc(new_n_resources * sizeof(resource *));
+    memcpy(new_resources, resources, n_resources * sizeof(resource *));
+    memset(new_resources + n_resources, 0,
+           (new_n_resources - n_resources) * sizeof(resource *));
+    gpr_free(resources);
+    resources = new_resources;
+    n_resources = new_n_resources;
+    id = n_defined_resources;
+  } else {
+    GPR_ASSERT(n_defined_resources < n_resources);
+    // Find a free id.
+    for (size_t base = 0; base < n_resources; base++) {
+      id = (next_id + base) % n_resources;
+      if (resources[id] == NULL) break;
+    }
+  }
+  GPR_ASSERT(id < n_resources && resources[id] == NULL);
+  resources[id] = gpr_malloc(sizeof(resource));
+  memset(resources[id], 0, sizeof(resource));
+  n_defined_resources++;
+  next_id = (id + 1) % n_resources;
+  return id;
+}
+
+int32_t census_define_resource(const uint8_t *resource_pb,
+                               size_t resource_pb_size) {
+  if (resource_pb == NULL) {
+    return -1;
+  }
+  gpr_mu_lock(&resource_lock);
+  size_t id = allocate_resource();
+  // Validate pb, extract name.
+  if (!validate_resource_pb(resource_pb, resource_pb_size, id)) {
+    delete_resource_locked(id);
+    gpr_mu_unlock(&resource_lock);
+    return -1;
+  }
+  gpr_mu_unlock(&resource_lock);
+  return (int32_t)id;
+}
+
+void census_delete_resource(int32_t rid) {
+  gpr_mu_lock(&resource_lock);
+  if (rid >= 0 && (size_t)rid < n_resources && resources[rid] != NULL) {
+    delete_resource_locked((size_t)rid);
+  }
+  gpr_mu_unlock(&resource_lock);
+}
+
+int32_t census_resource_id(const char *name) {
+  gpr_mu_lock(&resource_lock);
+  for (int32_t id = 0; (size_t)id < n_resources; id++) {
+    if (resources[id] != NULL && strcmp(resources[id]->name, name) == 0) {
+      gpr_mu_unlock(&resource_lock);
+      return id;
+    }
+  }
+  gpr_mu_unlock(&resource_lock);
+  return -1;
+}
+
+int32_t define_resource(const resource *base) {
+  GPR_ASSERT(base != NULL && base->name != NULL && base->n_numerators > 0 &&
+             base->numerators != NULL);
+  gpr_mu_lock(&resource_lock);
+  size_t id = allocate_resource();
+  size_t len = strlen(base->name) + 1;
+  resources[id]->name = gpr_malloc(len);
+  memcpy(resources[id]->name, base->name, len);
+  if (base->description) {
+    len = strlen(base->description) + 1;
+    resources[id]->description = gpr_malloc(len);
+    memcpy(resources[id]->description, base->description, len);
+  }
+  resources[id]->prefix = base->prefix;
+  resources[id]->n_numerators = base->n_numerators;
+  len = (size_t)base->n_numerators * sizeof(*base->numerators);
+  resources[id]->numerators = gpr_malloc(len);
+  memcpy(resources[id]->numerators, base->numerators, len);
+  resources[id]->n_denominators = base->n_denominators;
+  if (base->n_denominators != 0) {
+    len = (size_t)base->n_denominators * sizeof(*base->denominators);
+    resources[id]->denominators = gpr_malloc(len);
+    memcpy(resources[id]->denominators, base->denominators, len);
+  }
+  gpr_mu_unlock(&resource_lock);
+  return (int32_t)id;
+}
diff --git a/src/core/ext/census/resource.h b/src/core/ext/census/resource.h
new file mode 100644
index 0000000..591bff0
--- /dev/null
+++ b/src/core/ext/census/resource.h
@@ -0,0 +1,63 @@
+/*
+ *
+ * Copyright 2016, 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.
+ *
+ */
+
+/* Census-internal resource definition and manipluation functions. */
+#ifndef GRPC_CORE_EXT_CENSUS_RESOURCE_H
+#define GRPC_CORE_EXT_CENSUS_RESOURCE_H
+
+#include <grpc/grpc.h>
+#include "src/core/ext/census/gen/census.pb.h"
+
+/* Internal representation of a resource. */
+typedef struct {
+  char *name;
+  char *description;
+  int32_t prefix;
+  int n_numerators;
+  google_census_Resource_BasicUnit *numerators;
+  int n_denominators;
+  google_census_Resource_BasicUnit *denominators;
+} resource;
+
+/* Initialize and shutdown the resources subsystem. */
+void initialize_resources(void);
+void shutdown_resources(void);
+
+/* Add a new resource, given a proposed resource structure. Returns the
+   resource ID, or -ve on failure.
+   TODO(aveitch): this function exists to support addition of the base
+   resources. It should be removed when we have the ability to add resources
+   from configuration files. */
+int32_t define_resource(const resource *base);
+
+#endif /* GRPC_CORE_EXT_CENSUS_RESOURCE_H */
diff --git a/src/core/ext/client_config/client_channel.c b/src/core/ext/client_config/client_channel.c
index 739487a..2c0c4ab 100644
--- a/src/core/ext/client_config/client_channel.c
+++ b/src/core/ext/client_config/client_channel.c
@@ -436,10 +436,12 @@
 }
 
 /* Constructor for call_data */
-static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
-                           grpc_call_element_args *args) {
+static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
+                                  grpc_call_element *elem,
+                                  grpc_call_element_args *args) {
   grpc_subchannel_call_holder_init(elem->call_data, cc_pick_subchannel, elem,
                                    args->call_stack);
+  return GRPC_ERROR_NONE;
 }
 
 /* Destructor for call_data */
diff --git a/src/core/ext/client_config/subchannel.c b/src/core/ext/client_config/subchannel.c
index d089cd4..df35904 100644
--- a/src/core/ext/client_config/subchannel.c
+++ b/src/core/ext/client_config/subchannel.c
@@ -702,19 +702,26 @@
   return GET_CONNECTED_SUBCHANNEL(c, acq);
 }
 
-grpc_subchannel_call *grpc_connected_subchannel_create_call(
+grpc_error *grpc_connected_subchannel_create_call(
     grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *con,
-    grpc_polling_entity *pollent) {
+    grpc_polling_entity *pollent, grpc_subchannel_call **call) {
   grpc_channel_stack *chanstk = CHANNEL_STACK_FROM_CONNECTION(con);
-  grpc_subchannel_call *call =
-      gpr_malloc(sizeof(grpc_subchannel_call) + chanstk->call_stack_size);
-  grpc_call_stack *callstk = SUBCHANNEL_CALL_TO_CALL_STACK(call);
-  call->connection = con;
+  *call = gpr_malloc(sizeof(grpc_subchannel_call) + chanstk->call_stack_size);
+  grpc_call_stack *callstk = SUBCHANNEL_CALL_TO_CALL_STACK(*call);
+  (*call)->connection = con;  // Ref is added below.
+  grpc_error *error =
+      grpc_call_stack_init(exec_ctx, chanstk, 1, subchannel_call_destroy, *call,
+                           NULL, NULL, callstk);
+  if (error != GRPC_ERROR_NONE) {
+    const char *error_string = grpc_error_string(error);
+    gpr_log(GPR_ERROR, "error: %s", error_string);
+    grpc_error_free_string(error_string);
+    gpr_free(*call);
+    return error;
+  }
   GRPC_CONNECTED_SUBCHANNEL_REF(con, "subchannel_call");
-  grpc_call_stack_init(exec_ctx, chanstk, 1, subchannel_call_destroy, call,
-                       NULL, NULL, callstk);
   grpc_call_stack_set_pollset_or_pollset_set(exec_ctx, callstk, pollent);
-  return call;
+  return GRPC_ERROR_NONE;
 }
 
 grpc_call_stack *grpc_subchannel_call_get_call_stack(
diff --git a/src/core/ext/client_config/subchannel.h b/src/core/ext/client_config/subchannel.h
index 9fbf3b6..40d90be 100644
--- a/src/core/ext/client_config/subchannel.h
+++ b/src/core/ext/client_config/subchannel.h
@@ -108,9 +108,9 @@
                                     GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
 
 /** construct a subchannel call */
-grpc_subchannel_call *grpc_connected_subchannel_create_call(
+grpc_error *grpc_connected_subchannel_create_call(
     grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *connected_subchannel,
-    grpc_polling_entity *pollent);
+    grpc_polling_entity *pollent, grpc_subchannel_call **subchannel_call);
 
 /** process a transport level op */
 void grpc_connected_subchannel_process_transport_op(
diff --git a/src/core/ext/client_config/subchannel_call_holder.c b/src/core/ext/client_config/subchannel_call_holder.c
index b96a0ad..be6d054 100644
--- a/src/core/ext/client_config/subchannel_call_holder.c
+++ b/src/core/ext/client_config/subchannel_call_holder.c
@@ -84,6 +84,11 @@
   gpr_free(holder->waiting_ops);
 }
 
+// The logic here is fairly complicated, due to (a) the fact that we
+// need to handle the case where we receive the send op before the
+// initial metadata op, and (b) the need for efficiency, especially in
+// the streaming case.
+// TODO(ctiller): Explain this more thoroughly.
 void grpc_subchannel_call_holder_perform_op(grpc_exec_ctx *exec_ctx,
                                             grpc_subchannel_call_holder *holder,
                                             grpc_transport_stream_op *op) {
@@ -121,7 +126,8 @@
   }
   /* if this is a cancellation, then we can raise our cancelled flag */
   if (op->cancel_error != GRPC_ERROR_NONE) {
-    if (!gpr_atm_rel_cas(&holder->subchannel_call, 0, 1)) {
+    if (!gpr_atm_rel_cas(&holder->subchannel_call, 0,
+                         (gpr_atm)(uintptr_t)CANCELLED_CALL)) {
       goto retry;
     } else {
       switch (holder->creation_phase) {
@@ -158,10 +164,17 @@
   /* if we've got a subchannel, then let's ask it to create a call */
   if (holder->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING &&
       holder->connected_subchannel != NULL) {
-    gpr_atm_rel_store(
-        &holder->subchannel_call,
-        (gpr_atm)(uintptr_t)grpc_connected_subchannel_create_call(
-            exec_ctx, holder->connected_subchannel, holder->pollent));
+    grpc_subchannel_call *subchannel_call = NULL;
+    grpc_error *error = grpc_connected_subchannel_create_call(
+        exec_ctx, holder->connected_subchannel, holder->pollent,
+        &subchannel_call);
+    if (error != GRPC_ERROR_NONE) {
+      subchannel_call = CANCELLED_CALL;
+      fail_locked(exec_ctx, holder, GRPC_ERROR_REF(error));
+      grpc_transport_stream_op_finish_with_failure(exec_ctx, op, error);
+    }
+    gpr_atm_rel_store(&holder->subchannel_call,
+                      (gpr_atm)(uintptr_t)subchannel_call);
     retry_waiting_locked(exec_ctx, holder);
     goto retry;
   }
@@ -189,10 +202,17 @@
                 GRPC_ERROR_CREATE_REFERENCING(
                     "Cancelled before creating subchannel", &error, 1));
   } else {
-    gpr_atm_rel_store(
-        &holder->subchannel_call,
-        (gpr_atm)(uintptr_t)grpc_connected_subchannel_create_call(
-            exec_ctx, holder->connected_subchannel, holder->pollent));
+    grpc_subchannel_call *subchannel_call = NULL;
+    grpc_error *new_error = grpc_connected_subchannel_create_call(
+        exec_ctx, holder->connected_subchannel, holder->pollent,
+        &subchannel_call);
+    if (new_error != GRPC_ERROR_NONE) {
+      new_error = grpc_error_add_child(new_error, error);
+      subchannel_call = CANCELLED_CALL;
+      fail_locked(exec_ctx, holder, new_error);
+    }
+    gpr_atm_rel_store(&holder->subchannel_call,
+                      (gpr_atm)(uintptr_t)subchannel_call);
     retry_waiting_locked(exec_ctx, holder);
   }
   gpr_mu_unlock(&holder->mu);
diff --git a/src/core/ext/load_reporting/load_reporting_filter.c b/src/core/ext/load_reporting/load_reporting_filter.c
index 99b560a..394f0cb 100644
--- a/src/core/ext/load_reporting/load_reporting_filter.c
+++ b/src/core/ext/load_reporting/load_reporting_filter.c
@@ -107,8 +107,9 @@
 }
 
 /* Constructor for call_data */
-static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
-                           grpc_call_element_args *args) {
+static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
+                                  grpc_call_element *elem,
+                                  grpc_call_element_args *args) {
   call_data *calld = elem->call_data;
   memset(calld, 0, sizeof(call_data));
 
@@ -125,6 +126,8 @@
                                                 NULL,
                                                 NULL};
   */
+
+  return GRPC_ERROR_NONE;
 }
 
 /* Destructor for call_data */
diff --git a/src/core/lib/channel/channel_stack.c b/src/core/lib/channel/channel_stack.c
index f9b7347..98f304f 100644
--- a/src/core/lib/channel/channel_stack.c
+++ b/src/core/lib/channel/channel_stack.c
@@ -157,12 +157,13 @@
   }
 }
 
-void grpc_call_stack_init(grpc_exec_ctx *exec_ctx,
-                          grpc_channel_stack *channel_stack, int initial_refs,
-                          grpc_iomgr_cb_func destroy, void *destroy_arg,
-                          grpc_call_context_element *context,
-                          const void *transport_server_data,
-                          grpc_call_stack *call_stack) {
+grpc_error *grpc_call_stack_init(grpc_exec_ctx *exec_ctx,
+                                 grpc_channel_stack *channel_stack,
+                                 int initial_refs, grpc_iomgr_cb_func destroy,
+                                 void *destroy_arg,
+                                 grpc_call_context_element *context,
+                                 const void *transport_server_data,
+                                 grpc_call_stack *call_stack) {
   grpc_channel_element *channel_elems = CHANNEL_ELEMS_FROM_STACK(channel_stack);
   grpc_call_element_args args;
   size_t count = channel_stack->count;
@@ -178,6 +179,7 @@
               ROUND_UP_TO_ALIGNMENT_SIZE(count * sizeof(grpc_call_element));
 
   /* init per-filter data */
+  grpc_error *first_error = GRPC_ERROR_NONE;
   for (i = 0; i < count; i++) {
     args.call_stack = call_stack;
     args.server_transport_data = transport_server_data;
@@ -185,10 +187,19 @@
     call_elems[i].filter = channel_elems[i].filter;
     call_elems[i].channel_data = channel_elems[i].channel_data;
     call_elems[i].call_data = user_data;
-    call_elems[i].filter->init_call_elem(exec_ctx, &call_elems[i], &args);
+    grpc_error *error =
+        call_elems[i].filter->init_call_elem(exec_ctx, &call_elems[i], &args);
+    if (error != GRPC_ERROR_NONE) {
+      if (first_error == GRPC_ERROR_NONE) {
+        first_error = error;
+      } else {
+        GRPC_ERROR_UNREF(error);
+      }
+    }
     user_data +=
         ROUND_UP_TO_ALIGNMENT_SIZE(call_elems[i].filter->sizeof_call_data);
   }
+  return first_error;
 }
 
 void grpc_call_stack_set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx,
diff --git a/src/core/lib/channel/channel_stack.h b/src/core/lib/channel/channel_stack.h
index 19d18cc..ee68701 100644
--- a/src/core/lib/channel/channel_stack.h
+++ b/src/core/lib/channel/channel_stack.h
@@ -115,8 +115,9 @@
      on a client; if it is non-NULL, then it points to memory owned by the
      transport and is on the server. Most filters want to ignore this
      argument. */
-  void (*init_call_elem)(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
-                         grpc_call_element_args *args);
+  grpc_error *(*init_call_elem)(grpc_exec_ctx *exec_ctx,
+                                grpc_call_element *elem,
+                                grpc_call_element_args *args);
   void (*set_pollset_or_pollset_set)(grpc_exec_ctx *exec_ctx,
                                      grpc_call_element *elem,
                                      grpc_polling_entity *pollent);
@@ -215,12 +216,13 @@
 /* Initialize a call stack given a channel stack. transport_server_data is
    expected to be NULL on a client, or an opaque transport owned pointer on the
    server. */
-void grpc_call_stack_init(grpc_exec_ctx *exec_ctx,
-                          grpc_channel_stack *channel_stack, int initial_refs,
-                          grpc_iomgr_cb_func destroy, void *destroy_arg,
-                          grpc_call_context_element *context,
-                          const void *transport_server_data,
-                          grpc_call_stack *call_stack);
+grpc_error *grpc_call_stack_init(grpc_exec_ctx *exec_ctx,
+                                 grpc_channel_stack *channel_stack,
+                                 int initial_refs, grpc_iomgr_cb_func destroy,
+                                 void *destroy_arg,
+                                 grpc_call_context_element *context,
+                                 const void *transport_server_data,
+                                 grpc_call_stack *call_stack);
 /* Set a pollset or a pollset_set for a call stack: must occur before the first
  * op is started */
 void grpc_call_stack_set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx,
diff --git a/src/core/lib/channel/compress_filter.c b/src/core/lib/channel/compress_filter.c
index af21ed7..134180e 100644
--- a/src/core/lib/channel/compress_filter.c
+++ b/src/core/lib/channel/compress_filter.c
@@ -256,8 +256,9 @@
 }
 
 /* Constructor for call_data */
-static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
-                           grpc_call_element_args *args) {
+static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
+                                  grpc_call_element *elem,
+                                  grpc_call_element_args *args) {
   /* grab pointers to our data from the call element */
   call_data *calld = elem->call_data;
 
@@ -266,6 +267,8 @@
   calld->has_compression_algorithm = 0;
   grpc_closure_init(&calld->got_slice, got_slice, elem);
   grpc_closure_init(&calld->send_done, send_done, elem);
+
+  return GRPC_ERROR_NONE;
 }
 
 /* Destructor for call_data */
diff --git a/src/core/lib/channel/connected_channel.c b/src/core/lib/channel/connected_channel.c
index 7371436..918379c 100644
--- a/src/core/lib/channel/connected_channel.c
+++ b/src/core/lib/channel/connected_channel.c
@@ -81,16 +81,16 @@
 }
 
 /* Constructor for call_data */
-static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
-                           grpc_call_element_args *args) {
+static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
+                                  grpc_call_element *elem,
+                                  grpc_call_element_args *args) {
   call_data *calld = elem->call_data;
   channel_data *chand = elem->channel_data;
-  int r;
-
-  r = grpc_transport_init_stream(
+  int r = grpc_transport_init_stream(
       exec_ctx, chand->transport, TRANSPORT_STREAM_FROM_CALL_DATA(calld),
       &args->call_stack->refcount, args->server_transport_data);
-  GPR_ASSERT(r == 0);
+  return r == 0 ? GRPC_ERROR_NONE
+                : GRPC_ERROR_CREATE("transport stream initialization failed");
 }
 
 static void set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx,
diff --git a/src/core/lib/channel/http_client_filter.c b/src/core/lib/channel/http_client_filter.c
index f1ed22c..a7a775c 100644
--- a/src/core/lib/channel/http_client_filter.c
+++ b/src/core/lib/channel/http_client_filter.c
@@ -175,11 +175,13 @@
 }
 
 /* Constructor for call_data */
-static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
-                           grpc_call_element_args *args) {
+static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
+                                  grpc_call_element *elem,
+                                  grpc_call_element_args *args) {
   call_data *calld = elem->call_data;
   calld->on_done_recv = NULL;
   grpc_closure_init(&calld->hc_on_recv, hc_on_recv, elem);
+  return GRPC_ERROR_NONE;
 }
 
 /* Destructor for call_data */
diff --git a/src/core/lib/channel/http_server_filter.c b/src/core/lib/channel/http_server_filter.c
index d52cc7d..5ce51f9 100644
--- a/src/core/lib/channel/http_server_filter.c
+++ b/src/core/lib/channel/http_server_filter.c
@@ -224,13 +224,15 @@
 }
 
 /* Constructor for call_data */
-static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
-                           grpc_call_element_args *args) {
+static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
+                                  grpc_call_element *elem,
+                                  grpc_call_element_args *args) {
   /* grab pointers to our data from the call element */
   call_data *calld = elem->call_data;
   /* initialize members */
   memset(calld, 0, sizeof(*calld));
   grpc_closure_init(&calld->hs_on_recv, hs_on_recv, elem);
+  return GRPC_ERROR_NONE;
 }
 
 /* Destructor for call_data */
diff --git a/src/core/lib/iomgr/error.h b/src/core/lib/iomgr/error.h
index 13f898e..bc77812 100644
--- a/src/core/lib/iomgr/error.h
+++ b/src/core/lib/iomgr/error.h
@@ -171,6 +171,8 @@
                                 gpr_timespec value) GRPC_MUST_USE_RESULT;
 grpc_error *grpc_error_set_str(grpc_error *src, grpc_error_strs which,
                                const char *value) GRPC_MUST_USE_RESULT;
+/// Returns NULL if the specified string is not set.
+/// Caller does NOT own return value.
 const char *grpc_error_get_str(grpc_error *error, grpc_error_strs which);
 /// Add a child error: an error that is believed to have contributed to this
 /// error occurring. Allows root causing high level errors from lower level
diff --git a/src/core/lib/security/transport/client_auth_filter.c b/src/core/lib/security/transport/client_auth_filter.c
index 382d307..2a1bf4d 100644
--- a/src/core/lib/security/transport/client_auth_filter.c
+++ b/src/core/lib/security/transport/client_auth_filter.c
@@ -267,10 +267,12 @@
 }
 
 /* Constructor for call_data */
-static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
-                           grpc_call_element_args *args) {
+static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
+                                  grpc_call_element *elem,
+                                  grpc_call_element_args *args) {
   call_data *calld = elem->call_data;
   memset(calld, 0, sizeof(*calld));
+  return GRPC_ERROR_NONE;
 }
 
 static void set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx,
diff --git a/src/core/lib/security/transport/secure_endpoint.c b/src/core/lib/security/transport/secure_endpoint.c
index bc50f9d..0169ccd 100644
--- a/src/core/lib/security/transport/secure_endpoint.c
+++ b/src/core/lib/security/transport/secure_endpoint.c
@@ -128,7 +128,7 @@
 
 static void call_read_cb(grpc_exec_ctx *exec_ctx, secure_endpoint *ep,
                          grpc_error *error) {
-  if (false && grpc_trace_secure_endpoint) {
+  if (grpc_trace_secure_endpoint) {
     size_t i;
     for (i = 0; i < ep->read_buffer->count; i++) {
       char *data = gpr_dump_slice(ep->read_buffer->slices[i],
@@ -256,7 +256,7 @@
 
   gpr_slice_buffer_reset_and_unref(&ep->output_buffer);
 
-  if (false && grpc_trace_secure_endpoint) {
+  if (grpc_trace_secure_endpoint) {
     for (i = 0; i < slices->count; i++) {
       char *data =
           gpr_dump_slice(slices->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII);
diff --git a/src/core/lib/security/transport/server_auth_filter.c b/src/core/lib/security/transport/server_auth_filter.c
index 5f3d0dc..def16c8 100644
--- a/src/core/lib/security/transport/server_auth_filter.c
+++ b/src/core/lib/security/transport/server_auth_filter.c
@@ -199,8 +199,9 @@
 }
 
 /* Constructor for call_data */
-static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
-                           grpc_call_element_args *args) {
+static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
+                                  grpc_call_element *elem,
+                                  grpc_call_element_args *args) {
   /* grab pointers to our data from the call element */
   call_data *calld = elem->call_data;
   channel_data *chand = elem->channel_data;
@@ -222,6 +223,8 @@
   args->context[GRPC_CONTEXT_SECURITY].value = server_ctx;
   args->context[GRPC_CONTEXT_SECURITY].destroy =
       grpc_server_security_context_destroy;
+
+  return GRPC_ERROR_NONE;
 }
 
 /* Destructor for call_data */
diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c
index 70c9479..7726811 100644
--- a/src/core/lib/surface/call.c
+++ b/src/core/lib/surface/call.c
@@ -264,9 +264,19 @@
       gpr_convert_clock_type(send_deadline, GPR_CLOCK_MONOTONIC);
   GRPC_CHANNEL_INTERNAL_REF(channel, "call");
   /* initial refcount dropped by grpc_call_destroy */
-  grpc_call_stack_init(&exec_ctx, channel_stack, 1, destroy_call, call,
-                       call->context, server_transport_data,
-                       CALL_STACK_FROM_CALL(call));
+  grpc_error *error = grpc_call_stack_init(
+      &exec_ctx, channel_stack, 1, destroy_call, call, call->context,
+      server_transport_data, CALL_STACK_FROM_CALL(call));
+  if (error != GRPC_ERROR_NONE) {
+    intptr_t status;
+    if (!grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, &status))
+      status = GRPC_STATUS_UNKNOWN;
+    const char *error_str =
+        grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION);
+    close_with_status(&exec_ctx, call, (grpc_status_code)status,
+                      error_str == NULL ? "unknown error" : error_str);
+    GRPC_ERROR_UNREF(error);
+  }
   if (cq != NULL) {
     GPR_ASSERT(
         pollset_set_alternative == NULL &&
@@ -1367,6 +1377,9 @@
   int num_completion_callbacks_needed = 1;
   grpc_call_error error = GRPC_CALL_OK;
 
+  // sent_initial_metadata guards against variable reuse.
+  grpc_metadata compression_md;
+
   GPR_TIMER_BEGIN("grpc_call_start_batch", 0);
 
   GRPC_CALL_LOG_BATCH(GPR_INFO, call, ops, nops, notify_tag);
@@ -1412,8 +1425,7 @@
           goto done_with_error;
         }
         /* process compression level */
-        grpc_metadata compression_md;
-        memset(&compression_md, 0, sizeof(grpc_metadata));
+        memset(&compression_md, 0, sizeof(compression_md));
         size_t additional_metadata_count = 0;
         grpc_compression_level effective_compression_level;
         bool level_set = false;
diff --git a/src/core/lib/surface/lame_client.c b/src/core/lib/surface/lame_client.c
index 0d3168e..19b7836 100644
--- a/src/core/lib/surface/lame_client.c
+++ b/src/core/lib/surface/lame_client.c
@@ -107,8 +107,11 @@
   GRPC_ERROR_UNREF(op->disconnect_with_error);
 }
 
-static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
-                           grpc_call_element_args *args) {}
+static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
+                                  grpc_call_element *elem,
+                                  grpc_call_element_args *args) {
+  return GRPC_ERROR_NONE;
+}
 
 static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
                               const grpc_call_final_info *final_info,
diff --git a/src/core/lib/surface/server.c b/src/core/lib/surface/server.c
index a482ba4..1d61ec3 100644
--- a/src/core/lib/surface/server.c
+++ b/src/core/lib/surface/server.c
@@ -856,8 +856,9 @@
   }
 }
 
-static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
-                           grpc_call_element_args *args) {
+static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
+                                  grpc_call_element *elem,
+                                  grpc_call_element_args *args) {
   call_data *calld = elem->call_data;
   channel_data *chand = elem->channel_data;
   memset(calld, 0, sizeof(call_data));
@@ -869,6 +870,7 @@
                     server_on_recv_initial_metadata, elem);
 
   server_ref(chand->server);
+  return GRPC_ERROR_NONE;
 }
 
 static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
diff --git a/src/core/lib/transport/static_metadata.c b/src/core/lib/transport/static_metadata.c
index c396c1e..8f3e5b5 100644
--- a/src/core/lib/transport/static_metadata.c
+++ b/src/core/lib/transport/static_metadata.c
@@ -51,15 +51,15 @@
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 
 const uint8_t grpc_static_metadata_elem_indices[GRPC_STATIC_MDELEM_COUNT * 2] =
-    {11, 35, 10, 35, 12, 35, 12, 49, 13, 35, 14, 35, 15, 35, 16, 35, 17, 35,
-     19, 35, 20, 35, 21, 35, 24, 35, 25, 35, 26, 35, 27, 35, 28, 35, 29, 35,
-     30, 18, 30, 35, 31, 35, 32, 35, 36, 35, 37, 35, 38, 35, 39, 35, 42, 33,
-     42, 34, 42, 48, 42, 53, 42, 54, 42, 55, 42, 56, 43, 33, 43, 48, 43, 53,
-     46, 0,  46, 1,  46, 2,  50, 35, 57, 35, 58, 35, 59, 35, 60, 35, 61, 35,
-     62, 35, 63, 35, 64, 35, 65, 35, 66, 35, 67, 35, 68, 40, 68, 70, 68, 73,
-     69, 81, 69, 82, 71, 35, 72, 35, 74, 35, 75, 35, 76, 35, 77, 35, 78, 41,
-     78, 51, 78, 52, 79, 35, 80, 35, 83, 3,  83, 4,  83, 5,  83, 6,  83, 7,
-     83, 8,  83, 9,  84, 35, 85, 86, 87, 35, 88, 35, 89, 35, 90, 35, 91, 35};
+    {11, 33, 10, 33, 12, 33, 12, 49, 13, 33, 14, 33, 15, 33, 16, 33, 17, 33,
+     19, 33, 20, 33, 21, 33, 22, 33, 23, 33, 24, 33, 25, 33, 26, 33, 27, 33,
+     28, 18, 28, 33, 29, 33, 30, 33, 34, 33, 35, 33, 36, 33, 37, 33, 40, 31,
+     40, 32, 40, 48, 40, 53, 40, 54, 40, 55, 40, 56, 42, 31, 42, 48, 42, 53,
+     45, 0,  45, 1,  45, 2,  50, 33, 57, 33, 58, 33, 59, 33, 60, 33, 61, 33,
+     62, 33, 63, 33, 64, 33, 65, 33, 66, 33, 67, 33, 68, 38, 68, 70, 68, 73,
+     69, 81, 69, 82, 71, 33, 72, 33, 74, 33, 75, 33, 76, 33, 77, 33, 78, 39,
+     78, 51, 78, 52, 79, 33, 80, 33, 83, 3,  83, 4,  83, 5,  83, 6,  83, 7,
+     83, 8,  83, 9,  84, 33, 85, 86, 87, 33, 88, 33, 89, 33, 90, 33, 91, 33};
 
 const char *const grpc_static_metadata_strings[GRPC_STATIC_MDSTR_COUNT] = {
     "0",
@@ -84,8 +84,6 @@
     ":authority",
     "authorization",
     "cache-control",
-    "census-bin",
-    "census-binary-bin",
     "content-disposition",
     "content-encoding",
     "content-language",
@@ -105,11 +103,13 @@
     "GET",
     "grpc",
     "grpc-accept-encoding",
+    "grpc-census-bin",
     "grpc-encoding",
     "grpc-internal-encoding-request",
     "grpc-message",
     "grpc-status",
     "grpc-timeout",
+    "grpc-tracing-bin",
     "gzip",
     "gzip, deflate",
     "host",
diff --git a/src/core/lib/transport/static_metadata.h b/src/core/lib/transport/static_metadata.h
index 491c8cf..b51baca 100644
--- a/src/core/lib/transport/static_metadata.h
+++ b/src/core/lib/transport/static_metadata.h
@@ -90,58 +90,58 @@
 #define GRPC_MDSTR_AUTHORIZATION (&grpc_static_mdstr_table[20])
 /* "cache-control" */
 #define GRPC_MDSTR_CACHE_CONTROL (&grpc_static_mdstr_table[21])
-/* "census-bin" */
-#define GRPC_MDSTR_CENSUS_BIN (&grpc_static_mdstr_table[22])
-/* "census-binary-bin" */
-#define GRPC_MDSTR_CENSUS_BINARY_BIN (&grpc_static_mdstr_table[23])
 /* "content-disposition" */
-#define GRPC_MDSTR_CONTENT_DISPOSITION (&grpc_static_mdstr_table[24])
+#define GRPC_MDSTR_CONTENT_DISPOSITION (&grpc_static_mdstr_table[22])
 /* "content-encoding" */
-#define GRPC_MDSTR_CONTENT_ENCODING (&grpc_static_mdstr_table[25])
+#define GRPC_MDSTR_CONTENT_ENCODING (&grpc_static_mdstr_table[23])
 /* "content-language" */
-#define GRPC_MDSTR_CONTENT_LANGUAGE (&grpc_static_mdstr_table[26])
+#define GRPC_MDSTR_CONTENT_LANGUAGE (&grpc_static_mdstr_table[24])
 /* "content-length" */
-#define GRPC_MDSTR_CONTENT_LENGTH (&grpc_static_mdstr_table[27])
+#define GRPC_MDSTR_CONTENT_LENGTH (&grpc_static_mdstr_table[25])
 /* "content-location" */
-#define GRPC_MDSTR_CONTENT_LOCATION (&grpc_static_mdstr_table[28])
+#define GRPC_MDSTR_CONTENT_LOCATION (&grpc_static_mdstr_table[26])
 /* "content-range" */
-#define GRPC_MDSTR_CONTENT_RANGE (&grpc_static_mdstr_table[29])
+#define GRPC_MDSTR_CONTENT_RANGE (&grpc_static_mdstr_table[27])
 /* "content-type" */
-#define GRPC_MDSTR_CONTENT_TYPE (&grpc_static_mdstr_table[30])
+#define GRPC_MDSTR_CONTENT_TYPE (&grpc_static_mdstr_table[28])
 /* "cookie" */
-#define GRPC_MDSTR_COOKIE (&grpc_static_mdstr_table[31])
+#define GRPC_MDSTR_COOKIE (&grpc_static_mdstr_table[29])
 /* "date" */
-#define GRPC_MDSTR_DATE (&grpc_static_mdstr_table[32])
+#define GRPC_MDSTR_DATE (&grpc_static_mdstr_table[30])
 /* "deflate" */
-#define GRPC_MDSTR_DEFLATE (&grpc_static_mdstr_table[33])
+#define GRPC_MDSTR_DEFLATE (&grpc_static_mdstr_table[31])
 /* "deflate,gzip" */
-#define GRPC_MDSTR_DEFLATE_COMMA_GZIP (&grpc_static_mdstr_table[34])
+#define GRPC_MDSTR_DEFLATE_COMMA_GZIP (&grpc_static_mdstr_table[32])
 /* "" */
-#define GRPC_MDSTR_EMPTY (&grpc_static_mdstr_table[35])
+#define GRPC_MDSTR_EMPTY (&grpc_static_mdstr_table[33])
 /* "etag" */
-#define GRPC_MDSTR_ETAG (&grpc_static_mdstr_table[36])
+#define GRPC_MDSTR_ETAG (&grpc_static_mdstr_table[34])
 /* "expect" */
-#define GRPC_MDSTR_EXPECT (&grpc_static_mdstr_table[37])
+#define GRPC_MDSTR_EXPECT (&grpc_static_mdstr_table[35])
 /* "expires" */
-#define GRPC_MDSTR_EXPIRES (&grpc_static_mdstr_table[38])
+#define GRPC_MDSTR_EXPIRES (&grpc_static_mdstr_table[36])
 /* "from" */
-#define GRPC_MDSTR_FROM (&grpc_static_mdstr_table[39])
+#define GRPC_MDSTR_FROM (&grpc_static_mdstr_table[37])
 /* "GET" */
-#define GRPC_MDSTR_GET (&grpc_static_mdstr_table[40])
+#define GRPC_MDSTR_GET (&grpc_static_mdstr_table[38])
 /* "grpc" */
-#define GRPC_MDSTR_GRPC (&grpc_static_mdstr_table[41])
+#define GRPC_MDSTR_GRPC (&grpc_static_mdstr_table[39])
 /* "grpc-accept-encoding" */
-#define GRPC_MDSTR_GRPC_ACCEPT_ENCODING (&grpc_static_mdstr_table[42])
+#define GRPC_MDSTR_GRPC_ACCEPT_ENCODING (&grpc_static_mdstr_table[40])
+/* "grpc-census-bin" */
+#define GRPC_MDSTR_GRPC_CENSUS_BIN (&grpc_static_mdstr_table[41])
 /* "grpc-encoding" */
-#define GRPC_MDSTR_GRPC_ENCODING (&grpc_static_mdstr_table[43])
+#define GRPC_MDSTR_GRPC_ENCODING (&grpc_static_mdstr_table[42])
 /* "grpc-internal-encoding-request" */
-#define GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST (&grpc_static_mdstr_table[44])
+#define GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST (&grpc_static_mdstr_table[43])
 /* "grpc-message" */
-#define GRPC_MDSTR_GRPC_MESSAGE (&grpc_static_mdstr_table[45])
+#define GRPC_MDSTR_GRPC_MESSAGE (&grpc_static_mdstr_table[44])
 /* "grpc-status" */
-#define GRPC_MDSTR_GRPC_STATUS (&grpc_static_mdstr_table[46])
+#define GRPC_MDSTR_GRPC_STATUS (&grpc_static_mdstr_table[45])
 /* "grpc-timeout" */
-#define GRPC_MDSTR_GRPC_TIMEOUT (&grpc_static_mdstr_table[47])
+#define GRPC_MDSTR_GRPC_TIMEOUT (&grpc_static_mdstr_table[46])
+/* "grpc-tracing-bin" */
+#define GRPC_MDSTR_GRPC_TRACING_BIN (&grpc_static_mdstr_table[47])
 /* "gzip" */
 #define GRPC_MDSTR_GZIP (&grpc_static_mdstr_table[48])
 /* "gzip, deflate" */
diff --git a/src/proto/census/census.proto b/src/proto/census/census.proto
index c869d85..c2a594b 100644
--- a/src/proto/census/census.proto
+++ b/src/proto/census/census.proto
@@ -33,12 +33,12 @@
 
 // All the census protos.
 //
-// Nomenclature note: capitalized names below (like Metric) are protos.
+// Nomenclature note: capitalized names below (like Resource) are protos.
 //
-// Census lets you define a Metric - something which can be measured, like the
+// Census lets you define a Resource - something which can be measured, like the
 // latency of an RPC, the number of CPU cycles spent on an operation, or
 // anything else you care to measure. You can record individual instances of
-// measurements (a double value) for every metric of interest. These
+// measurements (a double value) for every Resource of interest. These
 // individual measurements are aggregated together into an Aggregation. There
 // are two Aggregation types available: Distribution (describes the
 // distribution of all measurements, possibly with a histogram) and
@@ -47,8 +47,8 @@
 //
 // You can define how your stats are broken down by Tag values and which
 // Aggregations to use through a View. The corresponding combination of
-// Metric/View/Aggregation which is available to census clients is called a
-// ViewAggregation.
+// Resource/View/Aggregation which is available to census clients is called a
+// Metric.
 
 
 // The following two types are copied from
@@ -85,26 +85,23 @@
   int32 nanos = 2;
 }
 
-// Describes a metric
-message Metric {
-  // name of metric, e.g. rpc_latency, cpu.
+// Describes a Resource.
+message Resource {
+  // name of resource, e.g. rpc_latency, cpu. Must be unique.
   string name = 1;
 
-  // More detailed description of the metric, used in documentation.
+  // More detailed description of the resource, used in documentation.
   string description = 2;
 
   // Fundamental units of measurement supported by Census
   // TODO(aveitch): expand this to include other S.I. units?
-  message BasicUnit {
-    enum Measure {
-      UNKNOWN = 0;
-      BITS = 1;
-      BYTES = 2;
-      SECS = 3;
-      CORES = 4;
-      MAX_UNITS = 5;
-    }
-    Measure type = 1;
+  enum BasicUnit {
+    UNKNOWN = 0;
+    BITS = 1;
+    BYTES = 2;
+    SECS = 3;
+    CORES = 4;
+    MAX_UNITS = 5;
   }
 
   // MeasurementUnit lets you build compound units of the form
@@ -124,7 +121,7 @@
   //     denominator: SECS
   //     denominator: SECS
   //
-  // To specify multiples (in power of 10) units, specify a non-zero prefix
+  // To specify multiples (in power of 10) of units, specify a non-zero prefix
   // value, for example:
   //
   // - MB/s (i.e. megabytes / s):
@@ -141,32 +138,40 @@
     repeated BasicUnit denominator = 3;
   }
 
-  // The units in which the Metric value is reported.
+  // The units in which Resource values are measured.
   MeasurementUnit unit = 3;
-
-  // Metrics will be assigned an ID when registered. Invalid if <= 0.
-  int32 id = 4;
 }
 
-// An Aggregation summarizes a series of individual Metric measurements, an
+// An Aggregation summarizes a series of individual Resource measurements, an
 // AggregationDescriptor describes an Aggregation.
 message AggregationDescriptor {
-  // At most one set of options. If neither option is set, a default type
-  // of Distribution (without a histogram component) will be used.
+  enum AggregationType {
+    // Unspecified. Should not be used.
+    UNKNOWN = 0;
+    // A count of measurements made.
+    COUNT = 1;
+    // A Distribution.
+    DISTRIBUTION = 2;
+    // Counts over fixed time intervals.
+    INTERVAL = 3;
+  }
+  // The type of Aggregation.
+  AggregationType type = 1;
+
+  // At most one set of options. It is illegal to specifiy an option for
+  // COUNT Aggregations. interval_boundaries must be set for INTERVAL types.
+  // bucket_boundaries are optional for DISTRIBUTION types.
   oneof options {
-    // Defines the histogram bucket boundaries for Distributions.
-    BucketBoundaries bucket_boundaries = 1;
+    // Defines histogram bucket boundaries for Distributions.
+    BucketBoundaries bucket_boundaries = 2;
     // Defines the time windows to record for IntervalStats.
-    IntervalBoundaries interval_boundaries = 2;
+    IntervalBoundaries interval_boundaries = 3;
   }
 
   // A Distribution may optionally contain a histogram of the values in the
-  // population. The bucket boundaries for that histogram is described by
-  // `bucket_boundaries`.
-  //
-  // Describes histogram bucket boundaries. Defines `size(bounds) + 1` (= N)
-  // buckets (for size(bounds) >= 1; if size(bounds) == 0, then no histogram
-  // will be defined. The boundaries for bucket index i are:
+  // population. The bucket boundaries for that histogram are described by
+  // `bucket_boundaries`. This defines `size(bounds) + 1` (= N) buckets. The
+  // boundaries for bucket index i are:
   //
   // [-infinity, bounds[i]) for i == 0
   // [bounds[i-1], bounds[i]) for 0 < i < N-2
@@ -196,8 +201,8 @@
 // a specified set of histogram buckets, as defined in
 // Aggregation.bucket_options.
 //
-// The summary statistics are the count, mean, sum of the squared deviation from
-// the mean, the minimum, and the maximum of the set of population of values.
+// The summary statistics are the count, mean, minimum, and the maximum of the
+// set of population of values.
 //
 // Although it is not forbidden, it is generally a bad idea to include
 // non-finite values (infinities or NaNs) in the population of values, as this
@@ -243,7 +248,7 @@
 message IntervalStats {
   // Summary statistic over a single time window.
   message Window {
-    // The window duration.
+    // The window duration. Must be positive.
     Duration window_size = 1;
     // The number of measurements in this window.
     int64 count = 2;
@@ -251,7 +256,7 @@
     double mean = 3;
   }
 
-  // Full set of windows for this metric.
+  // Full set of windows for this aggregation.
   repeated Window window = 1;
 }
 
@@ -264,24 +269,24 @@
 // A View specifies an Aggregation and a set of tag keys. The Aggregation will
 // be broken down by the unique set of matching tag values for each measurement.
 message View {
-  // Name of view.
+  // Name of view. Must be unique.
   string name = 1;
 
   // More detailed description, for documentation purposes.
   string description = 2;
 
-  // ID of Metric to associate with this View.
-  int32 metric_id = 3;
+  // Name of Resource to be broken down for this view.
+  string resource_name = 3;
 
   // Aggregation type to associate with this View.
   AggregationDescriptor aggregation = 4;
 
-  // Tag keys to match with a given Metric. If no keys are specified, then all
-  // stats for the Metric are recorded. Keys must be unique.
+  // Tag keys to match with a given Resource measurement. If no keys are
+  // specified, then all stats are recorded. Keys must be unique.
   repeated string tag_key = 5;
 }
 
-// An Aggregation summarizes a series of individual Metric measures.
+// An Aggregation summarizes a series of individual Resource measurements.
 message Aggregation {
   // Name of this aggregation.
   string name = 1;
@@ -291,23 +296,27 @@
 
   // The data for this Aggregation.
   oneof data {
-    Distribution distribution = 3;
-    IntervalStats interval_stats = 4;
+    uint64 count = 3;
+    Distribution distribution = 4;
+    IntervalStats interval_stats = 5;
   }
 
   // Tags associated with this Aggregation.
-  repeated Tag tag = 5;
+  repeated Tag tag = 6;
 }
 
-// A ViewAggregations represents all the Aggregations for a particular view.
-message ViewAggregations {
+// A Metric represents all the Aggregations for a particular view.
+message Metric {
+  // View associated with this Metric.
+  string view_name = 1;
+
   // Aggregations - each will have a unique set of tag values for the tag_keys
   // associated with the corresponding View.
-  repeated Aggregation aggregation = 1;
+  repeated Aggregation aggregation = 2;
 
-  // Start and end timestamps over which the value was accumulated. These
+  // Start and end timestamps over which the metric was accumulated. These
   // values are not relevant/defined for IntervalStats aggregations, which are
   // always accumulated over a fixed time period.
-  Timestamp start = 2;
-  Timestamp end = 3;
+  Timestamp start = 3;
+  Timestamp end = 4;
 }
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index a029005..969e7b0 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -253,6 +253,7 @@
   'src/core/ext/resolver/sockaddr/sockaddr_resolver.c',
   'src/core/ext/load_reporting/load_reporting.c',
   'src/core/ext/load_reporting/load_reporting_filter.c',
+  'src/core/ext/census/base_resources.c',
   'src/core/ext/census/context.c',
   'src/core/ext/census/gen/census.pb.c',
   'src/core/ext/census/grpc_context.c',
@@ -262,6 +263,7 @@
   'src/core/ext/census/mlog.c',
   'src/core/ext/census/operation.c',
   'src/core/ext/census/placeholders.c',
+  'src/core/ext/census/resource.c',
   'src/core/ext/census/tracing.c',
   'src/core/plugin_registry/grpc_plugin_registry.c',
   'src/boringssl/err_data.c',
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c
index d7f862c..aee57b1 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c
@@ -61,15 +61,10 @@
 census_trace_scan_start_type census_trace_scan_start_import;
 census_get_trace_record_type census_get_trace_record_import;
 census_trace_scan_end_type census_trace_scan_end_import;
+census_define_resource_type census_define_resource_import;
+census_delete_resource_type census_delete_resource_import;
+census_resource_id_type census_resource_id_import;
 census_record_values_type census_record_values_import;
-census_view_create_type census_view_create_import;
-census_view_delete_type census_view_delete_import;
-census_view_metric_type census_view_metric_import;
-census_view_naggregations_type census_view_naggregations_import;
-census_view_tags_type census_view_tags_import;
-census_view_aggregrations_type census_view_aggregrations_import;
-census_view_get_data_type census_view_get_data_import;
-census_view_reset_type census_view_reset_import;
 grpc_compression_algorithm_parse_type grpc_compression_algorithm_parse_import;
 grpc_compression_algorithm_name_type grpc_compression_algorithm_name_import;
 grpc_compression_algorithm_for_level_type grpc_compression_algorithm_for_level_import;
@@ -334,15 +329,10 @@
   census_trace_scan_start_import = (census_trace_scan_start_type) GetProcAddress(library, "census_trace_scan_start");
   census_get_trace_record_import = (census_get_trace_record_type) GetProcAddress(library, "census_get_trace_record");
   census_trace_scan_end_import = (census_trace_scan_end_type) GetProcAddress(library, "census_trace_scan_end");
+  census_define_resource_import = (census_define_resource_type) GetProcAddress(library, "census_define_resource");
+  census_delete_resource_import = (census_delete_resource_type) GetProcAddress(library, "census_delete_resource");
+  census_resource_id_import = (census_resource_id_type) GetProcAddress(library, "census_resource_id");
   census_record_values_import = (census_record_values_type) GetProcAddress(library, "census_record_values");
-  census_view_create_import = (census_view_create_type) GetProcAddress(library, "census_view_create");
-  census_view_delete_import = (census_view_delete_type) GetProcAddress(library, "census_view_delete");
-  census_view_metric_import = (census_view_metric_type) GetProcAddress(library, "census_view_metric");
-  census_view_naggregations_import = (census_view_naggregations_type) GetProcAddress(library, "census_view_naggregations");
-  census_view_tags_import = (census_view_tags_type) GetProcAddress(library, "census_view_tags");
-  census_view_aggregrations_import = (census_view_aggregrations_type) GetProcAddress(library, "census_view_aggregrations");
-  census_view_get_data_import = (census_view_get_data_type) GetProcAddress(library, "census_view_get_data");
-  census_view_reset_import = (census_view_reset_type) GetProcAddress(library, "census_view_reset");
   grpc_compression_algorithm_parse_import = (grpc_compression_algorithm_parse_type) GetProcAddress(library, "grpc_compression_algorithm_parse");
   grpc_compression_algorithm_name_import = (grpc_compression_algorithm_name_type) GetProcAddress(library, "grpc_compression_algorithm_name");
   grpc_compression_algorithm_for_level_import = (grpc_compression_algorithm_for_level_type) GetProcAddress(library, "grpc_compression_algorithm_for_level");
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
index 14da637..3bb76fb 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
@@ -134,33 +134,18 @@
 typedef void(*census_trace_scan_end_type)();
 extern census_trace_scan_end_type census_trace_scan_end_import;
 #define census_trace_scan_end census_trace_scan_end_import
+typedef int32_t(*census_define_resource_type)(const uint8_t *resource_pb, size_t resource_pb_size);
+extern census_define_resource_type census_define_resource_import;
+#define census_define_resource census_define_resource_import
+typedef void(*census_delete_resource_type)(int32_t resource_id);
+extern census_delete_resource_type census_delete_resource_import;
+#define census_delete_resource census_delete_resource_import
+typedef int32_t(*census_resource_id_type)(const char *name);
+extern census_resource_id_type census_resource_id_import;
+#define census_resource_id census_resource_id_import
 typedef void(*census_record_values_type)(census_context *context, census_value *values, size_t nvalues);
 extern census_record_values_type census_record_values_import;
 #define census_record_values census_record_values_import
-typedef census_view *(*census_view_create_type)(uint32_t metric_id, const census_context *tags, const census_aggregation *aggregations, size_t naggregations);
-extern census_view_create_type census_view_create_import;
-#define census_view_create census_view_create_import
-typedef void(*census_view_delete_type)(census_view *view);
-extern census_view_delete_type census_view_delete_import;
-#define census_view_delete census_view_delete_import
-typedef size_t(*census_view_metric_type)(const census_view *view);
-extern census_view_metric_type census_view_metric_import;
-#define census_view_metric census_view_metric_import
-typedef size_t(*census_view_naggregations_type)(const census_view *view);
-extern census_view_naggregations_type census_view_naggregations_import;
-#define census_view_naggregations census_view_naggregations_import
-typedef const census_context *(*census_view_tags_type)(const census_view *view);
-extern census_view_tags_type census_view_tags_import;
-#define census_view_tags census_view_tags_import
-typedef const census_aggregation *(*census_view_aggregrations_type)(const census_view *view);
-extern census_view_aggregrations_type census_view_aggregrations_import;
-#define census_view_aggregrations census_view_aggregrations_import
-typedef const census_view_data *(*census_view_get_data_type)(const census_view *view);
-extern census_view_get_data_type census_view_get_data_import;
-#define census_view_get_data census_view_get_data_import
-typedef void(*census_view_reset_type)(census_view *view);
-extern census_view_reset_type census_view_reset_import;
-#define census_view_reset census_view_reset_import
 typedef int(*grpc_compression_algorithm_parse_type)(const char *name, size_t name_length, grpc_compression_algorithm *algorithm);
 extern grpc_compression_algorithm_parse_type grpc_compression_algorithm_parse_import;
 #define grpc_compression_algorithm_parse grpc_compression_algorithm_parse_import
diff --git a/test/core/census/README b/test/core/census/README
new file mode 100644
index 0000000..d5363b7
--- /dev/null
+++ b/test/core/census/README
@@ -0,0 +1,7 @@
+Test source and data files for Census.
+
+binary proto files (*.pb) in data directory are generated from the *.txt file,
+via:
+
+BASE="filename"
+cat $BASE.txt | protoc --encode=google.census.Resource census.proto > $BASE.pb
diff --git a/test/core/census/data/resource_empty_name.pb b/test/core/census/data/resource_empty_name.pb
new file mode 100644
index 0000000..4d54744
--- /dev/null
+++ b/test/core/census/data/resource_empty_name.pb
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/core/census/data/resource_empty_name.txt b/test/core/census/data/resource_empty_name.txt
new file mode 100644
index 0000000..271fd32
--- /dev/null
+++ b/test/core/census/data/resource_empty_name.txt
@@ -0,0 +1,5 @@
+# Name is present, but empty.
+name : ''
+unit {
+  numerator : SECS
+}
diff --git a/test/core/census/data/resource_full.pb b/test/core/census/data/resource_full.pb
new file mode 100644
index 0000000..e4c6a2a
--- /dev/null
+++ b/test/core/census/data/resource_full.pb
Binary files differ
diff --git a/test/core/census/data/resource_full.txt b/test/core/census/data/resource_full.txt
new file mode 100644
index 0000000..1aa2faf
--- /dev/null
+++ b/test/core/census/data/resource_full.txt
@@ -0,0 +1,9 @@
+# A full resource definition - all fields filled out.
+name : 'full_resource'
+description : 'A resource with everything defined'
+unit {
+  # Megabits per second.
+  prefix : 6
+  numerator : BITS
+  denominator : SECS
+}
diff --git a/test/core/census/data/resource_minimal_good.pb b/test/core/census/data/resource_minimal_good.pb
new file mode 100644
index 0000000..7100c46
--- /dev/null
+++ b/test/core/census/data/resource_minimal_good.pb
@@ -0,0 +1,2 @@
+
+minimal_good
\ No newline at end of file
diff --git a/test/core/census/data/resource_minimal_good.txt b/test/core/census/data/resource_minimal_good.txt
new file mode 100644
index 0000000..a7a7e71
--- /dev/null
+++ b/test/core/census/data/resource_minimal_good.txt
@@ -0,0 +1,5 @@
+# A minimal "good" Resource definition: has a name and numerator/unit.
+name : 'minimal_good'
+unit {
+  numerator : SECS
+}
diff --git a/test/core/census/data/resource_no_name.pb b/test/core/census/data/resource_no_name.pb
new file mode 100644
index 0000000..4d54744
--- /dev/null
+++ b/test/core/census/data/resource_no_name.pb
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/core/census/data/resource_no_name.txt b/test/core/census/data/resource_no_name.txt
new file mode 100644
index 0000000..8f12a91
--- /dev/null
+++ b/test/core/census/data/resource_no_name.txt
@@ -0,0 +1,4 @@
+# The minimal good Resource without a name.
+unit {
+  numerator : SECS
+}
diff --git a/test/core/census/data/resource_no_numerator.pb b/test/core/census/data/resource_no_numerator.pb
new file mode 100644
index 0000000..2a5ccee
--- /dev/null
+++ b/test/core/census/data/resource_no_numerator.pb
@@ -0,0 +1,2 @@
+
+resource_no_numeratorýÿÿÿÿÿÿÿÿ
\ No newline at end of file
diff --git a/test/core/census/data/resource_no_numerator.txt b/test/core/census/data/resource_no_numerator.txt
new file mode 100644
index 0000000..fc1fec7
--- /dev/null
+++ b/test/core/census/data/resource_no_numerator.txt
@@ -0,0 +1,6 @@
+# Resource without a numerator
+name : 'resource_no_numerator'
+unit {
+  prefix : -3
+  denominator : SECS
+}
diff --git a/test/core/census/data/resource_no_unit.pb b/test/core/census/data/resource_no_unit.pb
new file mode 100644
index 0000000..9dca262
--- /dev/null
+++ b/test/core/census/data/resource_no_unit.pb
@@ -0,0 +1,2 @@
+
+resource_no_unit
\ No newline at end of file
diff --git a/test/core/census/data/resource_no_unit.txt b/test/core/census/data/resource_no_unit.txt
new file mode 100644
index 0000000..c5d5115
--- /dev/null
+++ b/test/core/census/data/resource_no_unit.txt
@@ -0,0 +1,2 @@
+# The minimal good resource without a unit
+name : 'resource_no_unit'
diff --git a/test/core/census/resource_test.c b/test/core/census/resource_test.c
new file mode 100644
index 0000000..e1556d7
--- /dev/null
+++ b/test/core/census/resource_test.c
@@ -0,0 +1,157 @@
+/*
+ *
+ * Copyright 2016, 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 "src/core/ext/census/resource.h"
+#include <grpc/census.h>
+#include <grpc/support/log.h>
+#include <grpc/support/port_platform.h>
+#include <grpc/support/useful.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "src/core/ext/census/base_resources.h"
+#include "test/core/util/test_config.h"
+
+// Test all the functionality for dealing with Resources.
+
+// Just startup and shutdown resources subsystem.
+static void test_enable_disable() {
+  initialize_resources();
+  shutdown_resources();
+}
+
+// A blank/empty initialization should not work.
+static void test_empty_definition() {
+  initialize_resources();
+  int32_t rid = census_define_resource(NULL, 0);
+  GPR_ASSERT(rid == -1);
+  uint8_t buffer[50] = {0};
+  rid = census_define_resource(buffer, 50);
+  GPR_ASSERT(rid == -1);
+  shutdown_resources();
+}
+
+// Given a file name, read raw proto and define the resource included within.
+// Returns resource id from census_define_resource().
+static int32_t define_resource_from_file(const char *file) {
+#define BUF_SIZE 512
+  uint8_t buffer[BUF_SIZE];
+  FILE *input = fopen(file, "rb");
+  GPR_ASSERT(input != NULL);
+  size_t nbytes = fread(buffer, 1, BUF_SIZE, input);
+  GPR_ASSERT(nbytes != 0 && nbytes < BUF_SIZE && feof(input) && !ferror(input));
+  int32_t rid = census_define_resource(buffer, nbytes);
+  GPR_ASSERT(fclose(input) == 0);
+  return rid;
+}
+
+// Test definition of a single resource, using a proto read from a file. The
+// `succeed` parameter indicates whether we expect the definition to succeed or
+// fail. `name` is used to check that the returned resource can be looked up by
+// name.
+static void test_define_single_resource(const char *file, const char *name,
+                                        bool succeed) {
+  gpr_log(GPR_INFO, "Test defining resource \"%s\"\n", name);
+  initialize_resources();
+  int32_t rid = define_resource_from_file(file);
+  if (succeed) {
+    GPR_ASSERT(rid >= 0);
+    int32_t rid2 = census_resource_id(name);
+    GPR_ASSERT(rid == rid2);
+  } else {
+    GPR_ASSERT(rid < 0);
+  }
+  shutdown_resources();
+}
+
+// Try deleting various resources (both those that exist and those that don't).
+static void test_delete_resource() {
+  initialize_resources();
+  // Try deleting resource before any are defined.
+  census_delete_resource(0);
+  // Create and check a couple of resources.
+  int32_t rid1 = define_resource_from_file(
+      "test/core/census/data/resource_minimal_good.pb");
+  int32_t rid2 =
+      define_resource_from_file("test/core/census/data/resource_full.pb");
+  GPR_ASSERT(rid1 >= 0 && rid2 >= 0 && rid1 != rid2);
+  int32_t rid3 = census_resource_id("minimal_good");
+  int32_t rid4 = census_resource_id("full_resource");
+  GPR_ASSERT(rid1 == rid3 && rid2 == rid4);
+  // Try deleting non-existant resources.
+  census_delete_resource(-1);
+  census_delete_resource(rid1 + rid2 + 1);
+  census_delete_resource(10000000);
+  // Delete one of the previously defined resources and check for deletion.
+  census_delete_resource(rid1);
+  rid3 = census_resource_id("minimal_good");
+  GPR_ASSERT(rid3 < 0);
+  // Check that re-adding works.
+  rid1 = define_resource_from_file(
+      "test/core/census/data/resource_minimal_good.pb");
+  GPR_ASSERT(rid1 >= 0);
+  rid3 = census_resource_id("minimal_good");
+  GPR_ASSERT(rid1 == rid3);
+  shutdown_resources();
+}
+
+// Test define base resources.
+static void test_base_resources() {
+  initialize_resources();
+  define_base_resources();
+  int32_t rid1 = census_resource_id("client_rpc_latency");
+  int32_t rid2 = census_resource_id("server_rpc_latency");
+  GPR_ASSERT(rid1 >= 0 && rid2 >= 0 && rid1 != rid2);
+  shutdown_resources();
+}
+
+int main(int argc, char **argv) {
+  grpc_test_init(argc, argv);
+  test_enable_disable();
+  test_empty_definition();
+  test_define_single_resource("test/core/census/data/resource_minimal_good.pb",
+                              "minimal_good", true);
+  test_define_single_resource("test/core/census/data/resource_full.pb",
+                              "full_resource", true);
+  test_define_single_resource("test/core/census/data/resource_no_name.pb",
+                              "resource_no_name", false);
+  test_define_single_resource("test/core/census/data/resource_no_numerator.pb",
+                              "resource_no_numerator", false);
+  test_define_single_resource("test/core/census/data/resource_no_unit.pb",
+                              "resource_no_unit", false);
+  test_define_single_resource("test/core/census/data/resource_empty_name.pb",
+                              "resource_empty_name", false);
+  test_delete_resource();
+  test_base_resources();
+  return 0;
+}
diff --git a/test/core/channel/channel_stack_test.c b/test/core/channel/channel_stack_test.c
index 806fd0a..569b3f7 100644
--- a/test/core/channel/channel_stack_test.c
+++ b/test/core/channel/channel_stack_test.c
@@ -53,10 +53,12 @@
   *(int *)(elem->channel_data) = 0;
 }
 
-static void call_init_func(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
-                           grpc_call_element_args *args) {
+static grpc_error *call_init_func(grpc_exec_ctx *exec_ctx,
+                                  grpc_call_element *elem,
+                                  grpc_call_element_args *args) {
   ++*(int *)(elem->channel_data);
   *(int *)(elem->call_data) = 0;
+  return GRPC_ERROR_NONE;
 }
 
 static void channel_destroy_func(grpc_exec_ctx *exec_ctx,
@@ -133,8 +135,10 @@
   GPR_ASSERT(*channel_data == 0);
 
   call_stack = gpr_malloc(channel_stack->call_stack_size);
-  grpc_call_stack_init(&exec_ctx, channel_stack, 1, free_call, call_stack, NULL,
-                       NULL, call_stack);
+  grpc_error *error =
+      grpc_call_stack_init(&exec_ctx, channel_stack, 1, free_call, call_stack,
+                           NULL, NULL, call_stack);
+  GPR_ASSERT(error == GRPC_ERROR_NONE);
   GPR_ASSERT(call_stack->count == 1);
   call_elem = grpc_call_stack_element(call_stack, 0);
   GPR_ASSERT(call_elem->filter == channel_elem->filter);
diff --git a/test/core/end2end/end2end_nosec_tests.c b/test/core/end2end/end2end_nosec_tests.c
index 59ef6ba..3efd18c 100644
--- a/test/core/end2end/end2end_nosec_tests.c
+++ b/test/core/end2end/end2end_nosec_tests.c
@@ -69,6 +69,8 @@
 extern void disappearing_server_pre_init(void);
 extern void empty_batch(grpc_end2end_test_config config);
 extern void empty_batch_pre_init(void);
+extern void filter_call_init_fails(grpc_end2end_test_config config);
+extern void filter_call_init_fails_pre_init(void);
 extern void filter_causes_close(grpc_end2end_test_config config);
 extern void filter_causes_close_pre_init(void);
 extern void graceful_server_shutdown(grpc_end2end_test_config config);
@@ -140,6 +142,7 @@
   default_host_pre_init();
   disappearing_server_pre_init();
   empty_batch_pre_init();
+  filter_call_init_fails_pre_init();
   filter_causes_close_pre_init();
   graceful_server_shutdown_pre_init();
   high_initial_seqno_pre_init();
@@ -189,6 +192,7 @@
     default_host(config);
     disappearing_server(config);
     empty_batch(config);
+    filter_call_init_fails(config);
     filter_causes_close(config);
     graceful_server_shutdown(config);
     high_initial_seqno(config);
@@ -272,6 +276,10 @@
       empty_batch(config);
       continue;
     }
+    if (0 == strcmp("filter_call_init_fails", argv[i])) {
+      filter_call_init_fails(config);
+      continue;
+    }
     if (0 == strcmp("filter_causes_close", argv[i])) {
       filter_causes_close(config);
       continue;
diff --git a/test/core/end2end/end2end_tests.c b/test/core/end2end/end2end_tests.c
index cbc7c3c..e3d791a 100644
--- a/test/core/end2end/end2end_tests.c
+++ b/test/core/end2end/end2end_tests.c
@@ -71,6 +71,8 @@
 extern void disappearing_server_pre_init(void);
 extern void empty_batch(grpc_end2end_test_config config);
 extern void empty_batch_pre_init(void);
+extern void filter_call_init_fails(grpc_end2end_test_config config);
+extern void filter_call_init_fails_pre_init(void);
 extern void filter_causes_close(grpc_end2end_test_config config);
 extern void filter_causes_close_pre_init(void);
 extern void graceful_server_shutdown(grpc_end2end_test_config config);
@@ -143,6 +145,7 @@
   default_host_pre_init();
   disappearing_server_pre_init();
   empty_batch_pre_init();
+  filter_call_init_fails_pre_init();
   filter_causes_close_pre_init();
   graceful_server_shutdown_pre_init();
   high_initial_seqno_pre_init();
@@ -193,6 +196,7 @@
     default_host(config);
     disappearing_server(config);
     empty_batch(config);
+    filter_call_init_fails(config);
     filter_causes_close(config);
     graceful_server_shutdown(config);
     high_initial_seqno(config);
@@ -280,6 +284,10 @@
       empty_batch(config);
       continue;
     }
+    if (0 == strcmp("filter_call_init_fails", argv[i])) {
+      filter_call_init_fails(config);
+      continue;
+    }
     if (0 == strcmp("filter_causes_close", argv[i])) {
       filter_causes_close(config);
       continue;
diff --git a/test/core/end2end/fuzzers/hpack.dictionary b/test/core/end2end/fuzzers/hpack.dictionary
index af075c0..3157dfc 100644
--- a/test/core/end2end/fuzzers/hpack.dictionary
+++ b/test/core/end2end/fuzzers/hpack.dictionary
@@ -21,8 +21,6 @@
 "\x0A:authority"
 "\x0Dauthorization"
 "\x0Dcache-control"
-"\x0Acensus-bin"
-"\x11census-binary-bin"
 "\x13content-disposition"
 "\x10content-encoding"
 "\x10content-language"
@@ -42,11 +40,13 @@
 "\x03GET"
 "\x04grpc"
 "\x14grpc-accept-encoding"
+"\x0Fgrpc-census-bin"
 "\x0Dgrpc-encoding"
 "\x1Egrpc-internal-encoding-request"
 "\x0Cgrpc-message"
 "\x0Bgrpc-status"
 "\x0Cgrpc-timeout"
+"\x10grpc-tracing-bin"
 "\x04gzip"
 "\x0Dgzip, deflate"
 "\x04host"
diff --git a/test/core/end2end/gen_build_yaml.py b/test/core/end2end/gen_build_yaml.py
index cd0359f..c5bd776 100755
--- a/test/core/end2end/gen_build_yaml.py
+++ b/test/core/end2end/gen_build_yaml.py
@@ -103,6 +103,7 @@
     'disappearing_server': connectivity_test_options,
     'empty_batch': default_test_options,
     'filter_causes_close': default_test_options,
+    'filter_call_init_fails': default_test_options,
     'graceful_server_shutdown': default_test_options._replace(cpu_cost=LOWCPU),
     'hpack_size': default_test_options._replace(proxyable=False,
                                                 traceable=False),
diff --git a/test/core/end2end/tests/filter_call_init_fails.c b/test/core/end2end/tests/filter_call_init_fails.c
new file mode 100644
index 0000000..a09183b
--- /dev/null
+++ b/test/core/end2end/tests/filter_call_init_fails.c
@@ -0,0 +1,273 @@
+/*
+ *
+ * Copyright 2016, 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 "test/core/end2end/end2end_tests.h"
+
+#include <limits.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <grpc/byte_buffer.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/time.h>
+#include <grpc/support/useful.h>
+#include "src/core/lib/channel/channel_stack_builder.h"
+#include "src/core/lib/surface/channel_init.h"
+#include "test/core/end2end/cq_verifier.h"
+
+enum { TIMEOUT = 200000 };
+
+static bool g_enable_filter = false;
+
+static void *tag(intptr_t t) { return (void *)t; }
+
+static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
+                                            const char *test_name,
+                                            grpc_channel_args *client_args,
+                                            grpc_channel_args *server_args) {
+  grpc_end2end_test_fixture f;
+  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  f = config.create_fixture(client_args, server_args);
+  config.init_server(&f, server_args);
+  config.init_client(&f, client_args);
+  return f;
+}
+
+static gpr_timespec n_seconds_time(int n) {
+  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+}
+
+static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
+
+static void drain_cq(grpc_completion_queue *cq) {
+  grpc_event ev;
+  do {
+    ev = grpc_completion_queue_next(cq, five_seconds_time(), NULL);
+  } while (ev.type != GRPC_QUEUE_SHUTDOWN);
+}
+
+static void shutdown_server(grpc_end2end_test_fixture *f) {
+  if (!f->server) return;
+  grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
+  GPR_ASSERT(grpc_completion_queue_pluck(
+                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 .type == GRPC_OP_COMPLETE);
+  grpc_server_destroy(f->server);
+  f->server = NULL;
+}
+
+static void shutdown_client(grpc_end2end_test_fixture *f) {
+  if (!f->client) return;
+  grpc_channel_destroy(f->client);
+  f->client = NULL;
+}
+
+static void end_test(grpc_end2end_test_fixture *f) {
+  shutdown_server(f);
+  shutdown_client(f);
+
+  grpc_completion_queue_shutdown(f->cq);
+  drain_cq(f->cq);
+  grpc_completion_queue_destroy(f->cq);
+}
+
+// Simple request via a server filter that always fails to initialize
+// the call.
+static void test_request(grpc_end2end_test_config config) {
+  grpc_call *c;
+  grpc_call *s;
+  gpr_slice request_payload_slice = gpr_slice_from_copied_string("hello world");
+  grpc_byte_buffer *request_payload =
+      grpc_raw_byte_buffer_create(&request_payload_slice, 1);
+  gpr_timespec deadline = five_seconds_time();
+  grpc_end2end_test_fixture f =
+      begin_test(config, "filter_call_init_fails", NULL, NULL);
+  cq_verifier *cqv = cq_verifier_create(f.cq);
+  grpc_op ops[6];
+  grpc_op *op;
+  grpc_metadata_array initial_metadata_recv;
+  grpc_metadata_array trailing_metadata_recv;
+  grpc_metadata_array request_metadata_recv;
+  grpc_byte_buffer *request_payload_recv = NULL;
+  grpc_call_details call_details;
+  grpc_status_code status;
+  grpc_call_error error;
+  char *details = NULL;
+  size_t details_capacity = 0;
+
+  c = grpc_channel_create_call(f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               "/foo", "foo.test.google.fr", deadline, NULL);
+  GPR_ASSERT(c);
+
+  grpc_metadata_array_init(&initial_metadata_recv);
+  grpc_metadata_array_init(&trailing_metadata_recv);
+  grpc_metadata_array_init(&request_metadata_recv);
+  grpc_call_details_init(&call_details);
+
+  memset(ops, 0, sizeof(ops));
+  op = ops;
+  op->op = GRPC_OP_SEND_INITIAL_METADATA;
+  op->data.send_initial_metadata.count = 0;
+  op->data.send_initial_metadata.metadata = NULL;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  op->op = GRPC_OP_SEND_MESSAGE;
+  op->data.send_message = request_payload;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  op->op = GRPC_OP_RECV_INITIAL_METADATA;
+  op->data.recv_initial_metadata = &initial_metadata_recv;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
+  op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
+  op->data.recv_status_on_client.status = &status;
+  op->data.recv_status_on_client.status_details = &details;
+  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL);
+  GPR_ASSERT(GRPC_CALL_OK == error);
+
+  error =
+      grpc_server_request_call(f.server, &s, &call_details,
+                               &request_metadata_recv, f.cq, f.cq, tag(101));
+  GPR_ASSERT(GRPC_CALL_OK == error);
+
+  cq_expect_completion(cqv, tag(1), 1);
+  cq_verify(cqv);
+
+  GPR_ASSERT(status == GRPC_STATUS_PERMISSION_DENIED);
+  GPR_ASSERT(0 == strcmp(details, "access denied"));
+
+  gpr_free(details);
+  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);
+
+  grpc_call_destroy(c);
+
+  cq_verifier_destroy(cqv);
+
+  grpc_byte_buffer_destroy(request_payload);
+  grpc_byte_buffer_destroy(request_payload_recv);
+
+  end_test(&f);
+  config.tear_down_data(&f);
+}
+
+/*******************************************************************************
+ * Test filter - always fails to initialize a call
+ */
+
+static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
+                                  grpc_call_element *elem,
+                                  grpc_call_element_args *args) {
+  return grpc_error_set_int(GRPC_ERROR_CREATE("access denied"),
+                            GRPC_ERROR_INT_GRPC_STATUS,
+                            GRPC_STATUS_PERMISSION_DENIED);
+}
+
+static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
+                              const grpc_call_final_info *final_info,
+                              void *and_free_memory) {}
+
+static void init_channel_elem(grpc_exec_ctx *exec_ctx,
+                              grpc_channel_element *elem,
+                              grpc_channel_element_args *args) {}
+
+static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
+                                 grpc_channel_element *elem) {}
+
+static const grpc_channel_filter test_filter = {
+    grpc_call_next_op,
+    grpc_channel_next_op,
+    0,
+    init_call_elem,
+    grpc_call_stack_ignore_set_pollset_or_pollset_set,
+    destroy_call_elem,
+    0,
+    init_channel_elem,
+    destroy_channel_elem,
+    grpc_call_next_get_peer,
+    "filter_call_init_fails"};
+
+/*******************************************************************************
+ * Registration
+ */
+
+static bool maybe_add_filter(grpc_channel_stack_builder *builder, void *arg) {
+  if (g_enable_filter) {
+    // Want to add the filter as close to the end as possible, to make
+    // sure that all of the filters work well together.  However, we
+    // can't add it at the very end, because the connected channel filter
+    // must be the last one.  So we add it right before the last one.
+    grpc_channel_stack_builder_iterator *it =
+        grpc_channel_stack_builder_create_iterator_at_last(builder);
+    GPR_ASSERT(grpc_channel_stack_builder_move_prev(it));
+    const bool retval = grpc_channel_stack_builder_add_filter_before(
+        it, &test_filter, NULL, NULL);
+    grpc_channel_stack_builder_iterator_destroy(it);
+    return retval;
+  } else {
+    return true;
+  }
+}
+
+static void init_plugin(void) {
+  grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX,
+                                   maybe_add_filter, NULL);
+}
+
+static void destroy_plugin(void) {}
+
+void filter_call_init_fails(grpc_end2end_test_config config) {
+  g_enable_filter = true;
+  test_request(config);
+  g_enable_filter = false;
+}
+
+void filter_call_init_fails_pre_init(void) {
+  grpc_register_plugin(init_plugin, destroy_plugin);
+}
diff --git a/test/core/end2end/tests/filter_causes_close.c b/test/core/end2end/tests/filter_causes_close.c
index 5a4803b..c6c36d6 100644
--- a/test/core/end2end/tests/filter_causes_close.c
+++ b/test/core/end2end/tests/filter_causes_close.c
@@ -233,8 +233,11 @@
   grpc_call_next_op(exec_ctx, elem, op);
 }
 
-static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
-                           grpc_call_element_args *args) {}
+static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
+                                  grpc_call_element *elem,
+                                  grpc_call_element_args *args) {
+  return GRPC_ERROR_NONE;
+}
 
 static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
                               const grpc_call_final_info *final_info,
diff --git a/test/cpp/qps/limit_cores.cc b/test/cpp/qps/limit_cores.cc
index 59ed369..b5c2225 100644
--- a/test/cpp/qps/limit_cores.cc
+++ b/test/cpp/qps/limit_cores.cc
@@ -68,9 +68,9 @@
       cores_set++;
     }
   }
-  GPR_ASSERT(sched_setaffinity(0, size, cpup) == 0);
+  bool affinity_set = (sched_setaffinity(0, size, cpup) == 0);
   CPU_FREE(cpup);
-  return cores_set;
+  return affinity_set ? cores_set : num_cores;
 }
 
 }  // namespace testing
diff --git a/tools/codegen/core/gen_static_metadata.py b/tools/codegen/core/gen_static_metadata.py
index c3c0496..859adcb 100755
--- a/tools/codegen/core/gen_static_metadata.py
+++ b/tools/codegen/core/gen_static_metadata.py
@@ -50,8 +50,8 @@
     'host',
     'grpc-message',
     'grpc-status',
-    'census-bin',
-    'census-binary-bin',
+    'grpc-tracing-bin',
+    'grpc-census-bin',
     '',
     ('grpc-status', '0'),
     ('grpc-status', '1'),
diff --git a/tools/distrib/check_include_guards.py b/tools/distrib/check_include_guards.py
index 56b2924..2831281 100755
--- a/tools/distrib/check_include_guards.py
+++ b/tools/distrib/check_include_guards.py
@@ -200,6 +200,6 @@
 
 for filename in filename_list:
   if filename in KNOWN_BAD: continue
-  ok = validator.check(filename, args.fix)
+  ok = ok and validator.check(filename, args.fix)
 
 sys.exit(0 if ok else 1)
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index 5f5fdff..b172232 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -942,11 +942,13 @@
 src/core/ext/load_reporting/load_reporting.h \
 src/core/ext/load_reporting/load_reporting_filter.h \
 src/core/ext/census/aggregation.h \
+src/core/ext/census/base_resources.h \
 src/core/ext/census/census_interface.h \
 src/core/ext/census/census_rpc_stats.h \
 src/core/ext/census/gen/census.pb.h \
 src/core/ext/census/grpc_filter.h \
 src/core/ext/census/mlog.h \
+src/core/ext/census/resource.h \
 src/core/ext/census/rpc_metric_id.h \
 src/core/lib/surface/init.c \
 src/core/lib/channel/channel_args.c \
@@ -1126,6 +1128,7 @@
 src/core/ext/resolver/sockaddr/sockaddr_resolver.c \
 src/core/ext/load_reporting/load_reporting.c \
 src/core/ext/load_reporting/load_reporting_filter.c \
+src/core/ext/census/base_resources.c \
 src/core/ext/census/context.c \
 src/core/ext/census/gen/census.pb.c \
 src/core/ext/census/grpc_context.c \
@@ -1135,6 +1138,7 @@
 src/core/ext/census/mlog.c \
 src/core/ext/census/operation.c \
 src/core/ext/census/placeholders.c \
+src/core/ext/census/resource.c \
 src/core/ext/census/tracing.c \
 src/core/plugin_registry/grpc_plugin_registry.c \
 include/grpc/support/alloc.h \
diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json
index 132bdf9..4854a0b 100644
--- a/tools/run_tests/sources_and_headers.json
+++ b/tools/run_tests/sources_and_headers.json
@@ -149,6 +149,22 @@
     ], 
     "headers": [], 
     "language": "c", 
+    "name": "census_resource_test", 
+    "src": [
+      "test/core/census/resource_test.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
     "name": "channel_create_test", 
     "src": [
       "test/core/surface/channel_create_test.c"
@@ -5441,6 +5457,7 @@
       "test/core/end2end/tests/default_host.c", 
       "test/core/end2end/tests/disappearing_server.c", 
       "test/core/end2end/tests/empty_batch.c", 
+      "test/core/end2end/tests/filter_call_init_fails.c", 
       "test/core/end2end/tests/filter_causes_close.c", 
       "test/core/end2end/tests/graceful_server_shutdown.c", 
       "test/core/end2end/tests/high_initial_seqno.c", 
@@ -5502,6 +5519,7 @@
       "test/core/end2end/tests/default_host.c", 
       "test/core/end2end/tests/disappearing_server.c", 
       "test/core/end2end/tests/empty_batch.c", 
+      "test/core/end2end/tests/filter_call_init_fails.c", 
       "test/core/end2end/tests/filter_causes_close.c", 
       "test/core/end2end/tests/graceful_server_shutdown.c", 
       "test/core/end2end/tests/high_initial_seqno.c", 
@@ -5542,11 +5560,13 @@
     "headers": [
       "include/grpc/census.h", 
       "src/core/ext/census/aggregation.h", 
+      "src/core/ext/census/base_resources.h", 
       "src/core/ext/census/census_interface.h", 
       "src/core/ext/census/census_rpc_stats.h", 
       "src/core/ext/census/gen/census.pb.h", 
       "src/core/ext/census/grpc_filter.h", 
       "src/core/ext/census/mlog.h", 
+      "src/core/ext/census/resource.h", 
       "src/core/ext/census/rpc_metric_id.h"
     ], 
     "language": "c", 
@@ -5554,6 +5574,8 @@
     "src": [
       "include/grpc/census.h", 
       "src/core/ext/census/aggregation.h", 
+      "src/core/ext/census/base_resources.c", 
+      "src/core/ext/census/base_resources.h", 
       "src/core/ext/census/census_interface.h", 
       "src/core/ext/census/census_rpc_stats.h", 
       "src/core/ext/census/context.c", 
@@ -5568,6 +5590,8 @@
       "src/core/ext/census/mlog.h", 
       "src/core/ext/census/operation.c", 
       "src/core/ext/census/placeholders.c", 
+      "src/core/ext/census/resource.c", 
+      "src/core/ext/census/resource.h", 
       "src/core/ext/census/rpc_metric_id.h", 
       "src/core/ext/census/tracing.c"
     ], 
diff --git a/tools/run_tests/tests.json b/tools/run_tests/tests.json
index 142a3b6..3217142 100644
--- a/tools/run_tests/tests.json
+++ b/tools/run_tests/tests.json
@@ -182,6 +182,27 @@
     "flaky": false, 
     "gtest": false, 
     "language": "c", 
+    "name": "census_resource_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ]
+  }, 
+  {
+    "args": [], 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "gtest": false, 
+    "language": "c", 
     "name": "channel_create_test", 
     "platforms": [
       "linux", 
@@ -4699,6 +4720,28 @@
   }, 
   {
     "args": [
+      "filter_call_init_fails"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_census_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "filter_causes_close"
     ], 
     "ci_platforms": [
@@ -5601,6 +5644,28 @@
   }, 
   {
     "args": [
+      "filter_call_init_fails"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_compress_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "filter_causes_close"
     ], 
     "ci_platforms": [
@@ -6489,6 +6554,27 @@
   }, 
   {
     "args": [
+      "filter_call_init_fails"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_fakesec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "filter_causes_close"
     ], 
     "ci_platforms": [
@@ -7276,6 +7362,26 @@
   }, 
   {
     "args": [
+      "filter_call_init_fails"
+    ], 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_fd_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "filter_causes_close"
     ], 
     "ci_platforms": [
@@ -8084,6 +8190,28 @@
   }, 
   {
     "args": [
+      "filter_call_init_fails"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "filter_causes_close"
     ], 
     "ci_platforms": [
@@ -8902,6 +9030,22 @@
   }, 
   {
     "args": [
+      "filter_call_init_fails"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full+pipe_test", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
       "filter_causes_close"
     ], 
     "ci_platforms": [
@@ -9642,6 +9786,28 @@
   }, 
   {
     "args": [
+      "filter_call_init_fails"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full+trace_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "filter_causes_close"
     ], 
     "ci_platforms": [
@@ -10508,6 +10674,27 @@
   }, 
   {
     "args": [
+      "filter_call_init_fails"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_http_proxy_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "filter_causes_close"
     ], 
     "ci_platforms": [
@@ -11383,6 +11570,28 @@
   }, 
   {
     "args": [
+      "filter_call_init_fails"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_load_reporting_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "filter_causes_close"
     ], 
     "ci_platforms": [
@@ -12271,6 +12480,27 @@
   }, 
   {
     "args": [
+      "filter_call_init_fails"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_oauth2_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "filter_causes_close"
     ], 
     "ci_platforms": [
@@ -13090,6 +13320,27 @@
   }, 
   {
     "args": [
+      "filter_call_init_fails"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_proxy_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "filter_causes_close"
     ], 
     "ci_platforms": [
@@ -13804,6 +14055,27 @@
   }, 
   {
     "args": [
+      "filter_call_init_fails"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_sockpair_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "filter_causes_close"
     ], 
     "ci_platforms": [
@@ -14560,6 +14832,27 @@
   }, 
   {
     "args": [
+      "filter_call_init_fails"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_sockpair+trace_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "filter_causes_close"
     ], 
     "ci_platforms": [
@@ -15295,6 +15588,27 @@
   }, 
   {
     "args": [
+      "filter_call_init_fails"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_sockpair_1byte_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "filter_causes_close"
     ], 
     "ci_platforms": [
@@ -16128,6 +16442,28 @@
   }, 
   {
     "args": [
+      "filter_call_init_fails"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_ssl_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "filter_causes_close"
     ], 
     "ci_platforms": [
@@ -17030,6 +17366,28 @@
   }, 
   {
     "args": [
+      "filter_call_init_fails"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_ssl_cert_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "filter_causes_close"
     ], 
     "ci_platforms": [
@@ -17876,6 +18234,27 @@
   }, 
   {
     "args": [
+      "filter_call_init_fails"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_ssl_proxy_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "filter_causes_close"
     ], 
     "ci_platforms": [
@@ -18619,6 +18998,26 @@
   }, 
   {
     "args": [
+      "filter_call_init_fails"
+    ], 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_uds_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "filter_causes_close"
     ], 
     "ci_platforms": [
@@ -19445,6 +19844,28 @@
   }, 
   {
     "args": [
+      "filter_call_init_fails"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_census_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "filter_causes_close"
     ], 
     "ci_platforms": [
@@ -20325,6 +20746,28 @@
   }, 
   {
     "args": [
+      "filter_call_init_fails"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_compress_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "filter_causes_close"
     ], 
     "ci_platforms": [
@@ -21119,6 +21562,26 @@
   }, 
   {
     "args": [
+      "filter_call_init_fails"
+    ], 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_fd_nosec_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "filter_causes_close"
     ], 
     "ci_platforms": [
@@ -21905,6 +22368,28 @@
   }, 
   {
     "args": [
+      "filter_call_init_fails"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "filter_causes_close"
     ], 
     "ci_platforms": [
@@ -22707,6 +23192,22 @@
   }, 
   {
     "args": [
+      "filter_call_init_fails"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full+pipe_nosec_test", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
       "filter_causes_close"
     ], 
     "ci_platforms": [
@@ -23425,6 +23926,28 @@
   }, 
   {
     "args": [
+      "filter_call_init_fails"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full+trace_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "filter_causes_close"
     ], 
     "ci_platforms": [
@@ -24270,6 +24793,27 @@
   }, 
   {
     "args": [
+      "filter_call_init_fails"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_http_proxy_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "filter_causes_close"
     ], 
     "ci_platforms": [
@@ -25123,6 +25667,28 @@
   }, 
   {
     "args": [
+      "filter_call_init_fails"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_load_reporting_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "filter_causes_close"
     ], 
     "ci_platforms": [
@@ -25948,6 +26514,27 @@
   }, 
   {
     "args": [
+      "filter_call_init_fails"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_proxy_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "filter_causes_close"
     ], 
     "ci_platforms": [
@@ -26641,6 +27228,27 @@
   }, 
   {
     "args": [
+      "filter_call_init_fails"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_sockpair_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "filter_causes_close"
     ], 
     "ci_platforms": [
@@ -27376,6 +27984,27 @@
   }, 
   {
     "args": [
+      "filter_call_init_fails"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_sockpair+trace_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "filter_causes_close"
     ], 
     "ci_platforms": [
@@ -28110,6 +28739,29 @@
   }, 
   {
     "args": [
+      "filter_call_init_fails"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [
+      "msan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_sockpair_1byte_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "filter_causes_close"
     ], 
     "ci_platforms": [
@@ -28925,6 +29577,26 @@
   }, 
   {
     "args": [
+      "filter_call_init_fails"
+    ], 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_uds_nosec_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "filter_causes_close"
     ], 
     "ci_platforms": [
diff --git a/vsprojects/buildtests_c.sln b/vsprojects/buildtests_c.sln
index aa1eb2b..13a6bdc 100644
--- a/vsprojects/buildtests_c.sln
+++ b/vsprojects/buildtests_c.sln
@@ -109,6 +109,17 @@
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "census_resource_test", "vcxproj\test\census_resource_test\census_resource_test.vcxproj", "{18CF99B5-3C61-EC3D-9509-3C95334C3B88}"
+	ProjectSection(myProperties) = preProject
+        	lib = "False"
+	EndProjectSection
+	ProjectSection(ProjectDependencies) = postProject
+		{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}
+		{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
+		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
+		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
+	EndProjectSection
+EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "channel_create_test", "vcxproj\test\channel_create_test\channel_create_test.vcxproj", "{AFC88484-3A2E-32BC-25B2-23DF741D4F3D}"
 	ProjectSection(myProperties) = preProject
         	lib = "False"
@@ -1623,6 +1634,22 @@
 		{5C1CFC2D-AF3C-D7CB-BA74-D267E91CBC73}.Release-DLL|Win32.Build.0 = Release|Win32
 		{5C1CFC2D-AF3C-D7CB-BA74-D267E91CBC73}.Release-DLL|x64.ActiveCfg = Release|x64
 		{5C1CFC2D-AF3C-D7CB-BA74-D267E91CBC73}.Release-DLL|x64.Build.0 = Release|x64
+		{18CF99B5-3C61-EC3D-9509-3C95334C3B88}.Debug|Win32.ActiveCfg = Debug|Win32
+		{18CF99B5-3C61-EC3D-9509-3C95334C3B88}.Debug|x64.ActiveCfg = Debug|x64
+		{18CF99B5-3C61-EC3D-9509-3C95334C3B88}.Release|Win32.ActiveCfg = Release|Win32
+		{18CF99B5-3C61-EC3D-9509-3C95334C3B88}.Release|x64.ActiveCfg = Release|x64
+		{18CF99B5-3C61-EC3D-9509-3C95334C3B88}.Debug|Win32.Build.0 = Debug|Win32
+		{18CF99B5-3C61-EC3D-9509-3C95334C3B88}.Debug|x64.Build.0 = Debug|x64
+		{18CF99B5-3C61-EC3D-9509-3C95334C3B88}.Release|Win32.Build.0 = Release|Win32
+		{18CF99B5-3C61-EC3D-9509-3C95334C3B88}.Release|x64.Build.0 = Release|x64
+		{18CF99B5-3C61-EC3D-9509-3C95334C3B88}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
+		{18CF99B5-3C61-EC3D-9509-3C95334C3B88}.Debug-DLL|Win32.Build.0 = Debug|Win32
+		{18CF99B5-3C61-EC3D-9509-3C95334C3B88}.Debug-DLL|x64.ActiveCfg = Debug|x64
+		{18CF99B5-3C61-EC3D-9509-3C95334C3B88}.Debug-DLL|x64.Build.0 = Debug|x64
+		{18CF99B5-3C61-EC3D-9509-3C95334C3B88}.Release-DLL|Win32.ActiveCfg = Release|Win32
+		{18CF99B5-3C61-EC3D-9509-3C95334C3B88}.Release-DLL|Win32.Build.0 = Release|Win32
+		{18CF99B5-3C61-EC3D-9509-3C95334C3B88}.Release-DLL|x64.ActiveCfg = Release|x64
+		{18CF99B5-3C61-EC3D-9509-3C95334C3B88}.Release-DLL|x64.Build.0 = Release|x64
 		{AFC88484-3A2E-32BC-25B2-23DF741D4F3D}.Debug|Win32.ActiveCfg = Debug|Win32
 		{AFC88484-3A2E-32BC-25B2-23DF741D4F3D}.Debug|x64.ActiveCfg = Debug|x64
 		{AFC88484-3A2E-32BC-25B2-23DF741D4F3D}.Release|Win32.ActiveCfg = Release|Win32
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj
index 715664d..a2d9b85 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj
@@ -451,11 +451,13 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\load_reporting\load_reporting.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\load_reporting\load_reporting_filter.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\aggregation.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\base_resources.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\census_interface.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\census_rpc_stats.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\gen\census.pb.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\grpc_filter.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\mlog.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\resource.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\rpc_metric_id.h" />
   </ItemGroup>
   <ItemGroup>
@@ -815,6 +817,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\load_reporting\load_reporting_filter.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\base_resources.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\context.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\gen\census.pb.c">
@@ -833,6 +837,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\placeholders.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\resource.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\tracing.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\plugin_registry\grpc_plugin_registry.c">
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
index a22bd23..0ea4313 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
@@ -535,6 +535,9 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\load_reporting\load_reporting_filter.c">
       <Filter>src\core\ext\load_reporting</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\base_resources.c">
+      <Filter>src\core\ext\census</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\context.c">
       <Filter>src\core\ext\census</Filter>
     </ClCompile>
@@ -562,6 +565,9 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\placeholders.c">
       <Filter>src\core\ext\census</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\resource.c">
+      <Filter>src\core\ext\census</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\tracing.c">
       <Filter>src\core\ext\census</Filter>
     </ClCompile>
@@ -1118,6 +1124,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\aggregation.h">
       <Filter>src\core\ext\census</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\base_resources.h">
+      <Filter>src\core\ext\census</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\census_interface.h">
       <Filter>src\core\ext\census</Filter>
     </ClInclude>
@@ -1133,6 +1142,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\mlog.h">
       <Filter>src\core\ext\census</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\resource.h">
+      <Filter>src\core\ext\census</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\rpc_metric_id.h">
       <Filter>src\core\ext\census</Filter>
     </ClInclude>
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
index 0f40e9e..3bbd4b7 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
@@ -416,11 +416,13 @@
     <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_decode.h" />
     <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_encode.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\aggregation.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\base_resources.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\census_interface.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\census_rpc_stats.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\gen\census.pb.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\grpc_filter.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\mlog.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\resource.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\rpc_metric_id.h" />
   </ItemGroup>
   <ItemGroup>
@@ -722,6 +724,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\round_robin\round_robin.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\base_resources.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\context.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\gen\census.pb.c">
@@ -740,6 +744,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\placeholders.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\resource.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\tracing.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\plugin_registry\grpc_unsecure_plugin_registry.c">
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
index eb1b707..16ba3a7 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
@@ -448,6 +448,9 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\round_robin\round_robin.c">
       <Filter>src\core\ext\lb_policy\round_robin</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\base_resources.c">
+      <Filter>src\core\ext\census</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\context.c">
       <Filter>src\core\ext\census</Filter>
     </ClCompile>
@@ -475,6 +478,9 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\placeholders.c">
       <Filter>src\core\ext\census</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\resource.c">
+      <Filter>src\core\ext\census</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\tracing.c">
       <Filter>src\core\ext\census</Filter>
     </ClCompile>
@@ -953,6 +959,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\aggregation.h">
       <Filter>src\core\ext\census</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\base_resources.h">
+      <Filter>src\core\ext\census</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\census_interface.h">
       <Filter>src\core\ext\census</Filter>
     </ClInclude>
@@ -968,6 +977,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\mlog.h">
       <Filter>src\core\ext\census</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\resource.h">
+      <Filter>src\core\ext\census</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\rpc_metric_id.h">
       <Filter>src\core\ext\census</Filter>
     </ClInclude>
diff --git a/vsprojects/vcxproj/test/census_resource_test/census_resource_test.vcxproj b/vsprojects/vcxproj/test/census_resource_test/census_resource_test.vcxproj
new file mode 100644
index 0000000..c4fbd54
--- /dev/null
+++ b/vsprojects/vcxproj/test/census_resource_test/census_resource_test.vcxproj
@@ -0,0 +1,199 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{18CF99B5-3C61-EC3D-9509-3C95334C3B88}</ProjectGuid>
+    <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
+    <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>census_resource_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>census_resource_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\core\census\resource_test.c">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
+      <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
+      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/census_resource_test/census_resource_test.vcxproj.filters b/vsprojects/vcxproj/test/census_resource_test/census_resource_test.vcxproj.filters
new file mode 100644
index 0000000..93faac5
--- /dev/null
+++ b/vsprojects/vcxproj/test/census_resource_test/census_resource_test.vcxproj.filters
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\core\census\resource_test.c">
+      <Filter>test\core\census</Filter>
+    </ClCompile>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Filter Include="test">
+      <UniqueIdentifier>{313aad4e-d33b-88c5-7d94-e04a4cb0c912}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core">
+      <UniqueIdentifier>{ff2d74ef-228a-1739-7fa7-7dccbec5b0c5}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core\census">
+      <UniqueIdentifier>{4f529bd9-396f-027c-bc49-f9a6bbc97c72}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj b/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj
index fc1068f..a500fe3 100644
--- a/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj
+++ b/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj
@@ -179,6 +179,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\empty_batch.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\filter_call_init_fails.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\filter_causes_close.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\graceful_server_shutdown.c">
diff --git a/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj.filters b/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj.filters
index de8c0dd..6f2294c 100644
--- a/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj.filters
+++ b/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj.filters
@@ -43,6 +43,9 @@
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\empty_batch.c">
       <Filter>test\core\end2end\tests</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\filter_call_init_fails.c">
+      <Filter>test\core\end2end\tests</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\filter_causes_close.c">
       <Filter>test\core\end2end\tests</Filter>
     </ClCompile>
diff --git a/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj b/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj
index a902bb4..7614089 100644
--- a/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj
+++ b/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj
@@ -181,6 +181,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\empty_batch.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\filter_call_init_fails.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\filter_causes_close.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\graceful_server_shutdown.c">
diff --git a/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj.filters b/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj.filters
index 522f73d..db336f0 100644
--- a/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj.filters
+++ b/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj.filters
@@ -46,6 +46,9 @@
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\empty_batch.c">
       <Filter>test\core\end2end\tests</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\filter_call_init_fails.c">
+      <Filter>test\core\end2end\tests</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\filter_causes_close.c">
       <Filter>test\core\end2end\tests</Filter>
     </ClCompile>