You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kudu.apache.org by gr...@apache.org on 2019/11/14 18:57:51 UTC

[kudu] branch master updated: [metrics] Add metric severity level

This is an automated email from the ASF dual-hosted git repository.

granthenke pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/kudu.git


The following commit(s) were added to refs/heads/master by this push:
     new 9a418e8  [metrics] Add metric severity level
9a418e8 is described below

commit 9a418e8497466fc3d6bf66eec84cc268ab725581
Author: Grant Henke <gr...@apache.org>
AuthorDate: Mon Nov 4 15:52:13 2019 -0600

    [metrics] Add metric severity level
    
    Kudu has somewhere around 200 metrics defined for the server and
    tablet entities. The result is a lot of useful information. However, it is also
    difficult to view and understand which metrics are important. Additionally,
    as the tablet count grows within the cluster, the tablet level metrics may
    overwhelm users and some metric collection tools.
    
    Kudu already has the ability to filter metrics by type, attribute, name, etc.
    This patch adds the additional capability to filter by metric “severity level”.
    
    In order to do this, this patch introduces three metric severity levels:
    debug, info, and warn. These levels are defined similar to logging
    severity levels. See the `MetricLevel` documentation in `metrics.h` for
    a more detailed definition of each level.
    
    This patch takes a quick first pass at setting metric levels, over time
    the level of metrics can be adjusted based on their demand.
    
    Some quick testing on a tablet server with 3777 live tablet replicas shows
    a drastic reduction in size:
    - Debug: 58.2 MB
    - Info:      29.7 MB
    - Warn:    3.3 MB
    
    With `compact=true`:
    - Debug: 26.2 MB
    - Info:      13.6 MB
    - Warn:    1.8 MB
    
    Change-Id: I5aa7d2323bb75700104c348a3ae859fc449e1715
    Reviewed-on: http://gerrit.cloudera.org:8080/14630
    Tested-by: Kudu Jenkins
    Reviewed-by: Adar Dembo <ad...@cloudera.com>
---
 docs/administration.adoc                           |   9 ++
 src/kudu/clock/hybrid_clock.cc                     |   6 +-
 src/kudu/clock/logical_clock.cc                    |   4 +-
 src/kudu/clock/logical_clock.h                     |   1 -
 src/kudu/codegen/compilation_manager.cc            |   2 +
 src/kudu/consensus/consensus_queue.cc              |   9 +-
 src/kudu/consensus/log_cache.cc                    |   6 +-
 src/kudu/consensus/log_metrics.cc                  |   8 +-
 src/kudu/consensus/log_reader.cc                   |   7 +-
 src/kudu/consensus/raft_consensus.cc               |  12 +-
 src/kudu/fs/block_manager_metrics.cc               |  27 ++--
 src/kudu/fs/data_dirs.cc                           |   6 +-
 src/kudu/fs/log_block_manager.cc                   |  18 ++-
 src/kudu/kserver/kserver.cc                        |   4 +
 src/kudu/kserver/kserver.h                         |   1 +
 src/kudu/master/location_cache.cc                  |   6 +-
 src/kudu/master/sentry_client_metrics.cc           |  16 ++-
 src/kudu/master/sentry_privileges_cache_metrics.cc |  24 ++--
 src/kudu/master/table_metrics.cc                   |   6 +-
 src/kudu/master/ts_manager.cc                      |   3 +-
 src/kudu/rpc/acceptor_pool.cc                      |   3 +-
 src/kudu/rpc/protoc-gen-krpc.cc                    |   1 +
 src/kudu/rpc/reactor.cc                            |   5 +-
 src/kudu/rpc/service_pool.cc                       |   8 +-
 src/kudu/server/default_path_handlers.cc           |   3 +-
 src/kudu/server/glog_metrics.cc                    |   9 +-
 src/kudu/server/tcmalloc_metrics.cc                |  18 ++-
 src/kudu/tablet/tablet.cc                          |   9 +-
 src/kudu/tablet/tablet_metrics.cc                  | 137 ++++++++++++++-------
 src/kudu/tablet/tablet_replica.cc                  |  12 +-
 src/kudu/tablet/tablet_replica_mm_ops.cc           |   7 +-
 .../tablet/transactions/transaction_tracker.cc     |  12 +-
 src/kudu/tserver/scanner_metrics.cc                |   4 +-
 src/kudu/tserver/scanners.cc                       |   3 +-
 src/kudu/tserver/tablet_copy_client.cc             |   6 +-
 src/kudu/tserver/tablet_copy_source_session.cc     |   6 +-
 src/kudu/tserver/tablet_server-stress-test.cc      |   1 +
 src/kudu/tserver/tablet_server-test.cc             |   1 +
 src/kudu/tserver/ts_tablet_manager.cc              |  24 ++--
 src/kudu/util/block_cache_metrics.cc               |  24 ++--
 src/kudu/util/file_cache_metrics.cc                |  24 ++--
 src/kudu/util/maintenance_manager-test.cc          |   7 +-
 src/kudu/util/metrics-test.cc                      |  76 ++++++++++--
 src/kudu/util/metrics.cc                           |  70 ++++++++++-
 src/kudu/util/metrics.h                            |  77 ++++++++----
 src/kudu/util/mt-metrics-test.cc                   |   6 +-
 src/kudu/util/spinlock_profiling.cc                |   1 +
 src/kudu/util/thread.cc                            |   8 +-
 src/kudu/util/threadpool-test.cc                   |  12 +-
 src/kudu/util/ttl_cache_test_metrics.cc            |  24 ++--
 50 files changed, 565 insertions(+), 208 deletions(-)

diff --git a/docs/administration.adoc b/docs/administration.adoc
index dba50e0..2827235 100644
--- a/docs/administration.adoc
+++ b/docs/administration.adoc
@@ -108,6 +108,15 @@ bandwidth when fetching this page from a remote host.
 - `/metrics?include_raw_histograms=1` - include the raw buckets and values for histogram metrics,
 enabling accurate aggregation of percentile metrics over time and across hosts.
 
+- `/metrics?level=info` - limits the returned metrics based on their severity level.
+The levels are ordered and lower levels include the levels above them. If no level is specified,
+`debug` is used to include all metrics. The valid values are:
+   * `debug` - Metrics that are diagnostically helpful but generally not monitored
+               during normal operation.
+   * `info` - Generally useful metrics that operators always want to have available
+              but may not be monitored under normal circumstances.
+   * `warn` - Metrics which can often indicate operational oddities, which may need more investigation.
+
 For example:
 
 [source,bash]
diff --git a/src/kudu/clock/hybrid_clock.cc b/src/kudu/clock/hybrid_clock.cc
index 99ea277..b15bc2a 100644
--- a/src/kudu/clock/hybrid_clock.cc
+++ b/src/kudu/clock/hybrid_clock.cc
@@ -87,11 +87,13 @@ TAG_FLAG(ntp_initial_sync_wait_secs, evolving);
 METRIC_DEFINE_gauge_uint64(server, hybrid_clock_timestamp,
                            "Hybrid Clock Timestamp",
                            kudu::MetricUnit::kMicroseconds,
-                           "Hybrid clock timestamp.");
+                           "Hybrid clock timestamp.",
+                           kudu::MetricLevel::kInfo);
 METRIC_DEFINE_gauge_uint64(server, hybrid_clock_error,
                            "Hybrid Clock Error",
                            kudu::MetricUnit::kMicroseconds,
-                           "Server clock maximum error.");
+                           "Server clock maximum error.",
+                           kudu::MetricLevel::kInfo);
 
 namespace kudu {
 namespace clock {
diff --git a/src/kudu/clock/logical_clock.cc b/src/kudu/clock/logical_clock.cc
index 30c74aa..4e81bcf 100644
--- a/src/kudu/clock/logical_clock.cc
+++ b/src/kudu/clock/logical_clock.cc
@@ -25,6 +25,7 @@
 #include "kudu/gutil/atomicops.h"
 #include "kudu/gutil/bind.h"
 #include "kudu/gutil/bind_helpers.h"
+#include "kudu/gutil/port.h"
 #include "kudu/gutil/strings/substitute.h"
 #include "kudu/util/metrics.h"
 #include "kudu/util/status.h"
@@ -35,7 +36,8 @@ namespace clock {
 METRIC_DEFINE_gauge_uint64(server, logical_clock_timestamp,
                            "Logical Clock Timestamp",
                            kudu::MetricUnit::kUnits,
-                           "Logical clock timestamp.");
+                           "Logical clock timestamp.",
+                           kudu::MetricLevel::kInfo);
 
 using base::subtle::Atomic64;
 using base::subtle::Barrier_AtomicIncrement;
diff --git a/src/kudu/clock/logical_clock.h b/src/kudu/clock/logical_clock.h
index e4da536..091f617 100644
--- a/src/kudu/clock/logical_clock.h
+++ b/src/kudu/clock/logical_clock.h
@@ -23,7 +23,6 @@
 #include "kudu/common/common.pb.h"
 #include "kudu/common/timestamp.h"
 #include "kudu/gutil/atomicops.h"
-#include "kudu/gutil/port.h"
 #include "kudu/gutil/ref_counted.h"
 #include "kudu/util/metrics.h"
 #include "kudu/util/status.h"
diff --git a/src/kudu/codegen/compilation_manager.cc b/src/kudu/codegen/compilation_manager.cc
index 30719b4..51263d6 100644
--- a/src/kudu/codegen/compilation_manager.cc
+++ b/src/kudu/codegen/compilation_manager.cc
@@ -59,11 +59,13 @@ TAG_FLAG(codegen_cache_capacity, experimental);
 METRIC_DEFINE_gauge_int64(server, code_cache_hits, "Codegen Cache Hits",
                           kudu::MetricUnit::kCacheHits,
                           "Number of codegen cache hits since start",
+                          kudu::MetricLevel::kDebug,
                           kudu::EXPOSE_AS_COUNTER);
 METRIC_DEFINE_gauge_int64(server, code_cache_queries, "Codegen Cache Queries",
                           kudu::MetricUnit::kCacheQueries,
                           "Number of codegen cache queries (hits + misses) "
                           "since start",
+                          kudu::MetricLevel::kDebug,
                           kudu::EXPOSE_AS_COUNTER);
 namespace kudu {
 namespace codegen {
diff --git a/src/kudu/consensus/consensus_queue.cc b/src/kudu/consensus/consensus_queue.cc
index 1c91826..2a71020 100644
--- a/src/kudu/consensus/consensus_queue.cc
+++ b/src/kudu/consensus/consensus_queue.cc
@@ -92,14 +92,17 @@ namespace consensus {
 METRIC_DEFINE_gauge_int64(tablet, majority_done_ops, "Leader Operations Acked by Majority",
                           MetricUnit::kOperations,
                           "Number of operations in the leader queue ack'd by a majority but "
-                          "not all peers. This metric is always zero for followers.");
+                          "not all peers. This metric is always zero for followers.",
+                          kudu::MetricLevel::kDebug);
 METRIC_DEFINE_gauge_int64(tablet, in_progress_ops, "Operations in Progress",
                           MetricUnit::kOperations,
                           "Number of operations in the peer's queue ack'd by a minority of "
-                          "peers.");
+                          "peers.",
+                          kudu::MetricLevel::kDebug);
 METRIC_DEFINE_gauge_int64(tablet, ops_behind_leader, "Operations Behind Leader",
                           MetricUnit::kOperations,
-                          "Number of operations this server believes it is behind the leader.");
+                          "Number of operations this server believes it is behind the leader.",
+                          kudu::MetricLevel::kWarn);
 
 const char* PeerStatusToString(PeerStatus p) {
   switch (p) {
diff --git a/src/kudu/consensus/log_cache.cc b/src/kudu/consensus/log_cache.cc
index fe8572f..a0dbb95 100644
--- a/src/kudu/consensus/log_cache.cc
+++ b/src/kudu/consensus/log_cache.cc
@@ -70,10 +70,12 @@ namespace consensus {
 
 METRIC_DEFINE_gauge_int64(tablet, log_cache_num_ops, "Log Cache Operation Count",
                           MetricUnit::kOperations,
-                          "Number of operations in the log cache.");
+                          "Number of operations in the log cache.",
+                          kudu::MetricLevel::kDebug);
 METRIC_DEFINE_gauge_int64(tablet, log_cache_size, "Log Cache Memory Usage",
                           MetricUnit::kBytes,
-                          "Amount of memory in use for caching the local log.");
+                          "Amount of memory in use for caching the local log.",
+                          kudu::MetricLevel::kDebug);
 
 static const char kParentMemTrackerId[] = "log_cache";
 
diff --git a/src/kudu/consensus/log_metrics.cc b/src/kudu/consensus/log_metrics.cc
index 3e56c35..5536614 100644
--- a/src/kudu/consensus/log_metrics.cc
+++ b/src/kudu/consensus/log_metrics.cc
@@ -21,31 +21,37 @@
 
 METRIC_DEFINE_counter(tablet, log_bytes_logged, "Bytes Written to WAL",
                       kudu::MetricUnit::kBytes,
-                      "Number of bytes logged since service start");
+                      "Number of bytes logged since service start",
+                      kudu::MetricLevel::kDebug);
 
 METRIC_DEFINE_histogram(tablet, log_sync_latency, "Log Sync Latency",
                         kudu::MetricUnit::kMicroseconds,
                         "Microseconds spent on synchronizing the log segment file",
+                        kudu::MetricLevel::kInfo,
                         60000000LU, 2);
 
 METRIC_DEFINE_histogram(tablet, log_append_latency, "Log Append Latency",
                         kudu::MetricUnit::kMicroseconds,
                         "Microseconds spent on appending to the log segment file",
+                        kudu::MetricLevel::kInfo,
                         60000000LU, 2);
 
 METRIC_DEFINE_histogram(tablet, log_group_commit_latency, "Log Group Commit Latency",
                         kudu::MetricUnit::kMicroseconds,
                         "Microseconds spent on committing an entire group",
+                        kudu::MetricLevel::kDebug,
                         60000000LU, 2);
 
 METRIC_DEFINE_histogram(tablet, log_roll_latency, "Log Roll Latency",
                         kudu::MetricUnit::kMicroseconds,
                         "Microseconds spent on rolling over to a new log segment file",
+                        kudu::MetricLevel::kDebug,
                         60000000LU, 2);
 
 METRIC_DEFINE_histogram(tablet, log_entry_batches_per_group, "Log Group Commit Batch Size",
                         kudu::MetricUnit::kRequests,
                         "Number of log entry batches in a group commit group",
+                        kudu::MetricLevel::kDebug,
                         1024, 2);
 
 namespace kudu {
diff --git a/src/kudu/consensus/log_reader.cc b/src/kudu/consensus/log_reader.cc
index 145dbf1..741f908 100644
--- a/src/kudu/consensus/log_reader.cc
+++ b/src/kudu/consensus/log_reader.cc
@@ -41,15 +41,18 @@
 
 METRIC_DEFINE_counter(tablet, log_reader_bytes_read, "Bytes Read From Log",
                       kudu::MetricUnit::kBytes,
-                      "Data read from the WAL since tablet start");
+                      "Data read from the WAL since tablet start",
+                      kudu::MetricLevel::kDebug);
 
 METRIC_DEFINE_counter(tablet, log_reader_entries_read, "Entries Read From Log",
                       kudu::MetricUnit::kEntries,
-                      "Number of entries read from the WAL since tablet start");
+                      "Number of entries read from the WAL since tablet start",
+                      kudu::MetricLevel::kDebug);
 
 METRIC_DEFINE_histogram(tablet, log_reader_read_batch_latency, "Log Read Latency",
                         kudu::MetricUnit::kBytes,
                         "Microseconds spent reading log entry batches",
+                        kudu::MetricLevel::kInfo,
                         60000000LU, 2);
 
 using kudu::consensus::OpId;
diff --git a/src/kudu/consensus/raft_consensus.cc b/src/kudu/consensus/raft_consensus.cc
index 4300ebf..c473d13 100644
--- a/src/kudu/consensus/raft_consensus.cc
+++ b/src/kudu/consensus/raft_consensus.cc
@@ -140,23 +140,27 @@ METRIC_DEFINE_counter(tablet, follower_memory_pressure_rejections,
                       "Follower Memory Pressure Rejections",
                       kudu::MetricUnit::kRequests,
                       "Number of RPC requests rejected due to "
-                      "memory pressure while FOLLOWER.");
+                      "memory pressure while FOLLOWER.",
+                      kudu::MetricLevel::kWarn);
 METRIC_DEFINE_gauge_int64(tablet, raft_term,
                           "Current Raft Consensus Term",
                           kudu::MetricUnit::kUnits,
                           "Current Term of the Raft Consensus algorithm. This number increments "
-                          "each time a leader election is started.");
+                          "each time a leader election is started.",
+                          kudu::MetricLevel::kDebug);
 METRIC_DEFINE_gauge_int64(tablet, failed_elections_since_stable_leader,
                           "Failed Elections Since Stable Leader",
                           kudu::MetricUnit::kUnits,
                           "Number of failed elections on this node since there was a stable "
                           "leader. This number increments on each failed election and resets on "
-                          "each successful one.");
+                          "each successful one.",
+                          kudu::MetricLevel::kWarn);
 METRIC_DEFINE_gauge_int64(tablet, time_since_last_leader_heartbeat,
                           "Time Since Last Leader Heartbeat",
                           kudu::MetricUnit::kMilliseconds,
                           "The time elapsed since the last heartbeat from the leader "
-                          "in milliseconds. This metric is identically zero on a leader replica.");
+                          "in milliseconds. This metric is identically zero on a leader replica.",
+                          kudu::MetricLevel::kDebug);
 
 
 using boost::optional;
