initial implementation of resource handling
diff --git a/BUILD b/BUILD
index 024a518..b3b75ed 100644
--- a/BUILD
+++ b/BUILD
@@ -299,11 +299,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/channel/channel_args.c",
@@ -469,6 +471,7 @@
     "src/core/ext/lb_policy/round_robin/round_robin.c",
     "src/core/ext/resolver/dns/native/dns_resolver.c",
     "src/core/ext/resolver/sockaddr/sockaddr_resolver.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",
@@ -478,6 +481,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",
   ],
@@ -647,11 +651,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",
@@ -786,6 +792,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",
@@ -795,6 +802,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",
   ],
@@ -1512,6 +1520,7 @@
     "src/core/ext/lb_policy/round_robin/round_robin.c",
     "src/core/ext/resolver/dns/native/dns_resolver.c",
     "src/core/ext/resolver/sockaddr/sockaddr_resolver.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",
@@ -1521,6 +1530,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",
   ],
@@ -1693,11 +1703,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",
   ],
   includes = [
diff --git a/Makefile b/Makefile
index 98f6e56..34daedc 100644
--- a/Makefile
+++ b/Makefile
@@ -891,6 +891,7 @@
 api_fuzzer: $(BINDIR)/$(CONFIG)/api_fuzzer
 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
@@ -1223,6 +1224,7 @@
   $(BINDIR)/$(CONFIG)/alpn_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 \
@@ -1475,6 +1477,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"
@@ -2637,6 +2641,7 @@
     src/core/ext/lb_policy/round_robin/round_robin.c \
     src/core/ext/resolver/dns/native/dns_resolver.c \
     src/core/ext/resolver/sockaddr/sockaddr_resolver.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 \
@@ -2646,6 +2651,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 \
 
@@ -2961,6 +2967,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 \
@@ -2970,6 +2977,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 \
 
@@ -6195,6 +6203,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 1e8b5e2..cc8077d 100644
--- a/binding.gyp
+++ b/binding.gyp
@@ -730,6 +730,7 @@
         'src/core/ext/lb_policy/round_robin/round_robin.c',
         'src/core/ext/resolver/dns/native/dns_resolver.c',
         'src/core/ext/resolver/sockaddr/sockaddr_resolver.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',
@@ -739,6 +740,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 f211575..0d192ee 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:
@@ -1192,6 +1196,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 e8506bb..b8a8429 100644
--- a/config.m4
+++ b/config.m4
@@ -249,6 +249,7 @@
     src/core/ext/lb_policy/round_robin/round_robin.c \
     src/core/ext/resolver/dns/native/dns_resolver.c \
     src/core/ext/resolver/sockaddr/sockaddr_resolver.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 \
@@ -258,6 +259,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.podspec b/gRPC.podspec
index 9c049f0..8187b40 100644
--- a/gRPC.podspec
+++ b/gRPC.podspec
@@ -306,11 +306,13 @@
                       'third_party/nanopb/pb_decode.h',
                       'third_party/nanopb/pb_encode.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',
                       'include/grpc/byte_buffer.h',
                       'include/grpc/byte_buffer_reader.h',
@@ -509,6 +511,7 @@
                       'src/core/ext/lb_policy/round_robin/round_robin.c',
                       'src/core/ext/resolver/dns/native/dns_resolver.c',
                       'src/core/ext/resolver/sockaddr/sockaddr_resolver.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',
@@ -518,6 +521,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'
 
@@ -675,11 +679,13 @@
                               'third_party/nanopb/pb_decode.h',
                               'third_party/nanopb/pb_encode.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'
 
     ss.header_mappings_dir = '.'
diff --git a/grpc.def b/grpc.def
index b811f0f..f69370a 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 047845c..acb23bd 100755
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -315,11 +315,13 @@
   s.files += %w( third_party/nanopb/pb_decode.h )
   s.files += %w( third_party/nanopb/pb_encode.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 )
@@ -488,6 +490,7 @@
   s.files += %w( src/core/ext/lb_policy/round_robin/round_robin.c )
   s.files += %w( src/core/ext/resolver/dns/native/dns_resolver.c )
   s.files += %w( src/core/ext/resolver/sockaddr/sockaddr_resolver.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 )
@@ -497,6 +500,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/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 6f6b8dd..575b743 100644
--- a/package.xml
+++ b/package.xml
@@ -322,11 +322,13 @@
     <file baseinstalldir="/" name="third_party/nanopb/pb_decode.h" role="src" />
     <file baseinstalldir="/" name="third_party/nanopb/pb_encode.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" />
@@ -495,6 +497,7 @@
     <file baseinstalldir="/" name="src/core/ext/lb_policy/round_robin/round_robin.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/resolver/dns/native/dns_resolver.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/resolver/sockaddr/sockaddr_resolver.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" />
@@ -504,6 +507,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..8f0329a
--- /dev/null
+++ b/src/core/ext/census/base_resources.c
@@ -0,0 +1,148 @@
+/*
+ * 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 <stdio.h>
+#include <string.h>
+
+#include <grpc/census.h>
+#include <grpc/support/log.h>
+
+#include "base_resources.h"
+#include "gen/census.pb.h"
+#include "third_party/nanopb/pb_encode.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.
+
+// Structure representing a MeasurementUnit proto.
+typedef struct {
+  int32_t prefix;
+  int n_numerators;
+  const google_census_Resource_BasicUnit *numerators;
+  int n_denominators;
+  const google_census_Resource_BasicUnit *denominators;
+} measurement_unit;
+
+// Encode a nanopb string. Expects the string argument to be passed in as `arg`.
+static bool encode_string(pb_ostream_t *stream, const pb_field_t *field,
+                          void *const *arg) {
+  if (!pb_encode_tag_for_field(stream, field)) {
+    return false;
+  }
+  return pb_encode_string(stream, (uint8_t *)*arg, strlen((const char *)*arg));
+}
+
+// Encode the numerators part of a measurement_unit (passed in as `arg`).
+static bool encode_numerators(pb_ostream_t *stream, const pb_field_t *field,
+                              void *const *arg) {
+  const measurement_unit *mu = (const measurement_unit *)*arg;
+  for (int i = 0; i < mu->n_numerators; i++) {
+    if (!pb_encode_tag_for_field(stream, field)) {
+      return false;
+    }
+    if (!pb_encode_varint(stream, mu->numerators[i])) {
+      return false;
+    }
+  }
+  return true;
+}
+
+// Encode the denominators part of a measurement_unit (passed in as `arg`).
+static bool encode_denominators(pb_ostream_t *stream, const pb_field_t *field,
+                                void *const *arg) {
+  const measurement_unit *mu = (const measurement_unit *)*arg;
+  for (int i = 0; i < mu->n_denominators; i++) {
+    if (!pb_encode_tag_for_field(stream, field)) {
+      return false;
+    }
+    if (!pb_encode_varint(stream, mu->numerators[i])) {
+      return false;
+    }
+  }
+  return true;
+}
+
+// Define a Resource, given the important details. Encodes a protobuf, which
+// is then passed to census_define_resource.
+static void define_resource(const char *name, const char *description,
+                            const measurement_unit *unit) {
+  // nanopb generated type for Resource. Initialize encoding functions to NULL
+  // since we can't directly initialize them due to embedded union in struct.
+  google_census_Resource resource = {
+      {{NULL}, (void *)name},
+      {{NULL}, (void *)description},
+      true,  // has_unit
+      {true, unit->prefix, {{NULL}, (void *)unit}, {{NULL}, (void *)unit}}};
+  resource.name.funcs.encode = &encode_string;
+  resource.description.funcs.encode = &encode_string;
+  resource.unit.numerator.funcs.encode = &encode_numerators;
+  resource.unit.denominator.funcs.encode = &encode_denominators;
+
+  // Buffer for storing encoded proto.
+  uint8_t buffer[512];
+  pb_ostream_t stream = pb_ostream_from_buffer(buffer, 512);
+  if (!pb_encode(&stream, google_census_Resource_fields, &resource)) {
+    gpr_log(GPR_ERROR, "Error encoding resource %s.", name);
+    return;
+  }
+  int32_t mid = census_define_resource(buffer, stream.bytes_written);
+  if (mid < 0) {
+    gpr_log(GPR_ERROR, "Error defining resource %s.", name);
+  }
+}
+
+// Define a resource for client RPC latency.
+static void define_client_rpc_latency_resource() {
+  google_census_Resource_BasicUnit numerator =
+      google_census_Resource_BasicUnit_SECS;
+  measurement_unit unit = {0, 1, &numerator, 0, NULL};
+  define_resource("client_rpc_latency", "Client RPC latency in seconds", &unit);
+}
+
+// Define a resource for server RPC latency.
+static void define_server_rpc_latency_resource() {
+  google_census_Resource_BasicUnit numerator =
+      google_census_Resource_BasicUnit_SECS;
+  measurement_unit unit = {0, 1, &numerator, 0, NULL};
+  define_resource("server_rpc_latency", "Server RPC latency in seconds", &unit);
+}
+
+// Define all base resources. This should be called by census initialization.
+void define_base_resources() {
+  define_client_rpc_latency_resource();
+  define_server_rpc_latency_resource();
+}
diff --git a/src/core/ext/census/base_resources.h b/src/core/ext/census/base_resources.h
new file mode 100644
index 0000000..992e5f6
--- /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/initialize.c b/src/core/ext/census/initialize.c
index 896276e..1181635 100644
--- a/src/core/ext/census/initialize.c
+++ b/src/core/ext/census/initialize.c
@@ -32,19 +32,31 @@
  */
 
 #include <grpc/census.h>
+#include "base_resources.h"
+#include "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..632b899
--- /dev/null
+++ b/src/core/ext/census/resource.c
@@ -0,0 +1,255 @@
+/*
+ *
+ * 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 "resource.h"
+#include "gen/census.pb.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>
+
+// Internal representation of a resource.
+typedef struct {
+  char *name;
+  // Pointer to raw protobuf used in resource definition.
+  uint8_t *raw_pb;
+} resource;
+
+// 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() {
+  gpr_mu_init(&resource_lock);
+  gpr_mu_lock(&resource_lock);
+  GPR_ASSERT(resources == NULL && n_resources == 0 && n_defined_resources == 0);
+  // 8 seems like a reasonable size for initial number of resources.
+  n_resources = 8;
+  resources = gpr_malloc(n_resources * sizeof(resource *));
+  memset(resources, 0, n_resources * sizeof(resource *));
+  gpr_mu_unlock(&resource_lock);
+}
+
+// Delete a resource given it's ID. Must be called with resource_lock held.
+static void delete_resource_locked(size_t rid) {
+  GPR_ASSERT(resources[rid] != NULL && resources[rid]->raw_pb != NULL &&
+             resources[rid]->name != NULL && n_defined_resources > 0);
+  gpr_free(resources[rid]->name);
+  gpr_free(resources[rid]->raw_pb);
+  gpr_free(resources[rid]);
+  resources[rid] = NULL;
+  n_defined_resources--;
+}
+
+void shutdown_resources() {
+  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:
+      // Description is optional, does not need validating, just skip.
+      if (!pb_read(stream, NULL, 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;
+}
+
+// Validate units field of a Resource proto.
+static bool validate_units(pb_istream_t *stream, const pb_field_t *field,
+                           void **arg) {
+  if (field->tag == google_census_Resource_MeasurementUnit_numerator_tag) {
+    *(bool *)*arg = true;  // has_numerator = true.
+  }
+  while (stream->bytes_left) {
+    uint64_t value;
+    if (!pb_decode_varint(stream, &value)) {
+      return false;
+    }
+  }
+  return true;
+}
+
+// Vlaidate 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.unit.numerator.funcs.decode = &validate_units;
+  bool has_numerator = false;
+  vresource.unit.numerator.arg = &has_numerator;
+  vresource.unit.denominator.funcs.decode = &validate_units;
+
+  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 && has_numerator);
+}
+
+int32_t census_define_resource(const uint8_t *resource_pb,
+                               size_t resource_pb_size) {
+  // use next_id to optimize expected placement of next new resource.
+  static size_t next_id = 0;
+  if (resource_pb == NULL) {
+    return -1;
+  }
+  gpr_mu_lock(&resource_lock);
+  size_t id = n_resources;  // resource ID - initialize to invalid value.
+  // Expand resources if needed.
+  if (n_resources == n_defined_resources) {
+    resource **new_resources = gpr_malloc(n_resources * 2 * sizeof(resource *));
+    memcpy(new_resources, resources, n_resources * sizeof(resource *));
+    memset(new_resources + n_resources, 0, n_resources * sizeof(resource *));
+    gpr_free(resources);
+    resources = new_resources;
+    n_resources *= 2;
+    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));
+  resources[id]->name = NULL;
+  // Validate pb, extract name.
+  if (!validate_resource_pb(resource_pb, resource_pb_size, id)) {
+    if (resources[id]->name != NULL) {
+      gpr_free(resources[id]->name);
+    }
+    gpr_free(resources[id]);
+    resources[id] = NULL;
+    gpr_mu_unlock(&resource_lock);
+    return -1;
+  }
+  next_id = (id + 1) % n_resources;
+  // Make copy of raw proto, and return.
+  resources[id]->raw_pb = gpr_malloc(resource_pb_size);
+  memcpy(resources[id]->raw_pb, resource_pb, resource_pb_size);
+  n_defined_resources++;
+  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) {
+      if (strcmp(resources[id]->name, name) == 0) {
+        gpr_mu_unlock(&resource_lock);
+        return id;
+      }
+    }
+  }
+  gpr_mu_unlock(&resource_lock);
+  return -1;
+}
diff --git a/src/core/ext/census/resource.h b/src/core/ext/census/resource.h
new file mode 100644
index 0000000..5ad5a0f
--- /dev/null
+++ b/src/core/ext/census/resource.h
@@ -0,0 +1,42 @@
+/*
+ *
+ * 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
+
+// Initialize and shutdown the resources subsystem.
+void initialize_resources();
+void shutdown_resources();
+
+#endif /* GRPC_CORE_EXT_CENSUS_RESOURCE_H */
diff --git a/src/python/grpcio/grpc/_cython/imports.generated.c b/src/python/grpcio/grpc/_cython/imports.generated.c
index f71cf12..29ada16 100644
--- a/src/python/grpcio/grpc/_cython/imports.generated.c
+++ b/src/python/grpcio/grpc/_cython/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;
@@ -333,15 +328,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/python/grpcio/grpc/_cython/imports.generated.h b/src/python/grpcio/grpc/_cython/imports.generated.h
index a364075..f6dd79c 100644
--- a/src/python/grpcio/grpc/_cython/imports.generated.h
+++ b/src/python/grpcio/grpc/_cython/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/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index d0f23f4..c7d042d 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -243,6 +243,7 @@
   'src/core/ext/lb_policy/round_robin/round_robin.c',
   'src/core/ext/resolver/dns/native/dns_resolver.c',
   'src/core/ext/resolver/sockaddr/sockaddr_resolver.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',
@@ -252,6 +253,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 3b62984..5d0f565 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;
@@ -329,15 +324,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 1428e6d..4033e5e 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..bfb76bc
--- /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) {
+  const size_t buf_size = 512;
+  uint8_t buffer[buf_size];
+  FILE *input = fopen(file, "r");
+  GPR_ASSERT(input != NULL);
+  size_t nbytes = fread(buffer, 1, buf_size, input);
+  GPR_ASSERT(nbytes != 0 && nbytes < buf_size);
+  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/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index 7446fec..51007a5 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -932,11 +932,13 @@
 third_party/nanopb/pb_decode.h \
 third_party/nanopb/pb_encode.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 \
@@ -1105,6 +1107,7 @@
 src/core/ext/lb_policy/round_robin/round_robin.c \
 src/core/ext/resolver/dns/native/dns_resolver.c \
 src/core/ext/resolver/sockaddr/sockaddr_resolver.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 \
@@ -1114,6 +1117,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 e047123..28f54e7 100644
--- a/tools/run_tests/sources_and_headers.json
+++ b/tools/run_tests/sources_and_headers.json
@@ -118,6 +118,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"
@@ -5296,11 +5312,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", 
@@ -5308,6 +5326,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", 
@@ -5322,6 +5342,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 850f947..a1946d2 100644
--- a/tools/run_tests/tests.json
+++ b/tools/run_tests/tests.json
@@ -140,6 +140,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", 
diff --git a/vsprojects/buildtests_c.sln b/vsprojects/buildtests_c.sln
index be8b5d4..d94a435 100644
--- a/vsprojects/buildtests_c.sln
+++ b/vsprojects/buildtests_c.sln
@@ -180,6 +180,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"
@@ -1707,6 +1718,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 61a59e7..d5ac625 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj
@@ -441,11 +441,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>
@@ -783,6 +785,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\resolver\sockaddr\sockaddr_resolver.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">
@@ -801,6 +805,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 4bd436a..37b1f09 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
@@ -502,6 +502,9 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\resolver\sockaddr\sockaddr_resolver.c">
       <Filter>src\core\ext\resolver\sockaddr</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>
@@ -529,6 +532,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>
@@ -1055,6 +1061,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>
@@ -1070,6 +1079,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 e29a275..5bb2614 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
@@ -405,11 +405,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>
@@ -685,6 +687,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">
@@ -703,6 +707,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 e5e4acc..3616227 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
@@ -409,6 +409,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>
@@ -436,6 +439,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>
@@ -881,6 +887,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>
@@ -896,6 +905,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>
+