diff --git a/src/kudu/fs/block_manager_metrics.cc b/src/kudu/fs/block_manager_metrics.cc
index a116e94..4dab00f 100644
--- a/src/kudu/fs/block_manager_metrics.cc
+++ b/src/kudu/fs/block_manager_metrics.cc
@@ -22,47 +22,56 @@
 METRIC_DEFINE_gauge_uint64(server, block_manager_blocks_open_reading,
                            "Data Blocks Open For Read",
                            kudu::MetricUnit::kBlocks,
-                           "Number of data blocks currently open for reading");
+                           "Number of data blocks currently open for reading",
+                           kudu::MetricLevel::kInfo);
 
 METRIC_DEFINE_gauge_uint64(server, block_manager_blocks_open_writing,
                            "Data Blocks Open For Write",
                            kudu::MetricUnit::kBlocks,
-                           "Number of data blocks currently open for writing");
+                           "Number of data blocks currently open for writing",
+                           kudu::MetricLevel::kInfo);
 
 METRIC_DEFINE_counter(server, block_manager_total_writable_blocks,
                       "Data Blocks Opened For Write",
                       kudu::MetricUnit::kBlocks,
-                      "Number of data blocks opened for writing since service start");
+                      "Number of data blocks opened for writing since service start",
+                      kudu::MetricLevel::kDebug);
 
 METRIC_DEFINE_counter(server, block_manager_total_readable_blocks,
                       "Data Blocks Opened For Read",
                       kudu::MetricUnit::kBlocks,
-                      "Number of data blocks opened for reading since service start");
+                      "Number of data blocks opened for reading since service start",
+                      kudu::MetricLevel::kDebug);
 
 METRIC_DEFINE_counter(server, block_manager_total_blocks_created,
                       "Data Blocks Created",
                       kudu::MetricUnit::kBlocks,
-                      "Number of data blocks that were created since service start");
+                      "Number of data blocks that were created since service start",
+                      kudu::MetricLevel::kDebug);
 
 METRIC_DEFINE_counter(server, block_manager_total_blocks_deleted,
                       "Data Blocks Deleted",
                       kudu::MetricUnit::kBlocks,
-                      "Number of data blocks that were deleted since service start");
+                      "Number of data blocks that were deleted since service start",
+                      kudu::MetricLevel::kDebug);
 
 METRIC_DEFINE_counter(server, block_manager_total_bytes_written,
                       "Block Data Bytes Written",
                       kudu::MetricUnit::kBytes,
-                      "Number of bytes of block data written since service start");
+                      "Number of bytes of block data written since service start",
+                      kudu::MetricLevel::kDebug);
 
 METRIC_DEFINE_counter(server, block_manager_total_bytes_read,
                       "Block Data Bytes Read",
                       kudu::MetricUnit::kBytes,
-                      "Number of bytes of block data read since service start");
+                      "Number of bytes of block data read since service start",
+                      kudu::MetricLevel::kDebug);
 
 METRIC_DEFINE_counter(server, block_manager_total_disk_sync,
                       "Block Data Disk Synchronization Count",
                       kudu::MetricUnit::kBlocks,
-                      "Number of disk synchronizations of block data since service start");
+                      "Number of disk synchronizations of block data since service start",
+                      kudu::MetricLevel::kDebug);
 
 namespace kudu {
 namespace fs {
diff --git a/src/kudu/fs/data_dirs.cc b/src/kudu/fs/data_dirs.cc
index 5812e1d..8142877 100644
--- a/src/kudu/fs/data_dirs.cc
+++ b/src/kudu/fs/data_dirs.cc
@@ -105,11 +105,13 @@ METRIC_DEFINE_gauge_uint64(server, data_dirs_failed,
                            "Data Directories Failed",
                            kudu::MetricUnit::kDataDirectories,
                            "Number of data directories whose disks are currently "
-                           "in a failed state");
+                           "in a failed state",
+                           kudu::MetricLevel::kWarn);
 METRIC_DEFINE_gauge_uint64(server, data_dirs_full,
                            "Data Directories Full",
                            kudu::MetricUnit::kDataDirectories,
-                           "Number of data directories whose disks are currently full");
+                           "Number of data directories whose disks are currently full",
+                           kudu::MetricLevel::kWarn);
 
 DECLARE_bool(enable_data_block_fsync);
 DECLARE_string(block_manager);
diff --git a/src/kudu/fs/log_block_manager.cc b/src/kudu/fs/log_block_manager.cc
index beda716..585efe6 100644
--- a/src/kudu/fs/log_block_manager.cc
+++ b/src/kudu/fs/log_block_manager.cc
@@ -121,32 +121,38 @@ TAG_FLAG(log_block_manager_delete_dead_container, experimental);
 METRIC_DEFINE_gauge_uint64(server, log_block_manager_bytes_under_management,
                            "Bytes Under Management",
                            kudu::MetricUnit::kBytes,
-                           "Number of bytes of data blocks currently under management");
+                           "Number of bytes of data blocks currently under management",
+                           kudu::MetricLevel::kInfo);
 
 METRIC_DEFINE_gauge_uint64(server, log_block_manager_blocks_under_management,
                            "Blocks Under Management",
                            kudu::MetricUnit::kBlocks,
-                           "Number of data blocks currently under management");
+                           "Number of data blocks currently under management",
+                           kudu::MetricLevel::kInfo);
 
 METRIC_DEFINE_gauge_uint64(server, log_block_manager_containers,
                            "Number of Block Containers",
                            kudu::MetricUnit::kLogBlockContainers,
-                           "Number of log block containers");
+                           "Number of log block containers",
+                           kudu::MetricLevel::kInfo);
 
 METRIC_DEFINE_gauge_uint64(server, log_block_manager_full_containers,
                            "Number of Full Block Containers",
                            kudu::MetricUnit::kLogBlockContainers,
-                           "Number of full log block containers");
+                           "Number of full log block containers",
+                           kudu::MetricLevel::kInfo);
 
 METRIC_DEFINE_counter(server, log_block_manager_holes_punched,
                       "Number of Holes Punched",
                       kudu::MetricUnit::kHoles,
-                      "Number of holes punched since service start");
+                      "Number of holes punched since service start",
+                      kudu::MetricLevel::kDebug);
 
 METRIC_DEFINE_counter(server, log_block_manager_dead_containers_deleted,
                       "Number of Dead Block Containers Deleted",
                       kudu::MetricUnit::kLogBlockContainers,
-                      "Number of full (but dead) block containers that were deleted");
+                      "Number of full (but dead) block containers that were deleted",
+                      kudu::MetricLevel::kDebug);
 
 namespace kudu {
 
diff --git a/src/kudu/kserver/kserver.cc b/src/kudu/kserver/kserver.cc
index 985e777..6b0adf3 100644
--- a/src/kudu/kserver/kserver.cc
+++ b/src/kudu/kserver/kserver.cc
@@ -28,6 +28,7 @@
 #include <glog/logging.h>
 
 #include "kudu/fs/fs_manager.h"
+#include "kudu/gutil/gscoped_ptr.h"
 #include "kudu/gutil/integral_types.h"
 #include "kudu/gutil/strings/numbers.h"
 #include "kudu/gutil/strings/substitute.h"
@@ -67,6 +68,7 @@ METRIC_DEFINE_histogram(server, op_apply_queue_length, "Operation Apply Queue Le
                         "Number of operations waiting to be applied to the tablet. "
                         "High queue lengths indicate that the server is unable to process "
                         "operations as fast as they are being written to the WAL.",
+                        kudu::MetricLevel::kWarn,
                         10000, 2);
 
 METRIC_DEFINE_histogram(server, op_apply_queue_time, "Operation Apply Queue Time",
@@ -74,6 +76,7 @@ METRIC_DEFINE_histogram(server, op_apply_queue_time, "Operation Apply Queue Time
                         "Time that operations spent waiting in the apply queue before being "
                         "processed. High queue times indicate that the server is unable to "
                         "process operations as fast as they are being written to the WAL.",
+                        kudu::MetricLevel::kWarn,
                         10000000, 2);
 
 METRIC_DEFINE_histogram(server, op_apply_run_time, "Operation Apply Run Time",
@@ -81,6 +84,7 @@ METRIC_DEFINE_histogram(server, op_apply_run_time, "Operation Apply Run Time",
                         "Time that operations spent being applied to the tablet. "
                         "High values may indicate that the server is under-provisioned or "
                         "that operations consist of very large batches.",
+                        kudu::MetricLevel::kWarn,
                         10000000, 2);
 
 namespace {
diff --git a/src/kudu/kserver/kserver.h b/src/kudu/kserver/kserver.h
index 09903a9..1833323 100644
--- a/src/kudu/kserver/kserver.h
+++ b/src/kudu/kserver/kserver.h
@@ -17,6 +17,7 @@
 
 #pragma once
 
+#include <memory>
 #include <string>
 
 #include "kudu/gutil/macros.h"
diff --git a/src/kudu/master/location_cache.cc b/src/kudu/master/location_cache.cc
index 77b2f91..9c8a8e4 100644
--- a/src/kudu/master/location_cache.cc
+++ b/src/kudu/master/location_cache.cc
@@ -40,11 +40,13 @@ METRIC_DEFINE_counter(server, location_mapping_cache_hits,
                       "Location Mapping Cache Hits",
                       kudu::MetricUnit::kCacheHits,
                       "Number of times location mapping assignment used "
-                      "cached data");
+                      "cached data",
+                      kudu::MetricLevel::kDebug);
 METRIC_DEFINE_counter(server, location_mapping_cache_queries,
                       "Location Mapping Cache Queries",
                       kudu::MetricUnit::kCacheQueries,
-                      "Number of queries to the location mapping cache");
+                      "Number of queries to the location mapping cache",
+                      kudu::MetricLevel::kDebug);
 
 using std::string;
 using std::vector;
diff --git a/src/kudu/master/sentry_client_metrics.cc b/src/kudu/master/sentry_client_metrics.cc
index be593d2..bee17e2 100644
--- a/src/kudu/master/sentry_client_metrics.cc
+++ b/src/kudu/master/sentry_client_metrics.cc
@@ -21,23 +21,29 @@
 
 METRIC_DEFINE_counter(server, sentry_client_tasks_successful,
                       "Successful Tasks", kudu::MetricUnit::kTasks,
-                      "Number of successfully run tasks");
+                      "Number of successfully run tasks",
+                      kudu::MetricLevel::kDebug);
 METRIC_DEFINE_counter(server, sentry_client_tasks_failed_fatal,
                       "Failed tasks (fatal)", kudu::MetricUnit::kTasks,
-                      "Number of tasks failed with fatal errors");
+                      "Number of tasks failed with fatal errors",
+                      kudu::MetricLevel::kWarn);
 METRIC_DEFINE_counter(server, sentry_client_tasks_failed_nonfatal,
                       "Failed Tasks (nonfatal)", kudu::MetricUnit::kTasks,
-                      "Number of tasks failed with non-fatal errors");
+                      "Number of tasks failed with non-fatal errors",
+                      kudu::MetricLevel::kWarn);
 METRIC_DEFINE_counter(server, sentry_client_reconnections_succeeded,
                       "Successful Reconnections", kudu::MetricUnit::kUnits,
-                      "Number of successful reconnections to Sentry");
+                      "Number of successful reconnections to Sentry",
+                      kudu::MetricLevel::kDebug);
 METRIC_DEFINE_counter(server, sentry_client_reconnections_failed,
                       "Failed Reconnections", kudu::MetricUnit::kUnits,
-                      "Number of failed reconnections to Sentry");
+                      "Number of failed reconnections to Sentry",
+                      kudu::MetricLevel::kDebug);
 METRIC_DEFINE_histogram(server, sentry_client_task_execution_time_us,
                         "Task Execution Time (us)",
                         kudu::MetricUnit::kMicroseconds,
                         "Duration of HaClient::Execute() calls (us)",
+                        kudu::MetricLevel::kInfo,
                         60000000, 2);
 
 namespace kudu {
diff --git a/src/kudu/master/sentry_privileges_cache_metrics.cc b/src/kudu/master/sentry_privileges_cache_metrics.cc
index 65549b0..7e0477a 100644
--- a/src/kudu/master/sentry_privileges_cache_metrics.cc
+++ b/src/kudu/master/sentry_privileges_cache_metrics.cc
@@ -22,37 +22,45 @@
 METRIC_DEFINE_counter(server, sentry_privileges_cache_inserts,
                       "Sentry Privileges Cache Inserts",
                       kudu::MetricUnit::kEntries,
-                      "Number of entries inserted in the cache");
+                      "Number of entries inserted in the cache",
+                      kudu::MetricLevel::kDebug);
 METRIC_DEFINE_counter(server, sentry_privileges_cache_lookups,
                       "Sentry Privileges Cache Lookups",
                       kudu::MetricUnit::kEntries,
-                      "Number of entries looked up from the cache");
+                      "Number of entries looked up from the cache",
+                      kudu::MetricLevel::kDebug);
 METRIC_DEFINE_counter(server, sentry_privileges_cache_evictions,
                       "Sentry Privileges Cache Evictions",
                       kudu::MetricUnit::kEntries,
-                      "Number of entries evicted from the cache");
+                      "Number of entries evicted from the cache",
+                      kudu::MetricLevel::kDebug);
 METRIC_DEFINE_counter(server, sentry_privileges_cache_evictions_expired,
                       "Sentry Privileges Cache Evictions of Expired Entries",
                       kudu::MetricUnit::kEntries,
                       "Number of entries that had already expired upon "
-                      "eviction from the cache");
+                      "eviction from the cache",
+                      kudu::MetricLevel::kDebug);
 METRIC_DEFINE_counter(server, sentry_privileges_cache_misses,
                       "Sentry Privileges Cache Misses",
                       kudu::MetricUnit::kEntries,
-                      "Number of lookups that didn't find a cached entry");
+                      "Number of lookups that didn't find a cached entry",
+                      kudu::MetricLevel::kDebug);
 METRIC_DEFINE_counter(server, sentry_privileges_cache_hits,
                       "Sentry Privileges Cache Hits",
                       kudu::MetricUnit::kEntries,
-                      "Number of lookups that found a cached entry");
+                      "Number of lookups that found a cached entry",
+                      kudu::MetricLevel::kDebug);
 METRIC_DEFINE_counter(server, sentry_privileges_cache_hits_expired,
                       "Sentry Privileges Cache Hits of Expired Entries",
                       kudu::MetricUnit::kEntries,
                       "Number of lookups that found an entry, but the entry "
-                      "had already expired at the time of lookup");
+                      "had already expired at the time of lookup",
+                      kudu::MetricLevel::kDebug);
 METRIC_DEFINE_gauge_uint64(server, sentry_privileges_cache_memory_usage,
                            "Sentry Privileges Cache Memory Usage",
                            kudu::MetricUnit::kBytes,
-                           "Memory consumed by the cache");
+                           "Memory consumed by the cache",
+                           kudu::MetricLevel::kDebug);
 
 namespace kudu {
 namespace master {
diff --git a/src/kudu/master/table_metrics.cc b/src/kudu/master/table_metrics.cc
index 30aa7a4..cde684e 100644
--- a/src/kudu/master/table_metrics.cc
+++ b/src/kudu/master/table_metrics.cc
@@ -27,11 +27,13 @@ namespace master {
 METRIC_DEFINE_gauge_uint64(table, on_disk_size, "Table Size On Disk",
     kudu::MetricUnit::kBytes,
     "Pre-replication aggregated disk space used by all tablets in this table, "
-    "including metadata.");
+    "including metadata.",
+    kudu::MetricLevel::kInfo);
 METRIC_DEFINE_gauge_uint64(table, live_row_count, "Table Live Row count",
     kudu::MetricUnit::kRows,
     "Pre-replication aggregated number of live rows in this table. "
-    "Only accurate if all tablets in the table support live row counting.");
+    "Only accurate if all tablets in the table support live row counting.",
+    kudu::MetricLevel::kInfo);
 
 #define GINIT(x) x(METRIC_##x.Instantiate(entity, 0))
 
diff --git a/src/kudu/master/ts_manager.cc b/src/kudu/master/ts_manager.cc
index 2841501..de77c97 100644
--- a/src/kudu/master/ts_manager.cc
+++ b/src/kudu/master/ts_manager.cc
@@ -56,7 +56,8 @@ METRIC_DEFINE_gauge_int32(server, cluster_replica_skew,
                           "The difference between the number of replicas on "
                           "the tablet server hosting the most replicas and "
                           "the number of replicas on the tablet server hosting "
-                          "the least replicas.");
+                          "the least replicas.",
+                          kudu::MetricLevel::kWarn);
 
 using kudu::pb_util::SecureShortDebugString;
 using std::lock_guard;
diff --git a/src/kudu/rpc/acceptor_pool.cc b/src/kudu/rpc/acceptor_pool.cc
index e4bcbd1..88d48da 100644
--- a/src/kudu/rpc/acceptor_pool.cc
+++ b/src/kudu/rpc/acceptor_pool.cc
@@ -50,7 +50,8 @@ using std::string;
 METRIC_DEFINE_counter(server, rpc_connections_accepted,
                       "RPC Connections Accepted",
                       kudu::MetricUnit::kConnections,
-                      "Number of incoming TCP connections made to the RPC server");
+                      "Number of incoming TCP connections made to the RPC server",
+                      kudu::MetricLevel::kInfo);
 
 DEFINE_int32(rpc_acceptor_listen_backlog, 128,
              "Socket backlog parameter used when listening for RPC connections. "
diff --git a/src/kudu/rpc/protoc-gen-krpc.cc b/src/kudu/rpc/protoc-gen-krpc.cc
index cc25f67..c4c7abd 100644
--- a/src/kudu/rpc/protoc-gen-krpc.cc
+++ b/src/kudu/rpc/protoc-gen-krpc.cc
@@ -468,6 +468,7 @@ class CodeGenerator : public ::google::protobuf::compiler::CodeGenerator {
           "  \"$rpc_full_name$ RPC Time\",\n"
           "  kudu::MetricUnit::kMicroseconds,\n"
           "  \"Microseconds spent handling $rpc_full_name$() RPC requests\",\n"
+          "  kudu::MetricLevel::kInfo,\n"
           "  60000000LU, 2);\n"
           "\n");
         subs->Pop();
diff --git a/src/kudu/rpc/reactor.cc b/src/kudu/rpc/reactor.cc
index a3e56f7..4ed2f5b 100644
--- a/src/kudu/rpc/reactor.cc
+++ b/src/kudu/rpc/reactor.cc
@@ -102,7 +102,9 @@ METRIC_DEFINE_histogram(server, reactor_load_percent,
                         "The percentage of time that the reactor is busy "
                         "(not blocked awaiting network activity). If this metric "
                         "shows significant samples nears 100%, increasing the "
-                        "number of reactors may be beneficial.", 100, 2);
+                        "number of reactors may be beneficial.",
+                        kudu::MetricLevel::kInfo,
+                        100, 2);
 
 METRIC_DEFINE_histogram(server, reactor_active_latency_us,
                         "Reactor Thread Active Latency",
@@ -111,6 +113,7 @@ METRIC_DEFINE_histogram(server, reactor_active_latency_us,
                         "The reactor thread is responsible for all network I/O and "
                         "therefore outliers in this latency histogram directly contribute "
                         "to the latency of both inbound and outbound RPCs.",
+                        kudu::MetricLevel::kInfo,
                         1000000, 2);
 
 namespace kudu {
diff --git a/src/kudu/rpc/service_pool.cc b/src/kudu/rpc/service_pool.cc
index 50a0af7..f4f0130 100644
--- a/src/kudu/rpc/service_pool.cc
+++ b/src/kudu/rpc/service_pool.cc
@@ -54,19 +54,21 @@ METRIC_DEFINE_histogram(server, rpc_incoming_queue_time,
                         "RPC Queue Time",
                         kudu::MetricUnit::kMicroseconds,
                         "Number of microseconds incoming RPC requests spend in the worker queue",
+                        kudu::MetricLevel::kInfo,
                         60000000LU, 3);
 
 METRIC_DEFINE_counter(server, rpcs_timed_out_in_queue,
                       "RPC Queue Timeouts",
                       kudu::MetricUnit::kRequests,
                       "Number of RPCs whose timeout elapsed while waiting "
-                      "in the service queue, and thus were not processed.");
+                      "in the service queue, and thus were not processed.",
+                      kudu::MetricLevel::kWarn);
 
 METRIC_DEFINE_counter(server, rpcs_queue_overflow,
                       "RPC Queue Overflows",
                       kudu::MetricUnit::kRequests,
-                      "Number of RPCs dropped because the service queue "
-                      "was full.");
+                      "Number of RPCs dropped because the service queue was full.",
+                      kudu::MetricLevel::kWarn);
 
 namespace kudu {
 namespace rpc {
diff --git a/src/kudu/server/default_path_handlers.cc b/src/kudu/server/default_path_handlers.cc
index b139bd9..209d304 100644
--- a/src/kudu/server/default_path_handlers.cc
+++ b/src/kudu/server/default_path_handlers.cc
@@ -346,9 +346,10 @@ static void WriteMetricsAsJson(const MetricRegistry* const metrics,
 
   MetricFilters& filters = opts.filters;
   filters.entity_types = ParseArray(req.parsed_args, "types");
-  filters.entity_ids =  ParseArray(req.parsed_args, "ids");
+  filters.entity_ids = ParseArray(req.parsed_args, "ids");
   filters.entity_attrs = ParseArray(req.parsed_args, "attributes");
   filters.entity_metrics = ParseArray(req.parsed_args, "metrics");
+  filters.entity_level = FindWithDefault(req.parsed_args, "level", "debug");
   vector<string> merge_rules = ParseArray(req.parsed_args, "merge_rules");
   for (const auto& merge_rule : merge_rules) {
     vector<string> values;
diff --git a/src/kudu/server/glog_metrics.cc b/src/kudu/server/glog_metrics.cc
index 9eed622..3d947ae 100644
--- a/src/kudu/server/glog_metrics.cc
+++ b/src/kudu/server/glog_metrics.cc
@@ -24,15 +24,18 @@
 
 METRIC_DEFINE_counter(server, glog_info_messages,
                       "INFO-level Log Messages", kudu::MetricUnit::kMessages,
-                      "Number of INFO-level log messages emitted by the application.");
+                      "Number of INFO-level log messages emitted by the application.",
+                      kudu::MetricLevel::kDebug);
 
 METRIC_DEFINE_counter(server, glog_warning_messages,
                       "WARNING-level Log Messages", kudu::MetricUnit::kMessages,
-                      "Number of WARNING-level log messages emitted by the application.");
+                      "Number of WARNING-level log messages emitted by the application.",
+                      kudu::MetricLevel::kWarn);
 
 METRIC_DEFINE_counter(server, glog_error_messages,
                       "ERROR-level Log Messages", kudu::MetricUnit::kMessages,
-                      "Number of ERROR-level log messages emitted by the application.");
+                      "Number of ERROR-level log messages emitted by the application.",
+                      kudu::MetricLevel::kWarn);
 
 struct tm;
 
diff --git a/src/kudu/server/tcmalloc_metrics.cc b/src/kudu/server/tcmalloc_metrics.cc
index 3c84e9b..15f3eac 100644
--- a/src/kudu/server/tcmalloc_metrics.cc
+++ b/src/kudu/server/tcmalloc_metrics.cc
@@ -42,18 +42,21 @@ METRIC_DEFINE_gauge_uint64(server, generic_current_allocated_bytes,
     "Heap Memory Usage", kudu::MetricUnit::kBytes,
     "Number of bytes used by the application. This will not typically match the memory "
     "use reported by the OS, because it does not include TCMalloc overhead or memory "
-    "fragmentation." TCM_ASAN_MSG);
+    "fragmentation." TCM_ASAN_MSG,
+    kudu::MetricLevel::kInfo);
 
 METRIC_DEFINE_gauge_uint64(server, generic_heap_size,
     "Reserved Heap Memory", kudu::MetricUnit::kBytes,
-    "Bytes of system memory reserved by TCMalloc." TCM_ASAN_MSG);
+    "Bytes of system memory reserved by TCMalloc." TCM_ASAN_MSG,
+    kudu::MetricLevel::kInfo);
 
 METRIC_DEFINE_gauge_uint64(server, tcmalloc_pageheap_free_bytes,
     "Free Heap Memory", kudu::MetricUnit::kBytes,
     "Number of bytes in free, mapped pages in page heap. These bytes can be used to "
     "fulfill allocation requests. They always count towards virtual memory usage, and "
     "unless the underlying memory is swapped out by the OS, they also count towards "
-    "physical memory usage." TCM_ASAN_MSG);
+    "physical memory usage." TCM_ASAN_MSG,
+    kudu::MetricLevel::kInfo);
 
 METRIC_DEFINE_gauge_uint64(server, tcmalloc_pageheap_unmapped_bytes,
     "Unmapped Heap Memory", kudu::MetricUnit::kBytes,
@@ -61,16 +64,19 @@ METRIC_DEFINE_gauge_uint64(server, tcmalloc_pageheap_unmapped_bytes,
     "been released back to the OS, possibly by one of the MallocExtension \"Release\" "
     "calls. They can be used to fulfill allocation requests, but typically incur a page "
     "fault. They always count towards virtual memory usage, and depending on the OS, "
-    "typically do not count towards physical memory usage." TCM_ASAN_MSG);
+    "typically do not count towards physical memory usage." TCM_ASAN_MSG,
+    kudu::MetricLevel::kInfo);
 
 METRIC_DEFINE_gauge_uint64(server, tcmalloc_max_total_thread_cache_bytes,
     "Thread Cache Memory Limit", kudu::MetricUnit::kBytes,
     "A limit to how much memory TCMalloc dedicates for small objects. Higher numbers "
-    "trade off more memory use for -- in some situations -- improved efficiency." TCM_ASAN_MSG);
+    "trade off more memory use for -- in some situations -- improved efficiency." TCM_ASAN_MSG,
+    kudu::MetricLevel::kInfo);
 
 METRIC_DEFINE_gauge_uint64(server, tcmalloc_current_total_thread_cache_bytes,
     "Thread Cache Memory Usage", kudu::MetricUnit::kBytes,
-    "A measure of some of the memory TCMalloc is using (for small objects)." TCM_ASAN_MSG);
+    "A measure of some of the memory TCMalloc is using (for small objects)." TCM_ASAN_MSG,
+    kudu::MetricLevel::kInfo);
 
 #undef TCM_ASAN_MSG
 
diff --git a/src/kudu/tablet/tablet.cc b/src/kudu/tablet/tablet.cc
index 8d0d560..3802a68 100644
--- a/src/kudu/tablet/tablet.cc
+++ b/src/kudu/tablet/tablet.cc
@@ -153,13 +153,16 @@ TAG_FLAG(max_encoded_key_size_bytes, unsafe);
 METRIC_DEFINE_entity(tablet);
 METRIC_DEFINE_gauge_size(tablet, memrowset_size, "MemRowSet Memory Usage",
                          kudu::MetricUnit::kBytes,
-                         "Size of this tablet's memrowset");
+                         "Size of this tablet's memrowset",
+                         kudu::MetricLevel::kInfo);
 METRIC_DEFINE_gauge_size(tablet, on_disk_data_size, "Tablet Data Size On Disk",
                          kudu::MetricUnit::kBytes,
-                         "Space used by this tablet's data blocks.");
+                         "Space used by this tablet's data blocks.",
+                         kudu::MetricLevel::kInfo);
 METRIC_DEFINE_gauge_size(tablet, num_rowsets_on_disk, "Tablet Number of Rowsets on Disk",
                          kudu::MetricUnit::kUnits,
-                         "Number of diskrowsets in this tablet");
+                         "Number of diskrowsets in this tablet",
+                         kudu::MetricLevel::kInfo);
 
 using kudu::MaintenanceManager;
 using kudu::clock::HybridClock;
diff --git a/src/kudu/tablet/tablet_metrics.cc b/src/kudu/tablet/tablet_metrics.cc
index e266af1..e7bf936 100644
--- a/src/kudu/tablet/tablet_metrics.cc
+++ b/src/kudu/tablet/tablet_metrics.cc
@@ -20,9 +20,7 @@
 #include <map>
 #include <utility>
 #include <cstdint>
-#include <unordered_map>
 
-#include "kudu/gutil/strings/substitute.h"
 #include "kudu/tablet/rowset.h"
 #include "kudu/util/memory/arena.h"
 #include "kudu/util/metrics.h"
@@ -31,42 +29,51 @@
 // Tablet-specific metrics.
 METRIC_DEFINE_counter(tablet, rows_inserted, "Rows Inserted",
     kudu::MetricUnit::kRows,
-    "Number of rows inserted into this tablet since service start");
+    "Number of rows inserted into this tablet since service start",
+    kudu::MetricLevel::kInfo);
 METRIC_DEFINE_counter(tablet, rows_upserted, "Rows Upserted",
     kudu::MetricUnit::kRows,
-    "Number of rows upserted into this tablet since service start");
+    "Number of rows upserted into this tablet since service start",
+    kudu::MetricLevel::kInfo);
 METRIC_DEFINE_counter(tablet, rows_updated, "Rows Updated",
     kudu::MetricUnit::kRows,
-    "Number of row update operations performed on this tablet since service start");
+    "Number of row update operations performed on this tablet since service start",
+    kudu::MetricLevel::kInfo);
 METRIC_DEFINE_counter(tablet, rows_deleted, "Rows Deleted",
     kudu::MetricUnit::kRows,
-    "Number of row delete operations performed on this tablet since service start");
+    "Number of row delete operations performed on this tablet since service start",
+    kudu::MetricLevel::kInfo);
 
 METRIC_DEFINE_counter(tablet, insertions_failed_dup_key, "Duplicate Key Inserts",
                       kudu::MetricUnit::kRows,
-                      "Number of inserts which failed because the key already existed");
+                      "Number of inserts which failed because the key already existed",
+                      kudu::MetricLevel::kDebug);
 
 METRIC_DEFINE_counter(tablet, upserts_as_updates, "Upserts converted into updates",
                       kudu::MetricUnit::kRows,
                       "Number of upserts which were applied as updates because the key already "
-                          "existed.");
+                      "existed.",
+                      kudu::MetricLevel::kInfo);
 
 METRIC_DEFINE_counter(tablet, scanner_rows_returned, "Scanner Rows Returned",
                       kudu::MetricUnit::kRows,
                       "Number of rows returned by scanners to clients. This count "
                       "is measured after predicates are applied, and thus is not "
-                      "a reflection of the amount of work being done by scanners.");
+                      "a reflection of the amount of work being done by scanners.",
+                      kudu::MetricLevel::kDebug);
 METRIC_DEFINE_counter(tablet, scanner_cells_returned, "Scanner Cells Returned",
                       kudu::MetricUnit::kCells,
                       "Number of table cells returned by scanners to clients. This count "
                       "is measured after predicates are applied, and thus is not "
-                      "a reflection of the amount of work being done by scanners.");
+                      "a reflection of the amount of work being done by scanners.",
+                      kudu::MetricLevel::kDebug);
 METRIC_DEFINE_counter(tablet, scanner_bytes_returned, "Scanner Bytes Returned",
                       kudu::MetricUnit::kBytes,
                       "Number of bytes returned by scanners to clients. This count "
                       "is measured after predicates are applied and the data is decoded "
                       "for consumption by clients, and thus is not "
-                      "a reflection of the amount of work being done by scanners.");
+                      "a reflection of the amount of work being done by scanners.",
+                      kudu::MetricLevel::kDebug);
 
 METRIC_DEFINE_counter(tablet, scanner_rows_scanned, "Scanner Rows Scanned",
                       kudu::MetricUnit::kRows,
@@ -74,7 +81,8 @@ METRIC_DEFINE_counter(tablet, scanner_rows_scanned, "Scanner Rows Scanned",
                       "as a raw count prior to application of predicates, deleted data,"
                       "or MVCC-based filtering. Thus, this is a better measure of actual "
                       "table rows that have been processed by scan operations compared "
-                      "to the Scanner Rows Returned metric.");
+                      "to the Scanner Rows Returned metric.",
+                      kudu::MetricLevel::kDebug);
 
 METRIC_DEFINE_counter(tablet, scanner_cells_scanned_from_disk, "Scanner Cells Scanned From Disk",
                       kudu::MetricUnit::kCells,
@@ -85,7 +93,8 @@ METRIC_DEFINE_counter(tablet, scanner_cells_scanned_from_disk, "Scanner Cells Sc
                       "to the Scanner Cells Returned metric.\n"
                       "Note that this only counts data that has been flushed to disk, "
                       "and does not include data read from in-memory stores. However, it"
-                      "includes both cache misses and cache hits.");
+                      "includes both cache misses and cache hits.",
+                      kudu::MetricLevel::kDebug);
 
 METRIC_DEFINE_counter(tablet, scanner_bytes_scanned_from_disk, "Scanner Bytes Scanned From Disk",
                       kudu::MetricUnit::kBytes,
@@ -96,37 +105,46 @@ METRIC_DEFINE_counter(tablet, scanner_bytes_scanned_from_disk, "Scanner Bytes Sc
                       "to the Scanner Bytes Returned metric.\n"
                       "Note that this only counts data that has been flushed to disk, "
                       "and does not include data read from in-memory stores. However, it"
-                      "includes both cache misses and cache hits.");
+                      "includes both cache misses and cache hits.",
+                      kudu::MetricLevel::kDebug);
 
 METRIC_DEFINE_counter(tablet, scans_started, "Scans Started",
                       kudu::MetricUnit::kScanners,
-                      "Number of scanners which have been started on this tablet");
+                      "Number of scanners which have been started on this tablet",
+                      kudu::MetricLevel::kDebug);
 METRIC_DEFINE_gauge_size(tablet, tablet_active_scanners, "Active Scanners",
                          kudu::MetricUnit::kScanners,
-                         "Number of scanners that are currently active on this tablet");
+                         "Number of scanners that are currently active on this tablet",
+                         kudu::MetricLevel::kDebug);
 
 METRIC_DEFINE_counter(tablet, bloom_lookups, "Bloom Filter Lookups",
                       kudu::MetricUnit::kProbes,
-                      "Number of times a bloom filter was consulted");
+                      "Number of times a bloom filter was consulted",
+                      kudu::MetricLevel::kDebug);
 METRIC_DEFINE_counter(tablet, key_file_lookups, "Key File Lookups",
                       kudu::MetricUnit::kProbes,
-                      "Number of times a key cfile was consulted");
+                      "Number of times a key cfile was consulted",
+                      kudu::MetricLevel::kDebug);
 METRIC_DEFINE_counter(tablet, delta_file_lookups, "Delta File Lookups",
                       kudu::MetricUnit::kProbes,
-                      "Number of times a delta file was consulted");
+                      "Number of times a delta file was consulted",
+                      kudu::MetricLevel::kDebug);
 METRIC_DEFINE_counter(tablet, mrs_lookups, "MemRowSet Lookups",
                       kudu::MetricUnit::kProbes,
-                      "Number of times a MemRowSet was consulted.");
+                      "Number of times a MemRowSet was consulted.",
+                      kudu::MetricLevel::kDebug);
 METRIC_DEFINE_counter(tablet, bytes_flushed, "Bytes Flushed",
                       kudu::MetricUnit::kBytes,
-                      "Amount of data that has been flushed to disk by this tablet.");
+                      "Amount of data that has been flushed to disk by this tablet.",
+                      kudu::MetricLevel::kDebug);
 
 METRIC_DEFINE_counter(tablet, undo_delta_block_gc_bytes_deleted,
                       "Undo Delta Block GC Bytes Deleted",
                       kudu::MetricUnit::kBytes,
                       "Number of bytes deleted by garbage-collecting old UNDO delta blocks "
                       "on this tablet since this server was restarted. "
-                      "Does not include bytes garbage collected during compactions.");
+                      "Does not include bytes garbage collected during compactions.",
+                      kudu::MetricLevel::kDebug);
 
 METRIC_DEFINE_histogram(tablet, bloom_lookups_per_op, "Bloom Lookups per Operation",
                         kudu::MetricUnit::kProbes,
@@ -134,6 +152,7 @@ METRIC_DEFINE_histogram(tablet, bloom_lookups_per_op, "Bloom Lookups per Operati
                         "operation. A single operation may perform several bloom filter "
                         "lookups if the tablet is not fully compacted. High frequency of "
                         "high values may indicate that compaction is falling behind.",
+                        kudu::MetricLevel::kDebug,
                         20, 2);
 
 METRIC_DEFINE_histogram(tablet, key_file_lookups_per_op, "Key Lookups per Operation",
@@ -141,128 +160,158 @@ METRIC_DEFINE_histogram(tablet, key_file_lookups_per_op, "Key Lookups per Operat
                         "Tracks the number of key file lookups performed by each "
                         "operation. A single operation may perform several key file "
                         "lookups if the tablet is not fully compacted and if bloom filters "
-                        "are not effectively culling lookups.", 20, 2);
+                        "are not effectively culling lookups.",
+                        kudu::MetricLevel::kDebug,
+                        20, 2);
 
 METRIC_DEFINE_histogram(tablet, delta_file_lookups_per_op, "Delta File Lookups per Operation",
                         kudu::MetricUnit::kProbes,
                         "Tracks the number of delta file lookups performed by each "
                         "operation. A single operation may perform several delta file "
                         "lookups if the tablet is not fully compacted. High frequency of "
-                        "high values may indicate that compaction is falling behind.", 20, 2);
+                        "high values may indicate that compaction is falling behind.",
+                        kudu::MetricLevel::kInfo,
+                        20, 2);
 
 METRIC_DEFINE_histogram(tablet, write_op_duration_client_propagated_consistency,
   "Write Op Duration with Propagated Consistency",
   kudu::MetricUnit::kMicroseconds,
   "Duration of writes to this tablet with external consistency set to CLIENT_PROPAGATED.",
+  kudu::MetricLevel::kDebug,
   60000000LU, 2);
 
 METRIC_DEFINE_histogram(tablet, write_op_duration_commit_wait_consistency,
   "Write Op Duration with Commit-Wait Consistency",
   kudu::MetricUnit::kMicroseconds,
   "Duration of writes to this tablet with external consistency set to COMMIT_WAIT.",
+  kudu::MetricLevel::kDebug,
   60000000LU, 2);
 
 METRIC_DEFINE_histogram(tablet, commit_wait_duration,
   "Commit-Wait Duration",
   kudu::MetricUnit::kMicroseconds,
   "Time spent waiting for COMMIT_WAIT external consistency writes for this tablet.",
+  kudu::MetricLevel::kDebug,
   60000000LU, 2);
 
 METRIC_DEFINE_histogram(tablet, snapshot_read_inflight_wait_duration,
   "Time Waiting For Snapshot Reads",
   kudu::MetricUnit::kMicroseconds,
   "Time spent waiting for in-flight writes to complete for READ_AT_SNAPSHOT scans.",
+  kudu::MetricLevel::kDebug,
   60000000LU, 2);
 
 METRIC_DEFINE_gauge_uint32(tablet, flush_dms_running,
   "DeltaMemStore Flushes Running",
   kudu::MetricUnit::kMaintenanceOperations,
-  "Number of delta memstore flushes currently running.");
+  "Number of delta memstore flushes currently running.",
+  kudu::MetricLevel::kDebug);
 
 METRIC_DEFINE_gauge_uint32(tablet, flush_mrs_running,
   "MemRowSet Flushes Running",
   kudu::MetricUnit::kMaintenanceOperations,
-  "Number of MemRowSet flushes currently running.");
+  "Number of MemRowSet flushes currently running.",
+  kudu::MetricLevel::kDebug);
 
 METRIC_DEFINE_gauge_uint32(tablet, compact_rs_running,
   "RowSet Compactions Running",
   kudu::MetricUnit::kMaintenanceOperations,
-  "Number of RowSet compactions currently running.");
+  "Number of RowSet compactions currently running.",
+  kudu::MetricLevel::kDebug);
 
 METRIC_DEFINE_gauge_uint32(tablet, delta_minor_compact_rs_running,
   "Minor Delta Compactions Running",
   kudu::MetricUnit::kMaintenanceOperations,
-  "Number of delta minor compactions currently running.");
+  "Number of delta minor compactions currently running.",
+  kudu::MetricLevel::kDebug);
 
 METRIC_DEFINE_gauge_uint32(tablet, delta_major_compact_rs_running,
   "Major Delta Compactions Running",
   kudu::MetricUnit::kMaintenanceOperations,
-  "Number of delta major compactions currently running.");
+  "Number of delta major compactions currently running.",
+  kudu::MetricLevel::kDebug);
 
 METRIC_DEFINE_gauge_uint32(tablet, undo_delta_block_gc_running,
   "Undo Delta Block GC Running",
   kudu::MetricUnit::kMaintenanceOperations,
-  "Number of UNDO delta block GC operations currently running.");
+  "Number of UNDO delta block GC operations currently running.",
+  kudu::MetricLevel::kDebug);
 
 METRIC_DEFINE_gauge_int64(tablet, undo_delta_block_estimated_retained_bytes,
   "Estimated Deletable Bytes Retained in Undo Delta Blocks",
   kudu::MetricUnit::kBytes,
   "Estimated bytes of deletable data in undo delta blocks for this tablet. "
-  "May be an overestimate.");
+  "May be an overestimate.",
+  kudu::MetricLevel::kDebug);
 
 METRIC_DEFINE_histogram(tablet, flush_dms_duration,
   "DeltaMemStore Flush Duration",
   kudu::MetricUnit::kMilliseconds,
-  "Time spent flushing DeltaMemStores.", 60000LU, 1);
+  "Time spent flushing DeltaMemStores.",
+  kudu::MetricLevel::kInfo,
+  60000LU, 1);
 
 METRIC_DEFINE_histogram(tablet, flush_mrs_duration,
   "MemRowSet Flush Duration",
   kudu::MetricUnit::kMilliseconds,
-  "Time spent flushing MemRowSets.", 60000LU, 1);
+  "Time spent flushing MemRowSets.",
+  kudu::MetricLevel::kInfo,
+  60000LU, 1);
 
 METRIC_DEFINE_histogram(tablet, compact_rs_duration,
   "RowSet Compaction Duration",
   kudu::MetricUnit::kMilliseconds,
-  "Time spent compacting RowSets.", 60000LU, 1);
+  "Time spent compacting RowSets.",
+  kudu::MetricLevel::kInfo,
+  60000LU, 1);
 
 METRIC_DEFINE_histogram(tablet, delta_minor_compact_rs_duration,
   "Minor Delta Compaction Duration",
   kudu::MetricUnit::kMilliseconds,
-  "Time spent minor delta compacting.", 60000LU, 1);
+  "Time spent minor delta compacting.",
+  kudu::MetricLevel::kInfo,
+  60000LU, 1);
 
 METRIC_DEFINE_histogram(tablet, delta_major_compact_rs_duration,
   "Major Delta Compaction Duration",
   kudu::MetricUnit::kSeconds,
-  "Seconds spent major delta compacting.", 60000000LU, 2);
+  "Seconds spent major delta compacting.",
+  kudu::MetricLevel::kInfo,
+  60000000LU, 2);
 
 METRIC_DEFINE_histogram(tablet, undo_delta_block_gc_init_duration,
   "Undo Delta Block GC Init Duration",
   kudu::MetricUnit::kMilliseconds,
-  "Time spent initializing ancient UNDO delta blocks.", 60000LU, 1);
+  "Time spent initializing ancient UNDO delta blocks.",
+  kudu::MetricLevel::kInfo,
+  60000LU, 1);
 
 METRIC_DEFINE_histogram(tablet, undo_delta_block_gc_delete_duration,
   "Undo Delta Block GC Delete Duration",
   kudu::MetricUnit::kMilliseconds,
-  "Time spent deleting ancient UNDO delta blocks.", 60000LU, 1);
+  "Time spent deleting ancient UNDO delta blocks.",
+  kudu::MetricLevel::kInfo,
+  60000LU, 1);
 
 METRIC_DEFINE_histogram(tablet, undo_delta_block_gc_perform_duration,
   "Undo Delta Block GC Perform Duration",
   kudu::MetricUnit::kMilliseconds,
-  "Time spent running the maintenance operation to GC ancient UNDO delta blocks.", 60000LU, 1);
+  "Time spent running the maintenance operation to GC ancient UNDO delta blocks.",
+  kudu::MetricLevel::kInfo,
+  60000LU, 1);
 
 METRIC_DEFINE_counter(tablet, leader_memory_pressure_rejections,
   "Leader Memory Pressure Rejections",
   kudu::MetricUnit::kRequests,
-  "Number of RPC requests rejected due to memory pressure while LEADER.");
+  "Number of RPC requests rejected due to memory pressure while LEADER.",
+  kudu::MetricLevel::kWarn);
 
 METRIC_DEFINE_gauge_double(tablet, average_diskrowset_height, "Average DiskRowSet Height",
                            kudu::MetricUnit::kUnits,
                            "Average height of the diskrowsets in this tablet "
                            "replica. The larger the average height, the more "
-                           "uncompacted the tablet replica is.");
-
-using strings::Substitute;
-using std::unordered_map;
+                           "uncompacted the tablet replica is.",
+                           kudu::MetricLevel::kInfo);
 
 namespace kudu {
 namespace tablet {
diff --git a/src/kudu/tablet/tablet_replica.cc b/src/kudu/tablet/tablet_replica.cc
index 3999bdb..7a32791 100644
--- a/src/kudu/tablet/tablet_replica.cc
+++ b/src/kudu/tablet/tablet_replica.cc
@@ -66,6 +66,7 @@ METRIC_DEFINE_histogram(tablet, op_prepare_queue_length, "Operation Prepare Queu
                         "Number of operations waiting to be prepared within this tablet. "
                         "High queue lengths indicate that the server is unable to process "
                         "operations as fast as they are being written to the WAL.",
+                        kudu::MetricLevel::kInfo,
                         10000, 2);
 
 METRIC_DEFINE_histogram(tablet, op_prepare_queue_time, "Operation Prepare Queue Time",
@@ -73,6 +74,7 @@ METRIC_DEFINE_histogram(tablet, op_prepare_queue_time, "Operation Prepare Queue
                         "Time that operations spent waiting in the prepare queue before being "
                         "processed. High queue times indicate that the server is unable to "
                         "process operations as fast as they are being written to the WAL.",
+                        kudu::MetricLevel::kInfo,
                         10000000, 2);
 
 METRIC_DEFINE_histogram(tablet, op_prepare_run_time, "Operation Prepare Run Time",
@@ -81,17 +83,21 @@ METRIC_DEFINE_histogram(tablet, op_prepare_run_time, "Operation Prepare Run Time
                         "High values may indicate that the server is under-provisioned or "
                         "that operations are experiencing high contention with one another for "
                         "locks.",
+                        kudu::MetricLevel::kInfo,
                         10000000, 2);
 
 METRIC_DEFINE_gauge_size(tablet, on_disk_size, "Tablet Size On Disk",
                          kudu::MetricUnit::kBytes,
-                         "Space used by this tablet on disk, including metadata.");
+                         "Space used by this tablet on disk, including metadata.",
+                         kudu::MetricLevel::kInfo);
 METRIC_DEFINE_gauge_string(tablet, state, "Tablet State",
                            kudu::MetricUnit::kState,
-                           "State of this tablet.");
+                           "State of this tablet.",
+                           kudu::MetricLevel::kInfo);
 METRIC_DEFINE_gauge_uint64(tablet, live_row_count, "Tablet Live Row Count",
                            kudu::MetricUnit::kRows,
-                           "Number of live rows in this tablet, excludes deleted rows.");
+                           "Number of live rows in this tablet, excludes deleted rows.",
+                           kudu::MetricLevel::kInfo);
 
 namespace kudu {
 namespace tablet {
diff --git a/src/kudu/tablet/tablet_replica_mm_ops.cc b/src/kudu/tablet/tablet_replica_mm_ops.cc
index 10713bb..dafe746 100644
--- a/src/kudu/tablet/tablet_replica_mm_ops.cc
+++ b/src/kudu/tablet/tablet_replica_mm_ops.cc
@@ -79,11 +79,14 @@ TAG_FLAG(flush_threshold_secs, runtime);
 METRIC_DEFINE_gauge_uint32(tablet, log_gc_running,
                            "Log GCs Running",
                            kudu::MetricUnit::kOperations,
-                           "Number of log GC operations currently running.");
+                           "Number of log GC operations currently running.",
+                           kudu::MetricLevel::kInfo);
 METRIC_DEFINE_histogram(tablet, log_gc_duration,
                         "Log GC Duration",
                         kudu::MetricUnit::kMilliseconds,
-                        "Time spent garbage collecting the logs.", 60000LU, 1);
+                        "Time spent garbage collecting the logs.",
+                        kudu::MetricLevel::kInfo,
+                        60000LU, 1);
 
 namespace kudu {
 namespace tablet {
diff --git a/src/kudu/tablet/transactions/transaction_tracker.cc b/src/kudu/tablet/transactions/transaction_tracker.cc
index 1c7d310..4b0ee90 100644
--- a/src/kudu/tablet/transactions/transaction_tracker.cc
+++ b/src/kudu/tablet/transactions/transaction_tracker.cc
@@ -53,21 +53,25 @@ TAG_FLAG(tablet_transaction_memory_limit_mb, advanced);
 METRIC_DEFINE_gauge_uint64(tablet, all_transactions_inflight,
                            "Transactions In Flight",
                            kudu::MetricUnit::kTransactions,
-                           "Number of transactions currently in-flight, including any type.");
+                           "Number of transactions currently in-flight, including any type.",
+                           kudu::MetricLevel::kDebug);
 METRIC_DEFINE_gauge_uint64(tablet, write_transactions_inflight,
                            "Write Transactions In Flight",
                            kudu::MetricUnit::kTransactions,
-                           "Number of write transactions currently in-flight");
+                           "Number of write transactions currently in-flight",
+                           kudu::MetricLevel::kDebug);
 METRIC_DEFINE_gauge_uint64(tablet, alter_schema_transactions_inflight,
                            "Alter Schema Transactions In Flight",
                            kudu::MetricUnit::kTransactions,
-                           "Number of alter schema transactions currently in-flight");
+                           "Number of alter schema transactions currently in-flight",
+                           kudu::MetricLevel::kDebug);
 
 METRIC_DEFINE_counter(tablet, transaction_memory_pressure_rejections,
                       "Transaction Memory Pressure Rejections",
                       kudu::MetricUnit::kTransactions,
                       "Number of transactions rejected because the tablet's "
-                      "transaction memory limit was reached.");
+                      "transaction memory limit was reached.",
+                      kudu::MetricLevel::kWarn);
 
 using std::shared_ptr;
 using std::string;
diff --git a/src/kudu/tserver/scanner_metrics.cc b/src/kudu/tserver/scanner_metrics.cc
index 503290e..4af5fcf 100644
--- a/src/kudu/tserver/scanner_metrics.cc
+++ b/src/kudu/tserver/scanner_metrics.cc
@@ -22,12 +22,14 @@
 METRIC_DEFINE_counter(server, scanners_expired,
                       "Scanners Expired",
                       kudu::MetricUnit::kScanners,
-                      "Number of scanners that have expired due to inactivity since service start");
+                      "Number of scanners that have expired due to inactivity since service start",
+                      kudu::MetricLevel::kWarn);
 
 METRIC_DEFINE_histogram(server, scanner_duration,
                         "Scanner Duration",
                         kudu::MetricUnit::kMicroseconds,
                         "Histogram of the duration of active scanners on this server",
+                        kudu::MetricLevel::kInfo,
                         60000000LU, 2);
 
 namespace kudu {
diff --git a/src/kudu/tserver/scanners.cc b/src/kudu/tserver/scanners.cc
index ff97d55..2b1aa7b 100644
--- a/src/kudu/tserver/scanners.cc
+++ b/src/kudu/tserver/scanners.cc
@@ -63,7 +63,8 @@ TAG_FLAG(scan_history_count, experimental);
 METRIC_DEFINE_gauge_size(server, active_scanners,
                          "Active Scanners",
                          kudu::MetricUnit::kScanners,
-                         "Number of scanners that are currently active");
+                         "Number of scanners that are currently active",
+                         kudu::MetricLevel::kInfo);
 
 using std::string;
 using std::unique_ptr;
diff --git a/src/kudu/tserver/tablet_copy_client.cc b/src/kudu/tserver/tablet_copy_client.cc
index f724c7f..a80993b 100644
--- a/src/kudu/tserver/tablet_copy_client.cc
+++ b/src/kudu/tserver/tablet_copy_client.cc
@@ -104,12 +104,14 @@ DECLARE_int32(tablet_copy_transfer_chunk_size_bytes);
 METRIC_DEFINE_counter(server, tablet_copy_bytes_fetched,
                       "Bytes Fetched By Tablet Copy",
                       kudu::MetricUnit::kBytes,
-                      "Number of bytes fetched during tablet copy operations since server start");
+                      "Number of bytes fetched during tablet copy operations since server start",
+                      kudu::MetricLevel::kDebug);
 
 METRIC_DEFINE_gauge_int32(server, tablet_copy_open_client_sessions,
                           "Open Table Copy Client Sessions",
                           kudu::MetricUnit::kSessions,
-                          "Number of currently open tablet copy client sessions on this server");
+                          "Number of currently open tablet copy client sessions on this server",
+                          kudu::MetricLevel::kInfo);
 
 // RETURN_NOT_OK_PREPEND() with a remote-error unwinding step.
 #define RETURN_NOT_OK_UNWIND_PREPEND(status, controller, msg) \
diff --git a/src/kudu/tserver/tablet_copy_source_session.cc b/src/kudu/tserver/tablet_copy_source_session.cc
index 546570d..6f38557 100644
--- a/src/kudu/tserver/tablet_copy_source_session.cc
+++ b/src/kudu/tserver/tablet_copy_source_session.cc
@@ -59,12 +59,14 @@ TAG_FLAG(tablet_copy_transfer_chunk_size_bytes, hidden);
 METRIC_DEFINE_counter(server, tablet_copy_bytes_sent,
                       "Bytes Sent For Tablet Copy",
                       kudu::MetricUnit::kBytes,
-                      "Number of bytes sent during tablet copy operations since server start");
+                      "Number of bytes sent during tablet copy operations since server start",
+                      kudu::MetricLevel::kDebug);
 
 METRIC_DEFINE_gauge_int32(server, tablet_copy_open_source_sessions,
                           "Open Table Copy Source Sessions",
                           kudu::MetricUnit::kSessions,
-                          "Number of currently open tablet copy source sessions on this server");
+                          "Number of currently open tablet copy source sessions on this server",
+                          kudu::MetricLevel::kInfo);
 
 DEFINE_int32(tablet_copy_session_inject_latency_on_init_ms, 0,
              "How much latency (in ms) to inject when a tablet copy session is initialized. "
diff --git a/src/kudu/tserver/tablet_server-stress-test.cc b/src/kudu/tserver/tablet_server-stress-test.cc
index 195f5a7..95d6a54 100644
--- a/src/kudu/tserver/tablet_server-stress-test.cc
+++ b/src/kudu/tserver/tablet_server-stress-test.cc
@@ -57,6 +57,7 @@ METRIC_DEFINE_histogram(test, insert_latency,
                         "Insert Latency",
                         kudu::MetricUnit::kMicroseconds,
                         "TabletServer single threaded insert latency.",
+                        kudu::MetricLevel::kInfo,
                         10000000,
                         2);
 
diff --git a/src/kudu/tserver/tablet_server-test.cc b/src/kudu/tserver/tablet_server-test.cc
index 467c74d..8d0590b 100644
--- a/src/kudu/tserver/tablet_server-test.cc
+++ b/src/kudu/tserver/tablet_server-test.cc
@@ -3456,6 +3456,7 @@ TEST_F(TabletServerTest, TestInsertLatencyMicroBenchmark) {
                           "Insert Latency",
                           MetricUnit::kMicroseconds,
                           "TabletServer single threaded insert latency.",
+                          kudu::MetricLevel::kInfo,
                           10000000,
                           2);
 
diff --git a/src/kudu/tserver/ts_tablet_manager.cc b/src/kudu/tserver/ts_tablet_manager.cc
index 1e71d3c..20e1e28 100644
--- a/src/kudu/tserver/ts_tablet_manager.cc
+++ b/src/kudu/tserver/ts_tablet_manager.cc
@@ -148,42 +148,50 @@ DECLARE_bool(raft_prepare_replacement_before_eviction);
 METRIC_DEFINE_gauge_int32(server, tablets_num_not_initialized,
                           "Number of Not Initialized Tablets",
                           kudu::MetricUnit::kTablets,
-                          "Number of tablets currently not initialized");
+                          "Number of tablets currently not initialized",
+                          kudu::MetricLevel::kInfo);
 
 METRIC_DEFINE_gauge_int32(server, tablets_num_initialized,
                           "Number of Initialized Tablets",
                           kudu::MetricUnit::kTablets,
-                          "Number of tablets currently initialized");
+                          "Number of tablets currently initialized",
+                          kudu::MetricLevel::kInfo);
 
 METRIC_DEFINE_gauge_int32(server, tablets_num_bootstrapping,
                           "Number of Bootstrapping Tablets",
                           kudu::MetricUnit::kTablets,
-                          "Number of tablets currently bootstrapping");
+                          "Number of tablets currently bootstrapping",
+                          kudu::MetricLevel::kInfo);
 
 METRIC_DEFINE_gauge_int32(server, tablets_num_running,
                           "Number of Running Tablets",
                           kudu::MetricUnit::kTablets,
-                          "Number of tablets currently running");
+                          "Number of tablets currently running",
+                          kudu::MetricLevel::kInfo);
 
 METRIC_DEFINE_gauge_int32(server, tablets_num_failed,
                           "Number of Failed Tablets",
                           kudu::MetricUnit::kTablets,
-                          "Number of failed tablets");
+                          "Number of failed tablets",
+                          kudu::MetricLevel::kWarn);
 
 METRIC_DEFINE_gauge_int32(server, tablets_num_stopping,
                           "Number of Stopping Tablets",
                           kudu::MetricUnit::kTablets,
-                          "Number of tablets currently stopping");
+                          "Number of tablets currently stopping",
+                          kudu::MetricLevel::kInfo);
 
 METRIC_DEFINE_gauge_int32(server, tablets_num_stopped,
                           "Number of Stopped Tablets",
                           kudu::MetricUnit::kTablets,
-                          "Number of tablets currently stopped");
+                          "Number of tablets currently stopped",
+                          kudu::MetricLevel::kInfo);
 
 METRIC_DEFINE_gauge_int32(server, tablets_num_shutdown,
                           "Number of Shut Down Tablets",
                           kudu::MetricUnit::kTablets,
-                          "Number of tablets currently shut down");
+                          "Number of tablets currently shut down",
+                          kudu::MetricLevel::kInfo);
 
 DECLARE_int32(heartbeat_interval_ms);
 
diff --git a/src/kudu/util/block_cache_metrics.cc b/src/kudu/util/block_cache_metrics.cc
index 60a946f..83529d7 100644
--- a/src/kudu/util/block_cache_metrics.cc
+++ b/src/kudu/util/block_cache_metrics.cc
@@ -21,33 +21,41 @@
 
 METRIC_DEFINE_counter(server, block_cache_inserts,
                       "Block Cache Inserts", kudu::MetricUnit::kBlocks,
-                      "Number of blocks inserted in the cache");
+                      "Number of blocks inserted in the cache",
+                      kudu::MetricLevel::kDebug);
 METRIC_DEFINE_counter(server, block_cache_lookups,
                       "Block Cache Lookups", kudu::MetricUnit::kBlocks,
-                      "Number of blocks looked up from the cache");
+                      "Number of blocks looked up from the cache",
+                      kudu::MetricLevel::kDebug);
 METRIC_DEFINE_counter(server, block_cache_evictions,
                       "Block Cache Evictions", kudu::MetricUnit::kBlocks,
-                      "Number of blocks evicted from the cache");
+                      "Number of blocks evicted from the cache",
+                      kudu::MetricLevel::kDebug);
 METRIC_DEFINE_counter(server, block_cache_misses,
                       "Block Cache Misses", kudu::MetricUnit::kBlocks,
-                      "Number of lookups that didn't yield a block");
+                      "Number of lookups that didn't yield a block",
+                      kudu::MetricLevel::kDebug);
 METRIC_DEFINE_counter(server, block_cache_misses_caching,
                       "Block Cache Misses (Caching)", kudu::MetricUnit::kBlocks,
                       "Number of lookups that were expecting a block that didn't yield one."
                       "Use this number instead of cache_misses when trying to determine how "
-                      "efficient the cache is");
+                      "efficient the cache is",
+                      kudu::MetricLevel::kDebug);
 METRIC_DEFINE_counter(server, block_cache_hits,
                       "Block Cache Hits", kudu::MetricUnit::kBlocks,
-                      "Number of lookups that found a block");
+                      "Number of lookups that found a block",
+                      kudu::MetricLevel::kDebug);
 METRIC_DEFINE_counter(server, block_cache_hits_caching,
                       "Block Cache Hits (Caching)", kudu::MetricUnit::kBlocks,
                       "Number of lookups that were expecting a block that found one."
                       "Use this number instead of cache_hits when trying to determine how "
-                      "efficient the cache is");
+                      "efficient the cache is",
+                      kudu::MetricLevel::kDebug);
 
 METRIC_DEFINE_gauge_uint64(server, block_cache_usage, "Block Cache Memory Usage",
                            kudu::MetricUnit::kBytes,
-                           "Memory consumed by the block cache");
+                           "Memory consumed by the block cache",
+                           kudu::MetricLevel::kInfo);
 
 namespace kudu {
 
diff --git a/src/kudu/util/file_cache_metrics.cc b/src/kudu/util/file_cache_metrics.cc
index befdda6..ca74191 100644
--- a/src/kudu/util/file_cache_metrics.cc
+++ b/src/kudu/util/file_cache_metrics.cc
@@ -21,34 +21,42 @@
 
 METRIC_DEFINE_counter(server, file_cache_inserts,
                       "File Cache Inserts", kudu::MetricUnit::kEntries,
-                      "Number of file descriptors inserted in the cache");
+                      "Number of file descriptors inserted in the cache",
+                      kudu::MetricLevel::kDebug);
 METRIC_DEFINE_counter(server, file_cache_lookups,
                       "File Cache Lookups", kudu::MetricUnit::kEntries,
-                      "Number of file descriptors looked up from the cache");
+                      "Number of file descriptors looked up from the cache",
+                      kudu::MetricLevel::kDebug);
 METRIC_DEFINE_counter(server, file_cache_evictions,
                       "File Cache Evictions", kudu::MetricUnit::kEntries,
-                      "Number of file descriptors evicted from the cache");
+                      "Number of file descriptors evicted from the cache",
+                      kudu::MetricLevel::kDebug);
 METRIC_DEFINE_counter(server, file_cache_misses,
                       "File Cache Misses", kudu::MetricUnit::kEntries,
-                      "Number of lookups that didn't yield a file descriptor");
+                      "Number of lookups that didn't yield a file descriptor",
+                      kudu::MetricLevel::kDebug);
 METRIC_DEFINE_counter(server, file_cache_misses_caching,
                       "File Cache Misses (Caching)", kudu::MetricUnit::kEntries,
                       "Number of lookups that were expecting a file descriptor "
                       "that didn't yield one. Use this number instead of "
                       "cache_misses when trying to determine how "
-                      "efficient the cache is");
+                      "efficient the cache is",
+                      kudu::MetricLevel::kDebug);
 METRIC_DEFINE_counter(server, file_cache_hits,
                       "File Cache Hits", kudu::MetricUnit::kEntries,
-                      "Number of lookups that found a file descriptor");
+                      "Number of lookups that found a file descriptor",
+                      kudu::MetricLevel::kDebug);
 METRIC_DEFINE_counter(server, file_cache_hits_caching,
                       "File Cache Hits (Caching)", kudu::MetricUnit::kEntries,
                       "Number of lookups that were expecting a file descriptor "
                       "that found one. Use this number instead of cache_hits "
-                      "when trying to determine how efficient the cache is");
+                      "when trying to determine how efficient the cache is",
+                      kudu::MetricLevel::kDebug);
 
 METRIC_DEFINE_gauge_uint64(server, file_cache_usage, "File Cache Usage",
                            kudu::MetricUnit::kEntries,
-                           "Number of entries in the file cache");
+                           "Number of entries in the file cache",
+                           kudu::MetricLevel::kInfo);
 
 namespace kudu {
 
diff --git a/src/kudu/util/maintenance_manager-test.cc b/src/kudu/util/maintenance_manager-test.cc
index 51f9fcd..0c5bf4d 100644
--- a/src/kudu/util/maintenance_manager-test.cc
+++ b/src/kudu/util/maintenance_manager-test.cc
@@ -54,10 +54,13 @@ METRIC_DEFINE_entity(test);
 METRIC_DEFINE_gauge_uint32(test, maintenance_ops_running,
                            "Number of Maintenance Operations Running",
                            kudu::MetricUnit::kMaintenanceOperations,
-                           "The number of background maintenance operations currently running.");
+                           "The number of background maintenance operations currently running.",
+                           kudu::MetricLevel::kInfo);
 METRIC_DEFINE_histogram(test, maintenance_op_duration,
                         "Maintenance Operation Duration",
-                        kudu::MetricUnit::kSeconds, "", 60000000LU, 2);
+                        kudu::MetricUnit::kSeconds, "",
+                        kudu::MetricLevel::kInfo,
+                        60000000LU, 2);
 
 DECLARE_int64(log_target_replay_size_mb);
 DECLARE_double(maintenance_op_multiplier);
diff --git a/src/kudu/util/metrics-test.cc b/src/kudu/util/metrics-test.cc
index 55ddecf..1a5f1ed 100644
--- a/src/kudu/util/metrics-test.cc
+++ b/src/kudu/util/metrics-test.cc
@@ -54,6 +54,8 @@ using std::vector;
 
 DECLARE_int32(metrics_retirement_age_ms);
 
+DECLARE_string(metrics_default_level);
+
 namespace kudu {
 
 METRIC_DEFINE_entity(test_entity);
@@ -83,7 +85,8 @@ class MetricsTest : public KuduTest {
 };
 
 METRIC_DEFINE_counter(test_entity, test_counter, "My Test Counter", MetricUnit::kRequests,
-                      "Description of test counter");
+                      "Description of test counter",
+                      kudu::MetricLevel::kInfo);
 
 TEST_F(MetricsTest, SimpleCounterTest) {
   scoped_refptr<Counter> requests =
@@ -115,7 +118,8 @@ TEST_F(MetricsTest, SimpleCounterMergeTest) {
 }
 
 METRIC_DEFINE_gauge_string(test_entity, test_string_gauge, "Test string Gauge",
-                           MetricUnit::kState, "Description of string Gauge");
+                           MetricUnit::kState, "Description of string Gauge",
+                           kudu::MetricLevel::kInfo);
 
 TEST_F(MetricsTest, SimpleStringGaugeTest) {
   scoped_refptr<StringGauge> state =
@@ -169,7 +173,8 @@ TEST_F(MetricsTest, SimpleStringGaugeForMergeTest) {
 }
 
 METRIC_DEFINE_gauge_double(test_entity, test_mean_gauge, "Test mean Gauge",
-                           MetricUnit::kUnits, "Description of mean Gauge");
+                           MetricUnit::kUnits, "Description of mean Gauge",
+                           kudu::MetricLevel::kInfo);
 
 TEST_F(MetricsTest, SimpleMeanGaugeTest) {
   scoped_refptr<MeanGauge> average_usage =
@@ -202,7 +207,8 @@ TEST_F(MetricsTest, SimpleMeanGaugeMergeTest) {
 }
 
 METRIC_DEFINE_gauge_uint64(test_entity, test_gauge, "Test uint64 Gauge",
-                           MetricUnit::kBytes, "Description of Test Gauge");
+                           MetricUnit::kBytes, "Description of Test Gauge",
+                           kudu::MetricLevel::kInfo);
 
 TEST_F(MetricsTest, SimpleAtomicGaugeTest) {
   scoped_refptr<AtomicGauge<uint64_t> > mem_usage =
@@ -232,7 +238,8 @@ TEST_F(MetricsTest, SimpleAtomicGaugeMergeTest) {
 }
 
 METRIC_DEFINE_gauge_int64(test_entity, test_func_gauge, "Test Function Gauge",
-                          MetricUnit::kBytes, "Test Gauge 2");
+                          MetricUnit::kBytes, "Test Gauge 2",
+                          kudu::MetricLevel::kInfo);
 
 static int64_t MyFunction(int* metric_val) {
   return (*metric_val)++;
@@ -258,7 +265,8 @@ TEST_F(MetricsTest, SimpleFunctionGaugeTest) {
 }
 
 METRIC_DEFINE_gauge_int64(test_entity, test_func_gauge_snapshot, "Test Function Gauge snapshot",
-                          MetricUnit::kOperations, "Description of Function Gauge snapshot");
+                          MetricUnit::kOperations, "Description of Function Gauge snapshot",
+                          kudu::MetricLevel::kInfo);
 class FunctionGaugeOwner {
  public:
   explicit FunctionGaugeOwner(const scoped_refptr<MetricEntity>& entity) {
@@ -368,13 +376,16 @@ TEST_F(MetricsTest, AutoDetachToConstant) {
 
 METRIC_DEFINE_gauge_uint64(test_entity, counter_as_gauge, "Gauge exposed as Counter",
                            MetricUnit::kBytes, "Gauge exposed as Counter",
+                           kudu::MetricLevel::kInfo,
                            EXPOSE_AS_COUNTER);
 TEST_F(MetricsTest, TEstExposeGaugeAsCounter) {
   ASSERT_EQ(MetricType::kCounter, METRIC_counter_as_gauge.type());
 }
 
 METRIC_DEFINE_histogram(test_entity, test_hist, "Test Histogram",
-                        MetricUnit::kMilliseconds, "foo", 1000000, 3);
+                        MetricUnit::kMilliseconds, "foo",
+                        MetricLevel::kInfo,
+                        1000000, 3);
 
 TEST_F(MetricsTest, SimpleHistogramTest) {
   scoped_refptr<Histogram> hist = METRIC_test_hist.Instantiate(entity_);
@@ -702,6 +713,7 @@ TEST_F(MetricsTest, TestDumpJsonPrototypes) {
     "            \"type\": \"gauge\",\n"
     "            \"unit\": \"bytes\",\n"
     "            \"description\": \"Test Gauge 2\",\n"
+    "            \"level\": \"info\",\n"
     "            \"entity_type\": \"test_entity\"\n"
     "        }";
   ASSERT_STR_CONTAINS(json, expected);
@@ -789,6 +801,14 @@ TEST_F(MetricsTest, TestDontDumpUntouched) {
   ASSERT_STR_CONTAINS(out.str(), "test_gauge");
 }
 
+METRIC_DEFINE_counter(test_entity, warn_counter, "Warn Metric", MetricUnit::kRequests,
+                      "Description of warn metric",
+                      kudu::MetricLevel::kWarn);
+
+METRIC_DEFINE_counter(test_entity, debug_counter, "Debug Metric", MetricUnit::kRequests,
+                      "Description of debug metric",
+                      kudu::MetricLevel::kDebug);
+
 TEST_F(MetricsTest, TestFilter) {
   const int32_t kNum = 4;
   vector<string> id_uuids;
@@ -817,6 +837,14 @@ TEST_F(MetricsTest, TestFilter) {
     attr2_uuids.emplace_back(attr2_uuid);
   }
 
+  // Add 1 warn and 1 debug entity and metric.
+  scoped_refptr<MetricEntity> warnEntity =
+      METRIC_ENTITY_test_entity.Instantiate(&registry_, oid.Next());
+  scoped_refptr<Counter> warnMetric = METRIC_warn_counter.Instantiate(warnEntity);
+  scoped_refptr<MetricEntity> debugEntity =
+      METRIC_ENTITY_test_entity.Instantiate(&registry_, oid.Next());
+  scoped_refptr<Counter> debugMetric = METRIC_debug_counter.Instantiate(debugEntity);
+
   // 2.Check the filter.
   Random rand(SeedRandom());
   const string not_exist_string = "not_exist_string";
@@ -840,7 +868,7 @@ TEST_F(MetricsTest, TestFilter) {
       ASSERT_OK(registry_.WriteAsJson(&w, opts));
       rapidjson::Document d;
       d.Parse<0>(out.str().c_str());
-      ASSERT_EQ(kNum + kEntityCount, d.Size());
+      ASSERT_EQ(kNum + kEntityCount + 2, d.Size());
       ASSERT_EQ(entity_type, d[rand.Next() % kNum]["type"].GetString());
     }
   }
@@ -918,14 +946,42 @@ TEST_F(MetricsTest, TestFilter) {
       ASSERT_EQ(kNum, d.Size());
     }
   }
-  // 2.5 Default filter condition.
+  // 2.5 Filter the 'level'
+  {
+    // Higher level.
+    {
+      const string entity_level = "warn";
+      std::ostringstream out;
+      MetricJsonOptions opts;
+      opts.filters.entity_level = entity_level;
+      JsonWriter w(&out, JsonWriter::PRETTY);
+      ASSERT_OK(registry_.WriteAsJson(&w, opts));
+      rapidjson::Document d;
+      d.Parse<0>(out.str().c_str());
+      ASSERT_EQ(kEntityCount + 1, d.Size());
+    }
+    // Debug level includes info and warn level.
+    {
+      const string entity_level = "debug";
+      std::ostringstream out;
+      MetricJsonOptions opts;
+      opts.filters.entity_level = entity_level;
+      JsonWriter w(&out, JsonWriter::PRETTY);
+      ASSERT_OK(registry_.WriteAsJson(&w, opts));
+      rapidjson::Document d;
+      d.Parse<0>(out.str().c_str());
+      ASSERT_EQ(kNum + kEntityCount + 2, d.Size());
+    }
+  }
+
+  // 2.6 Default filter condition.
   {
     std::ostringstream out;
     JsonWriter w(&out, JsonWriter::PRETTY);
     ASSERT_OK(registry_.WriteAsJson(&w, MetricJsonOptions()));
     rapidjson::Document d;
     d.Parse<0>(out.str().c_str());
-    ASSERT_EQ(kNum + kEntityCount, d.Size());
+    ASSERT_EQ(kNum + kEntityCount + 2, d.Size());
   }
 }
 
diff --git a/src/kudu/util/metrics.cc b/src/kudu/util/metrics.cc
index 3dd98da..9628447 100644
--- a/src/kudu/util/metrics.cc
+++ b/src/kudu/util/metrics.cc
@@ -225,21 +225,52 @@ scoped_refptr<Metric> MetricEntity::FindOrNull(const MetricPrototype& prototype)
 
 namespace {
 
-bool MatchNameInList(const string& name, const vector<string>& names) {
+bool MatchName(const string& name, const string& other) {
   string name_uc;
   ToUpperCase(name, &name_uc);
 
-  for (const string& e : names) {
-    // The parameter is a case-insensitive substring match of the metric name.
-    string e_uc;
-    ToUpperCase(e, &e_uc);
-    if (name_uc.find(e_uc) != string::npos) {
+  string other_uc;
+  ToUpperCase(other, &other_uc);
+
+  // The parameter is a case-insensitive substring match of the metric name.
+  return name_uc.find(other_uc) != string::npos;
+}
+
+bool MatchNameInList(const string& name, const vector<string>& names) {
+  for (const string& other : names) {
+    if (MatchName(name, other)) {
       return true;
     }
   }
   return false;
 }
 
+const char* MetricLevelName(MetricLevel level) {
+  switch (level) {
+    case MetricLevel::kDebug:
+      return "debug";
+    case MetricLevel::kInfo:
+      return "info";
+    case MetricLevel::kWarn:
+      return "warn";
+    default:
+      return "UNKNOWN LEVEL";
+  }
+}
+
+int MetricLevelNumeric(MetricLevel level) {
+  switch (level) {
+    case MetricLevel::kDebug:
+      return 0;
+    case MetricLevel::kInfo:
+      return 1;
+    case MetricLevel::kWarn:
+      return 2;
+    default:
+      LOG(FATAL) << "Unknown metric level";
+  }
+}
+
 } // anonymous namespace
 
 Status MetricEntity::GetMetricsAndAttrs(const MetricFilters& filters,
@@ -299,6 +330,30 @@ Status MetricEntity::GetMetricsAndAttrs(const MetricFilters& filters,
     }
   }
 
+  // Filter the metrics by 'level'.
+  // Includes all levels above the lowest matched level.
+  int lowest = MetricLevelNumeric(MetricLevel::kDebug); // Default to the lowest level.
+  if (!filters.entity_level.empty()) {
+    if (MatchName(MetricLevelName(MetricLevel::kDebug), filters.entity_level)) {
+      lowest = MetricLevelNumeric(MetricLevel::kDebug);
+    } else if (MatchName(MetricLevelName(MetricLevel::kInfo), filters.entity_level)) {
+      lowest = MetricLevelNumeric(MetricLevel::kInfo);
+    } else if (MatchName(MetricLevelName(MetricLevel::kWarn), filters.entity_level)) {
+      lowest = MetricLevelNumeric(MetricLevel::kWarn);
+    }
+  }
+  for (auto metric = metrics->begin(); metric != metrics->end();) {
+    if (MetricLevelNumeric(metric->first->level()) < lowest) {
+      metric = metrics->erase(metric);
+    } else {
+      ++metric;
+    }
+    // None of them match.
+    if (metrics->empty()) {
+      return Status::NotFound("entity is filtered by metric level");
+    }
+  }
+
   return Status::OK();
 }
 
@@ -581,6 +636,9 @@ void MetricPrototype::WriteFields(JsonWriter* writer,
 
     writer->String("description");
     writer->String(description());
+
+    writer->String("level");
+    writer->String(MetricLevelName(level()));
   }
 }
 
diff --git a/src/kudu/util/metrics.h b/src/kudu/util/metrics.h
index 4608770..5a3e391 100644
--- a/src/kudu/util/metrics.h
+++ b/src/kudu/util/metrics.h
@@ -102,6 +102,7 @@
 //                            "Threads Started",
 //                            kudu::MetricUnit::kThreads,
 //                            "Total number of threads started on this server",
+//                            kudu::MetricLevel::kInfo,
 //                            kudu::EXPOSE_AS_COUNTER);
 //
 //
@@ -138,7 +139,8 @@
 // 3) At the top of your .cc file where you want to emit a metric, define the metric prototype:
 //
 //   METRIC_DEFINE_counter(server, ping_requests, "Ping Requests", kudu::MetricUnit::kRequests,
-//       "Number of Ping() RPC requests this server has handled since start");
+//       "Number of Ping() RPC requests this server has handled since start",
+//       kudu::MetricLevel::kInfo);
 //
 // 4) In your class where you want to emit metrics, define the metric instance itself:
 //   scoped_refptr<Counter> ping_counter_;
@@ -162,7 +164,8 @@
 //
 //   METRIC_DEFINE_entity(my_entity);
 //   METRIC_DEFINE_counter(my_entity, ping_requests, "Ping Requests", kudu::MetricUnit::kRequests,
-//       "Number of Ping() RPC requests this particular entity has handled since start");
+//       "Number of Ping() RPC requests this particular entity has handled since start",
+//       kudu::MetricLevel::kInfo);
 //
 // In whatever class represents the entity:
 //
@@ -263,39 +266,40 @@
                            "Entities Count Merged From",                            \
                            kudu::MetricUnit::kEntries,                              \
                            "Count of entities merged together when entities are "   \
-                           "merged by common attribute value.");
+                           "merged by common attribute value.",                     \
+                           kudu::MetricLevel::kInfo);
 
 // Convenience macros to define metric prototypes.
 // See the documentation at the top of this file for example usage.
-#define METRIC_DEFINE_counter(entity, name, label, unit, desc)   \
+#define METRIC_DEFINE_counter(entity, name, label, unit, desc, level)   \
   ::kudu::CounterPrototype METRIC_##name(                        \
-      ::kudu::MetricPrototype::CtorArgs(#entity, #name, label, unit, desc))
+      ::kudu::MetricPrototype::CtorArgs(#entity, #name, label, unit, desc, level))
 
-#define METRIC_DEFINE_gauge_string(entity, name, label, unit, desc, ...) \
+#define METRIC_DEFINE_gauge_string(entity, name, label, unit, desc, level, ...) \
   ::kudu::GaugePrototype<std::string> METRIC_##name(                 \
-      ::kudu::MetricPrototype::CtorArgs(#entity, #name, label, unit, desc, ## __VA_ARGS__))
-#define METRIC_DEFINE_gauge_bool(entity, name, label, unit, desc, ...) \
+      ::kudu::MetricPrototype::CtorArgs(#entity, #name, label, unit, desc, level, ## __VA_ARGS__))
+#define METRIC_DEFINE_gauge_bool(entity, name, label, unit, desc, level, ...) \
   ::kudu::GaugePrototype<bool> METRIC_##  name(                    \
-      ::kudu::MetricPrototype::CtorArgs(#entity, #name, label, unit, desc, ## __VA_ARGS__))
-#define METRIC_DEFINE_gauge_int32(entity, name, label, unit, desc, ...) \
+      ::kudu::MetricPrototype::CtorArgs(#entity, #name, label, unit, desc, level, ## __VA_ARGS__))
+#define METRIC_DEFINE_gauge_int32(entity, name, label, unit, desc, level, ...) \
   ::kudu::GaugePrototype<int32_t> METRIC_##name(                   \
-      ::kudu::MetricPrototype::CtorArgs(#entity, #name, label, unit, desc, ## __VA_ARGS__))
-#define METRIC_DEFINE_gauge_uint32(entity, name, label, unit, desc, ...) \
+      ::kudu::MetricPrototype::CtorArgs(#entity, #name, label, unit, desc, level, ## __VA_ARGS__))
+#define METRIC_DEFINE_gauge_uint32(entity, name, label, unit, desc, level, ...) \
   ::kudu::GaugePrototype<uint32_t> METRIC_##name(                    \
-      ::kudu::MetricPrototype::CtorArgs(#entity, #name, label, unit, desc, ## __VA_ARGS__))
-#define METRIC_DEFINE_gauge_int64(entity, name, label, unit, desc, ...) \
+      ::kudu::MetricPrototype::CtorArgs(#entity, #name, label, unit, desc, level, ## __VA_ARGS__))
+#define METRIC_DEFINE_gauge_int64(entity, name, label, unit, desc, level, ...) \
   ::kudu::GaugePrototype<int64_t> METRIC_##name(                   \
-      ::kudu::MetricPrototype::CtorArgs(#entity, #name, label, unit, desc, ## __VA_ARGS__))
-#define METRIC_DEFINE_gauge_uint64(entity, name, label, unit, desc, ...) \
+      ::kudu::MetricPrototype::CtorArgs(#entity, #name, label, unit, desc, level, ## __VA_ARGS__))
+#define METRIC_DEFINE_gauge_uint64(entity, name, label, unit, desc, level, ...) \
   ::kudu::GaugePrototype<uint64_t> METRIC_##name(                    \
-      ::kudu::MetricPrototype::CtorArgs(#entity, #name, label, unit, desc, ## __VA_ARGS__))
-#define METRIC_DEFINE_gauge_double(entity, name, label, unit, desc, ...) \
+      ::kudu::MetricPrototype::CtorArgs(#entity, #name, label, unit, desc, level, ## __VA_ARGS__))
+#define METRIC_DEFINE_gauge_double(entity, name, label, unit, desc, level, ...) \
   ::kudu::GaugePrototype<double> METRIC_##name(                      \
-      ::kudu::MetricPrototype::CtorArgs(#entity, #name, label, unit, desc, ## __VA_ARGS__))
+      ::kudu::MetricPrototype::CtorArgs(#entity, #name, label, unit, desc, level, ## __VA_ARGS__))
 
-#define METRIC_DEFINE_histogram(entity, name, label, unit, desc, max_val, num_sig_digits) \
+#define METRIC_DEFINE_histogram(entity, name, label, unit, desc, level, max_val, num_sig_digits) \
   ::kudu::HistogramPrototype METRIC_##name(                                       \
-      ::kudu::MetricPrototype::CtorArgs(#entity, #name, label, unit, desc), \
+      ::kudu::MetricPrototype::CtorArgs(#entity, #name, label, unit, desc, level), \
     max_val, num_sig_digits)
 
 // The following macros act as forward declarations for entity types and metric prototypes.
@@ -321,9 +325,9 @@
   extern ::kudu::HistogramPrototype METRIC_##name
 
 #if defined(__APPLE__)
-#define METRIC_DEFINE_gauge_size(entity, name, label, unit, desc, ...) \
+#define METRIC_DEFINE_gauge_size(entity, name, label, unit, desc, level, ...) \
   ::kudu::GaugePrototype<size_t> METRIC_##name(                    \
-      ::kudu::MetricPrototype::CtorArgs(#entity, #name, label, unit, desc, ## __VA_ARGS__))
+      ::kudu::MetricPrototype::CtorArgs(#entity, #name, label, unit, desc, level, ## __VA_ARGS__))
 #define METRIC_DECLARE_gauge_size(name) \
   extern ::kudu::GaugePrototype<size_t> METRIC_##name
 #else
@@ -409,6 +413,23 @@ class MetricType {
   static const char* const kHistogramType;
 };
 
+// Severity level used with metrics.
+// Levels:
+//   - Debug: Metrics that are diagnostically helpful but generally not monitored
+//            during normal operation.
+//   - Info: Generally useful metrics that operators always want to have available
+//           but may not be monitored under normal circumstances.
+//   - Warn: Metrics which can often indicate operational oddities, which may need
+//           more investigation.
+//
+// The levels are ordered and lower levels include the levels above them:
+//    Debug < Info < Warn
+enum class MetricLevel {
+  kDebug = 0,
+  kInfo = 1,
+  kWarn = 2
+};
+
 struct MetricFilters {
   // A set of substrings to filter entity against, where empty matches all.
   //
@@ -425,6 +446,8 @@ struct MetricFilters {
   std::vector<std::string> entity_attrs;
   // entity metrics.
   std::vector<std::string> entity_metrics;
+  // entity level.
+  std::string entity_level;
 };
 
 struct MergeAttributes {
@@ -523,12 +546,14 @@ class MetricPrototype {
              const char* label,
              MetricUnit::Type unit,
              const char* description,
+             MetricLevel level,
              uint32_t flags = 0)
       : entity_type_(entity_type),
         name_(name),
         label_(label),
         unit_(unit),
         description_(description),
+        level_(level),
         flags_(flags) {
     }
 
@@ -537,6 +562,7 @@ class MetricPrototype {
     const char* const label_;
     const MetricUnit::Type unit_;
     const char* const description_;
+    const MetricLevel level_;
     const uint32_t flags_;
   };
 
@@ -546,6 +572,7 @@ class MetricPrototype {
   MetricUnit::Type unit() const { return args_.unit_; }
   const char* description() const { return args_.description_; }
   virtual MetricType::Type type() const = 0;
+  MetricLevel level() const { return args_.level_; }
 
   // Writes the fields of this prototype to the given JSON writer.
   void WriteFields(JsonWriter* writer,
@@ -1105,7 +1132,9 @@ class AtomicGauge : public Gauge {
 //
 // Example usage:
 //
-// METRIC_define_gauge_int64(my_metric, MetricUnit::kOperations, "My metric docs");
+// METRIC_define_gauge_int64(my_metric, MetricUnit::kOperations,
+//                           "My metric docs",
+//                           kudu::MetricLevel::kInfo);
 // class MyClassWithMetrics {
 //  public:
 //   MyClassWithMetrics(const scoped_refptr<MetricEntity>& entity) {
diff --git a/src/kudu/util/mt-metrics-test.cc b/src/kudu/util/mt-metrics-test.cc
index 2480d57..37fdde3 100644
--- a/src/kudu/util/mt-metrics-test.cc
+++ b/src/kudu/util/mt-metrics-test.cc
@@ -79,7 +79,8 @@ static void RunWithManyThreads(boost::function<void()>* f, int num_threads) {
 }
 
 METRIC_DEFINE_counter(test_entity, test_counter, "Test Counter",
-                      MetricUnit::kRequests, "Test counter");
+                      MetricUnit::kRequests, "Test counter",
+                      kudu::MetricLevel::kInfo);
 
 // Ensure that incrementing a counter is thread-safe.
 TEST_F(MultiThreadedMetricsTest, CounterIncrementTest) {
@@ -109,7 +110,8 @@ void MultiThreadedMetricsTest::RegisterCounters(
     string name = strings::Substitute("$0-$1-$2", name_prefix, tid, i);
     auto proto = new CounterPrototype(MetricPrototype::CtorArgs(
         "test_entity", strdup(name.c_str()), "Test Counter",
-        MetricUnit::kOperations, "test counter"));
+        MetricUnit::kOperations, "test counter",
+        MetricLevel::kInfo));
     proto->Instantiate(metric_entity)->Increment();
   }
 }
diff --git a/src/kudu/util/spinlock_profiling.cc b/src/kudu/util/spinlock_profiling.cc
index e7f93b0..e665f87 100644
--- a/src/kudu/util/spinlock_profiling.cc
+++ b/src/kudu/util/spinlock_profiling.cc
@@ -51,6 +51,7 @@ METRIC_DEFINE_gauge_uint64(server, spinlock_contention_time,
     "Amount of time consumed by contention on internal spinlocks since the server "
     "started. If this increases rapidly, it may indicate a performance issue in Kudu "
     "internals triggered by a particular workload and warrant investigation.",
+    kudu::MetricLevel::kWarn,
     kudu::EXPOSE_AS_COUNTER);
 
 
diff --git a/src/kudu/util/thread.cc b/src/kudu/util/thread.cc
index 223fbab..6697aa6 100644
--- a/src/kudu/util/thread.cc
+++ b/src/kudu/util/thread.cc
@@ -78,35 +78,41 @@ METRIC_DEFINE_gauge_uint64(server, threads_started,
                            "Threads Started",
                            kudu::MetricUnit::kThreads,
                            "Total number of threads started on this server",
+                           kudu::MetricLevel::kDebug,
                            kudu::EXPOSE_AS_COUNTER);
 
 METRIC_DEFINE_gauge_uint64(server, threads_running,
                            "Threads Running",
                            kudu::MetricUnit::kThreads,
-                           "Current number of running threads");
+                           "Current number of running threads",
+                           kudu::MetricLevel::kInfo);
 
 METRIC_DEFINE_gauge_uint64(server, cpu_utime,
                            "User CPU Time",
                            kudu::MetricUnit::kMilliseconds,
                            "Total user CPU time of the process",
+                           kudu::MetricLevel::kInfo,
                            kudu::EXPOSE_AS_COUNTER);
 
 METRIC_DEFINE_gauge_uint64(server, cpu_stime,
                            "System CPU Time",
                            kudu::MetricUnit::kMilliseconds,
                            "Total system CPU time of the process",
+                           kudu::MetricLevel::kInfo,
                            kudu::EXPOSE_AS_COUNTER);
 
 METRIC_DEFINE_gauge_uint64(server, voluntary_context_switches,
                            "Voluntary Context Switches",
                            kudu::MetricUnit::kContextSwitches,
                            "Total voluntary context switches",
+                           kudu::MetricLevel::kInfo,
                            kudu::EXPOSE_AS_COUNTER);
 
 METRIC_DEFINE_gauge_uint64(server, involuntary_context_switches,
                            "Involuntary Context Switches",
                            kudu::MetricUnit::kContextSwitches,
                            "Total involuntary context switches",
+                           kudu::MetricLevel::kInfo,
                            kudu::EXPOSE_AS_COUNTER);
 
 DEFINE_int32(thread_inject_start_latency_ms, 0,
diff --git a/src/kudu/util/threadpool-test.cc b/src/kudu/util/threadpool-test.cc
index f440cda..bf841d4 100644
--- a/src/kudu/util/threadpool-test.cc
+++ b/src/kudu/util/threadpool-test.cc
@@ -412,13 +412,19 @@ TEST_F(ThreadPoolTest, TestPromises) {
 
 METRIC_DEFINE_entity(test_entity);
 METRIC_DEFINE_histogram(test_entity, queue_length, "queue length",
-                        MetricUnit::kTasks, "queue length", 1000, 1);
+                        MetricUnit::kTasks, "queue length",
+                        kudu::MetricLevel::kInfo,
+                        1000, 1);
 
 METRIC_DEFINE_histogram(test_entity, queue_time, "queue time",
-                        MetricUnit::kMicroseconds, "queue time", 1000000, 1);
+                        MetricUnit::kMicroseconds, "queue time",
+                        kudu::MetricLevel::kInfo,
+                        1000000, 1);
 
 METRIC_DEFINE_histogram(test_entity, run_time, "run time",
-                        MetricUnit::kMicroseconds, "run time", 1000, 1);
+                        MetricUnit::kMicroseconds, "run time",
+                        kudu::MetricLevel::kInfo,
+                        1000, 1);
 
 TEST_F(ThreadPoolTest, TestMetrics) {
   MetricRegistry registry;
diff --git a/src/kudu/util/ttl_cache_test_metrics.cc b/src/kudu/util/ttl_cache_test_metrics.cc
index c71c541..1bb0e5f 100644
--- a/src/kudu/util/ttl_cache_test_metrics.cc
+++ b/src/kudu/util/ttl_cache_test_metrics.cc
@@ -22,37 +22,45 @@
 METRIC_DEFINE_counter(server, test_ttl_cache_inserts,
                       "TTL Cache Inserts",
                       kudu::MetricUnit::kEntries,
-                      "Number of entries inserted in the cache");
+                      "Number of entries inserted in the cache",
+                      kudu::MetricLevel::kInfo);
 METRIC_DEFINE_counter(server, test_ttl_cache_lookups,
                       "TTL Cache Lookups",
                       kudu::MetricUnit::kEntries,
-                      "Number of entries looked up from the cache");
+                      "Number of entries looked up from the cache",
+                      kudu::MetricLevel::kInfo);
 METRIC_DEFINE_counter(server, test_ttl_cache_evictions,
                       "TTL Cache Evictions",
                       kudu::MetricUnit::kEntries,
-                      "Number of entries evicted from the cache");
+                      "Number of entries evicted from the cache",
+                      kudu::MetricLevel::kInfo);
 METRIC_DEFINE_counter(server, test_ttl_cache_evictions_expired,
                       "TTL Cache Evictions of Expired Entries",
                       kudu::MetricUnit::kEntries,
                       "Number of entries that had already expired upon "
-                      "eviction from the cache");
+                      "eviction from the cache",
+                      kudu::MetricLevel::kInfo);
 METRIC_DEFINE_counter(server, test_ttl_cache_misses,
                       "TTL Cache Misses",
                       kudu::MetricUnit::kEntries,
-                      "Number of lookups that didn't find a cached entry");
+                      "Number of lookups that didn't find a cached entry",
+                      kudu::MetricLevel::kInfo);
 METRIC_DEFINE_counter(server, test_ttl_cache_hits,
                       "TTL Cache Hits",
                       kudu::MetricUnit::kEntries,
-                      "Number of lookups that found a cached entry");
+                      "Number of lookups that found a cached entry",
+                      kudu::MetricLevel::kInfo);
 METRIC_DEFINE_counter(server, test_ttl_cache_hits_expired,
                       "TTL Cache Hits of Expired Entries",
                       kudu::MetricUnit::kEntries,
                       "Number of lookups that found an entry, but the entry "
-                      "had already expired at the time of lookup");
+                      "had already expired at the time of lookup",
+                      kudu::MetricLevel::kInfo);
 METRIC_DEFINE_gauge_uint64(server, test_ttl_cache_memory_usage,
                            "TTL Cache Memory Usage",
                            kudu::MetricUnit::kBytes,
-                           "Memory consumed by the cache");
+                           "Memory consumed by the cache",
+                           kudu::MetricLevel::kInfo);
 
 namespace kudu {