diff --git a/BUILD b/BUILD
index 7b2cca3c1c3..4f9181a6d1c 100644
--- a/BUILD
+++ b/BUILD
@@ -2116,6 +2116,7 @@ grpc_cc_library(
         "//src/core:time",
         "//src/core:transport_fwd",
         "//src/core:try_seq",
+        "//src/core:unique_type_name",
         "//src/core:useful",
     ],
 )
diff --git a/src/core/BUILD b/src/core/BUILD
index e8fbbeeeebf..973cc9b1aa9 100644
--- a/src/core/BUILD
+++ b/src/core/BUILD
@@ -3073,6 +3073,7 @@ grpc_cc_library(
         "channel_fwd",
         "channel_stack_type",
         "interception_chain",
+        "unique_type_name",
         "//:channel_stack_builder",
         "//:debug_location",
         "//:gpr",
diff --git a/src/core/client_channel/client_channel_filter.cc b/src/core/client_channel/client_channel_filter.cc
index 7db7613f136..0ad970b5492 100644
--- a/src/core/client_channel/client_channel_filter.cc
+++ b/src/core/client_channel/client_channel_filter.cc
@@ -316,7 +316,7 @@ const grpc_channel_filter ClientChannelFilter::kFilter = {
     grpc_channel_stack_no_post_init,
     ClientChannelFilter::Destroy,
     ClientChannelFilter::GetChannelInfo,
-    "client-channel",
+    GRPC_UNIQUE_TYPE_NAME_HERE("client-channel"),
 };
 
 //
@@ -443,7 +443,7 @@ const grpc_channel_filter DynamicTerminationFilter::kFilterVtable = {
     grpc_channel_stack_no_post_init,
     DynamicTerminationFilter::Destroy,
     DynamicTerminationFilter::GetChannelInfo,
-    "dynamic_filter_termination",
+    GRPC_UNIQUE_TYPE_NAME_HERE("dynamic_filter_termination"),
 };
 
 }  // namespace
diff --git a/src/core/client_channel/dynamic_filters.cc b/src/core/client_channel/dynamic_filters.cc
index f901cf8b9bc..1e33da2105c 100644
--- a/src/core/client_channel/dynamic_filters.cc
+++ b/src/core/client_channel/dynamic_filters.cc
@@ -78,7 +78,9 @@ void DynamicFilters::Call::StartTransportStreamOpBatch(
     grpc_transport_stream_op_batch* batch) {
   grpc_call_stack* call_stack = CALL_TO_CALL_STACK(this);
   grpc_call_element* top_elem = grpc_call_stack_element(call_stack, 0);
-  GRPC_CALL_LOG_OP(GPR_INFO, top_elem, batch);
+  GRPC_TRACE_LOG(channel, INFO)
+      << "OP[" << top_elem->filter->name << ":" << top_elem
+      << "]: " << grpc_transport_stream_op_batch_string(batch, false);
   top_elem->filter->start_transport_stream_op_batch(top_elem, batch);
 }
 
diff --git a/src/core/client_channel/retry_filter.cc b/src/core/client_channel/retry_filter.cc
index f09d06d0e28..754a543d7eb 100644
--- a/src/core/client_channel/retry_filter.cc
+++ b/src/core/client_channel/retry_filter.cc
@@ -147,7 +147,7 @@ const grpc_channel_filter RetryFilter::kVtable = {
     grpc_channel_stack_no_post_init,
     RetryFilter::Destroy,
     RetryFilter::GetChannelInfo,
-    "retry_filter",
+    GRPC_UNIQUE_TYPE_NAME_HERE("retry_filter"),
 };
 
 }  // namespace grpc_core
diff --git a/src/core/client_channel/subchannel.cc b/src/core/client_channel/subchannel.cc
index b71df3cd9d6..9a76c22ae30 100644
--- a/src/core/client_channel/subchannel.cc
+++ b/src/core/client_channel/subchannel.cc
@@ -270,7 +270,9 @@ void SubchannelCall::StartTransportStreamOpBatch(
   MaybeInterceptRecvTrailingMetadata(batch);
   grpc_call_stack* call_stack = SUBCHANNEL_CALL_TO_CALL_STACK(this);
   grpc_call_element* top_elem = grpc_call_stack_element(call_stack, 0);
-  GRPC_CALL_LOG_OP(GPR_INFO, top_elem, batch);
+  GRPC_TRACE_LOG(channel, INFO)
+      << "OP[" << top_elem->filter->name << ":" << top_elem
+      << "]: " << grpc_transport_stream_op_batch_string(batch, false);
   top_elem->filter->start_transport_stream_op_batch(top_elem, batch);
 }
 
diff --git a/src/core/ext/filters/backend_metrics/backend_metric_filter.cc b/src/core/ext/filters/backend_metrics/backend_metric_filter.cc
index 082efb9716e..ebe189f9bea 100644
--- a/src/core/ext/filters/backend_metrics/backend_metric_filter.cc
+++ b/src/core/ext/filters/backend_metrics/backend_metric_filter.cc
@@ -117,8 +117,7 @@ absl::optional<std::string> MaybeSerializeBackendMetrics(
 }  // namespace
 
 const grpc_channel_filter BackendMetricFilter::kFilter =
-    MakePromiseBasedFilter<BackendMetricFilter, FilterEndpoint::kServer>(
-        "backend_metric");
+    MakePromiseBasedFilter<BackendMetricFilter, FilterEndpoint::kServer>();
 
 absl::StatusOr<std::unique_ptr<BackendMetricFilter>>
 BackendMetricFilter::Create(const ChannelArgs&, ChannelFilter::Args) {
diff --git a/src/core/ext/filters/backend_metrics/backend_metric_filter.h b/src/core/ext/filters/backend_metrics/backend_metric_filter.h
index 114fc3cc7bc..02ee8611dce 100644
--- a/src/core/ext/filters/backend_metrics/backend_metric_filter.h
+++ b/src/core/ext/filters/backend_metrics/backend_metric_filter.h
@@ -35,6 +35,8 @@ class BackendMetricFilter : public ImplementChannelFilter<BackendMetricFilter> {
  public:
   static const grpc_channel_filter kFilter;
 
+  static absl::string_view TypeName() { return "backend_metric"; }
+
   static absl::StatusOr<std::unique_ptr<BackendMetricFilter>> Create(
       const ChannelArgs& args, ChannelFilter::Args);
 
diff --git a/src/core/ext/filters/channel_idle/legacy_channel_idle_filter.cc b/src/core/ext/filters/channel_idle/legacy_channel_idle_filter.cc
index c2e82de4490..54e0c2a395f 100644
--- a/src/core/ext/filters/channel_idle/legacy_channel_idle_filter.cc
+++ b/src/core/ext/filters/channel_idle/legacy_channel_idle_filter.cc
@@ -289,11 +289,9 @@ void LegacyChannelIdleFilter::CloseChannel() {
 }
 
 const grpc_channel_filter LegacyClientIdleFilter::kFilter =
-    MakePromiseBasedFilter<LegacyClientIdleFilter, FilterEndpoint::kClient>(
-        "client_idle");
+    MakePromiseBasedFilter<LegacyClientIdleFilter, FilterEndpoint::kClient>();
 const grpc_channel_filter LegacyMaxAgeFilter::kFilter =
-    MakePromiseBasedFilter<LegacyMaxAgeFilter, FilterEndpoint::kServer>(
-        "max_age");
+    MakePromiseBasedFilter<LegacyMaxAgeFilter, FilterEndpoint::kServer>();
 
 void RegisterLegacyChannelIdleFilters(CoreConfiguration::Builder* builder) {
   builder->channel_init()
diff --git a/src/core/ext/filters/channel_idle/legacy_channel_idle_filter.h b/src/core/ext/filters/channel_idle/legacy_channel_idle_filter.h
index 001282276f1..9ee7981b2f5 100644
--- a/src/core/ext/filters/channel_idle/legacy_channel_idle_filter.h
+++ b/src/core/ext/filters/channel_idle/legacy_channel_idle_filter.h
@@ -96,6 +96,8 @@ class LegacyClientIdleFilter final : public LegacyChannelIdleFilter {
  public:
   static const grpc_channel_filter kFilter;
 
+  static absl::string_view TypeName() { return "client_idle"; }
+
   static absl::StatusOr<std::unique_ptr<LegacyClientIdleFilter>> Create(
       const ChannelArgs& args, ChannelFilter::Args filter_args);
 
@@ -107,6 +109,8 @@ class LegacyMaxAgeFilter final : public LegacyChannelIdleFilter {
   static const grpc_channel_filter kFilter;
   struct Config;
 
+  static absl::string_view TypeName() { return "max_age"; }
+
   static absl::StatusOr<std::unique_ptr<LegacyMaxAgeFilter>> Create(
       const ChannelArgs& args, ChannelFilter::Args filter_args);
 
diff --git a/src/core/ext/filters/fault_injection/fault_injection_filter.cc b/src/core/ext/filters/fault_injection/fault_injection_filter.cc
index 6190ad40084..033f8ee99c3 100644
--- a/src/core/ext/filters/fault_injection/fault_injection_filter.cc
+++ b/src/core/ext/filters/fault_injection/fault_injection_filter.cc
@@ -270,8 +270,7 @@ std::string FaultInjectionFilter::InjectionDecision::ToString() const {
 }
 
 const grpc_channel_filter FaultInjectionFilter::kFilter =
-    MakePromiseBasedFilter<FaultInjectionFilter, FilterEndpoint::kClient>(
-        "fault_injection_filter");
+    MakePromiseBasedFilter<FaultInjectionFilter, FilterEndpoint::kClient>();
 
 void FaultInjectionFilterRegister(CoreConfiguration::Builder* builder) {
   FaultInjectionServiceConfigParser::Register(builder);
diff --git a/src/core/ext/filters/fault_injection/fault_injection_filter.h b/src/core/ext/filters/fault_injection/fault_injection_filter.h
index 515df16a853..7bcd2227060 100644
--- a/src/core/ext/filters/fault_injection/fault_injection_filter.h
+++ b/src/core/ext/filters/fault_injection/fault_injection_filter.h
@@ -45,6 +45,8 @@ class FaultInjectionFilter
  public:
   static const grpc_channel_filter kFilter;
 
+  static absl::string_view TypeName() { return "fault_injection_filter"; }
+
   static absl::StatusOr<std::unique_ptr<FaultInjectionFilter>> Create(
       const ChannelArgs& args, ChannelFilter::Args filter_args);
 
diff --git a/src/core/ext/filters/http/client/http_client_filter.cc b/src/core/ext/filters/http/client/http_client_filter.cc
index 6af2b959be3..7fd04a371e4 100644
--- a/src/core/ext/filters/http/client/http_client_filter.cc
+++ b/src/core/ext/filters/http/client/http_client_filter.cc
@@ -59,7 +59,7 @@ const NoInterceptor HttpClientFilter::Call::OnFinalize;
 
 const grpc_channel_filter HttpClientFilter::kFilter =
     MakePromiseBasedFilter<HttpClientFilter, FilterEndpoint::kClient,
-                           kFilterExaminesServerInitialMetadata>("http-client");
+                           kFilterExaminesServerInitialMetadata>();
 
 namespace {
 absl::Status CheckServerMetadata(ServerMetadata* b) {
diff --git a/src/core/ext/filters/http/client/http_client_filter.h b/src/core/ext/filters/http/client/http_client_filter.h
index f985337f2ca..0b319cec303 100644
--- a/src/core/ext/filters/http/client/http_client_filter.h
+++ b/src/core/ext/filters/http/client/http_client_filter.h
@@ -35,6 +35,8 @@ class HttpClientFilter : public ImplementChannelFilter<HttpClientFilter> {
  public:
   static const grpc_channel_filter kFilter;
 
+  static absl::string_view TypeName() { return "http-client"; }
+
   static absl::StatusOr<std::unique_ptr<HttpClientFilter>> Create(
       const ChannelArgs& args, ChannelFilter::Args filter_args);
 
diff --git a/src/core/ext/filters/http/client_authority_filter.cc b/src/core/ext/filters/http/client_authority_filter.cc
index b6970d9ecb5..6dd44234151 100644
--- a/src/core/ext/filters/http/client_authority_filter.cc
+++ b/src/core/ext/filters/http/client_authority_filter.cc
@@ -66,8 +66,7 @@ void ClientAuthorityFilter::Call::OnClientInitialMetadata(
 }
 
 const grpc_channel_filter ClientAuthorityFilter::kFilter =
-    MakePromiseBasedFilter<ClientAuthorityFilter, FilterEndpoint::kClient>(
-        "authority");
+    MakePromiseBasedFilter<ClientAuthorityFilter, FilterEndpoint::kClient>();
 
 namespace {
 bool NeedsClientAuthorityFilter(const ChannelArgs& args) {
diff --git a/src/core/ext/filters/http/client_authority_filter.h b/src/core/ext/filters/http/client_authority_filter.h
index da154fbac5d..c3b817527c1 100644
--- a/src/core/ext/filters/http/client_authority_filter.h
+++ b/src/core/ext/filters/http/client_authority_filter.h
@@ -39,6 +39,8 @@ class ClientAuthorityFilter final
  public:
   static const grpc_channel_filter kFilter;
 
+  static absl::string_view TypeName() { return "authority"; }
+
   static absl::StatusOr<std::unique_ptr<ClientAuthorityFilter>> Create(
       const ChannelArgs& args, ChannelFilter::Args);
 
diff --git a/src/core/ext/filters/http/message_compress/compression_filter.cc b/src/core/ext/filters/http/message_compress/compression_filter.cc
index e3d0a61cd01..00839eebe5b 100644
--- a/src/core/ext/filters/http/message_compress/compression_filter.cc
+++ b/src/core/ext/filters/http/message_compress/compression_filter.cc
@@ -66,12 +66,12 @@ const grpc_channel_filter ClientCompressionFilter::kFilter =
     MakePromiseBasedFilter<ClientCompressionFilter, FilterEndpoint::kClient,
                            kFilterExaminesServerInitialMetadata |
                                kFilterExaminesInboundMessages |
-                               kFilterExaminesOutboundMessages>("compression");
+                               kFilterExaminesOutboundMessages>();
 const grpc_channel_filter ServerCompressionFilter::kFilter =
     MakePromiseBasedFilter<ServerCompressionFilter, FilterEndpoint::kServer,
                            kFilterExaminesServerInitialMetadata |
                                kFilterExaminesInboundMessages |
-                               kFilterExaminesOutboundMessages>("compression");
+                               kFilterExaminesOutboundMessages>();
 
 absl::StatusOr<std::unique_ptr<ClientCompressionFilter>>
 ClientCompressionFilter::Create(const ChannelArgs& args, ChannelFilter::Args) {
diff --git a/src/core/ext/filters/http/message_compress/compression_filter.h b/src/core/ext/filters/http/message_compress/compression_filter.h
index 5d82846d01d..ae3a9ee317e 100644
--- a/src/core/ext/filters/http/message_compress/compression_filter.h
+++ b/src/core/ext/filters/http/message_compress/compression_filter.h
@@ -25,6 +25,7 @@
 #include <stdint.h>
 
 #include "absl/status/statusor.h"
+#include "absl/strings/string_view.h"
 #include "absl/types/optional.h"
 
 #include <grpc/impl/compression_types.h>
@@ -110,6 +111,8 @@ class ClientCompressionFilter final
  public:
   static const grpc_channel_filter kFilter;
 
+  static absl::string_view TypeName() { return "compression"; }
+
   static absl::StatusOr<std::unique_ptr<ClientCompressionFilter>> Create(
       const ChannelArgs& args, ChannelFilter::Args filter_args);
 
@@ -147,6 +150,8 @@ class ServerCompressionFilter final
  public:
   static const grpc_channel_filter kFilter;
 
+  static absl::string_view TypeName() { return "compression"; }
+
   static absl::StatusOr<std::unique_ptr<ServerCompressionFilter>> Create(
       const ChannelArgs& args, ChannelFilter::Args filter_args);
 
diff --git a/src/core/ext/filters/http/server/http_server_filter.cc b/src/core/ext/filters/http/server/http_server_filter.cc
index 8d4b71d5108..0e863638901 100644
--- a/src/core/ext/filters/http/server/http_server_filter.cc
+++ b/src/core/ext/filters/http/server/http_server_filter.cc
@@ -55,7 +55,7 @@ const NoInterceptor HttpServerFilter::Call::OnFinalize;
 
 const grpc_channel_filter HttpServerFilter::kFilter =
     MakePromiseBasedFilter<HttpServerFilter, FilterEndpoint::kServer,
-                           kFilterExaminesServerInitialMetadata>("http-server");
+                           kFilterExaminesServerInitialMetadata>();
 
 namespace {
 void FilterOutgoingMetadata(ServerMetadata* md) {
diff --git a/src/core/ext/filters/http/server/http_server_filter.h b/src/core/ext/filters/http/server/http_server_filter.h
index a1f330e58bb..8f933865d7d 100644
--- a/src/core/ext/filters/http/server/http_server_filter.h
+++ b/src/core/ext/filters/http/server/http_server_filter.h
@@ -36,6 +36,8 @@ class HttpServerFilter : public ImplementChannelFilter<HttpServerFilter> {
  public:
   static const grpc_channel_filter kFilter;
 
+  static absl::string_view TypeName() { return "http-server"; }
+
   static absl::StatusOr<std::unique_ptr<HttpServerFilter>> Create(
       const ChannelArgs& args, ChannelFilter::Args filter_args);
 
diff --git a/src/core/ext/filters/load_reporting/server_load_reporting_filter.cc b/src/core/ext/filters/load_reporting/server_load_reporting_filter.cc
index 100584f5ba1..6b4f77bdae5 100644
--- a/src/core/ext/filters/load_reporting/server_load_reporting_filter.cc
+++ b/src/core/ext/filters/load_reporting/server_load_reporting_filter.cc
@@ -247,8 +247,8 @@ void ServerLoadReportingFilter::Call::OnFinalize(
 }
 
 const grpc_channel_filter ServerLoadReportingFilter::kFilter =
-    MakePromiseBasedFilter<ServerLoadReportingFilter, FilterEndpoint::kServer>(
-        "server_load_reporting");
+    MakePromiseBasedFilter<ServerLoadReportingFilter,
+                           FilterEndpoint::kServer>();
 
 // TODO(juanlishen): We should register the filter during grpc initialization
 // time once OpenCensus is compatible with our build system. For now, we force
diff --git a/src/core/ext/filters/load_reporting/server_load_reporting_filter.h b/src/core/ext/filters/load_reporting/server_load_reporting_filter.h
index 76684093a0b..41f66ec948d 100644
--- a/src/core/ext/filters/load_reporting/server_load_reporting_filter.h
+++ b/src/core/ext/filters/load_reporting/server_load_reporting_filter.h
@@ -39,6 +39,8 @@ class ServerLoadReportingFilter
  public:
   static const grpc_channel_filter kFilter;
 
+  static absl::string_view TypeName() { return "server_load_reporting"; }
+
   static absl::StatusOr<std::unique_ptr<ServerLoadReportingFilter>> Create(
       const ChannelArgs& args, ChannelFilter::Args);
 
diff --git a/src/core/ext/filters/logging/logging_filter.cc b/src/core/ext/filters/logging/logging_filter.cc
index 3d95d914585..c0a749d315e 100644
--- a/src/core/ext/filters/logging/logging_filter.cc
+++ b/src/core/ext/filters/logging/logging_filter.cc
@@ -417,7 +417,7 @@ const grpc_channel_filter ClientLoggingFilter::kFilter =
     MakePromiseBasedFilter<ClientLoggingFilter, FilterEndpoint::kClient,
                            kFilterExaminesServerInitialMetadata |
                                kFilterExaminesInboundMessages |
-                               kFilterExaminesOutboundMessages>("logging");
+                               kFilterExaminesOutboundMessages>();
 
 absl::StatusOr<std::unique_ptr<ServerLoggingFilter>>
 ServerLoggingFilter::Create(const ChannelArgs& /*args*/,
@@ -483,7 +483,7 @@ const grpc_channel_filter ServerLoggingFilter::kFilter =
     MakePromiseBasedFilter<ServerLoggingFilter, FilterEndpoint::kServer,
                            kFilterExaminesServerInitialMetadata |
                                kFilterExaminesInboundMessages |
-                               kFilterExaminesOutboundMessages>("logging");
+                               kFilterExaminesOutboundMessages>();
 
 void RegisterLoggingFilter(LoggingSink* sink) {
   g_logging_sink = sink;
diff --git a/src/core/ext/filters/logging/logging_filter.h b/src/core/ext/filters/logging/logging_filter.h
index 30c28a5b57a..5d8b77752cd 100644
--- a/src/core/ext/filters/logging/logging_filter.h
+++ b/src/core/ext/filters/logging/logging_filter.h
@@ -78,6 +78,8 @@ class ClientLoggingFilter final
  public:
   static const grpc_channel_filter kFilter;
 
+  static absl::string_view TypeName() { return "logging"; }
+
   static absl::StatusOr<std::unique_ptr<ClientLoggingFilter>> Create(
       const ChannelArgs& args, ChannelFilter::Args /*filter_args*/);
 
@@ -108,6 +110,8 @@ class ServerLoggingFilter final
  public:
   static const grpc_channel_filter kFilter;
 
+  static absl::string_view TypeName() { return "logging"; }
+
   static absl::StatusOr<std::unique_ptr<ServerLoggingFilter>> Create(
       const ChannelArgs& args, ChannelFilter::Args /*filter_args*/);
 
diff --git a/src/core/ext/filters/message_size/message_size_filter.cc b/src/core/ext/filters/message_size/message_size_filter.cc
index 3a8a3659a43..580770ede7b 100644
--- a/src/core/ext/filters/message_size/message_size_filter.cc
+++ b/src/core/ext/filters/message_size/message_size_filter.cc
@@ -137,12 +137,12 @@ size_t MessageSizeParser::ParserIndex() {
 const grpc_channel_filter ClientMessageSizeFilter::kFilter =
     MakePromiseBasedFilter<ClientMessageSizeFilter, FilterEndpoint::kClient,
                            kFilterExaminesOutboundMessages |
-                               kFilterExaminesInboundMessages>("message_size");
+                               kFilterExaminesInboundMessages>();
 
 const grpc_channel_filter ServerMessageSizeFilter::kFilter =
     MakePromiseBasedFilter<ServerMessageSizeFilter, FilterEndpoint::kServer,
                            kFilterExaminesOutboundMessages |
-                               kFilterExaminesInboundMessages>("message_size");
+                               kFilterExaminesInboundMessages>();
 
 absl::StatusOr<std::unique_ptr<ClientMessageSizeFilter>>
 ClientMessageSizeFilter::Create(const ChannelArgs& args, ChannelFilter::Args) {
diff --git a/src/core/ext/filters/message_size/message_size_filter.h b/src/core/ext/filters/message_size/message_size_filter.h
index 970604fe35a..3ed3b2b735b 100644
--- a/src/core/ext/filters/message_size/message_size_filter.h
+++ b/src/core/ext/filters/message_size/message_size_filter.h
@@ -89,6 +89,8 @@ class ServerMessageSizeFilter final
  public:
   static const grpc_channel_filter kFilter;
 
+  static absl::string_view TypeName() { return "message_size"; }
+
   static absl::StatusOr<std::unique_ptr<ServerMessageSizeFilter>> Create(
       const ChannelArgs& args, ChannelFilter::Args filter_args);
 
@@ -117,6 +119,8 @@ class ClientMessageSizeFilter final
  public:
   static const grpc_channel_filter kFilter;
 
+  static absl::string_view TypeName() { return "message_size"; }
+
   static absl::StatusOr<std::unique_ptr<ClientMessageSizeFilter>> Create(
       const ChannelArgs& args, ChannelFilter::Args filter_args);
 
diff --git a/src/core/ext/filters/rbac/rbac_filter.cc b/src/core/ext/filters/rbac/rbac_filter.cc
index a86636b10a8..583042786f0 100644
--- a/src/core/ext/filters/rbac/rbac_filter.cc
+++ b/src/core/ext/filters/rbac/rbac_filter.cc
@@ -71,7 +71,7 @@ absl::Status RbacFilter::Call::OnClientInitialMetadata(ClientMetadata& md,
 }
 
 const grpc_channel_filter RbacFilter::kFilterVtable =
-    MakePromiseBasedFilter<RbacFilter, FilterEndpoint::kServer>("rbac_filter");
+    MakePromiseBasedFilter<RbacFilter, FilterEndpoint::kServer>();
 
 RbacFilter::RbacFilter(size_t index,
                        EvaluateArgs::PerChannelArgs per_channel_evaluate_args)
diff --git a/src/core/ext/filters/rbac/rbac_filter.h b/src/core/ext/filters/rbac/rbac_filter.h
index d033b799d5f..f41e8490ccf 100644
--- a/src/core/ext/filters/rbac/rbac_filter.h
+++ b/src/core/ext/filters/rbac/rbac_filter.h
@@ -42,6 +42,8 @@ class RbacFilter : public ImplementChannelFilter<RbacFilter> {
   // and enforces the RBAC policy.
   static const grpc_channel_filter kFilterVtable;
 
+  static absl::string_view TypeName() { return "rbac_filter"; }
+
   static absl::StatusOr<std::unique_ptr<RbacFilter>> Create(
       const ChannelArgs& args, ChannelFilter::Args filter_args);
 
diff --git a/src/core/ext/filters/stateful_session/stateful_session_filter.cc b/src/core/ext/filters/stateful_session/stateful_session_filter.cc
index 246605a490b..c677bd2cc1d 100644
--- a/src/core/ext/filters/stateful_session/stateful_session_filter.cc
+++ b/src/core/ext/filters/stateful_session/stateful_session_filter.cc
@@ -69,8 +69,7 @@ UniqueTypeName XdsOverrideHostAttribute::TypeName() {
 
 const grpc_channel_filter StatefulSessionFilter::kFilter =
     MakePromiseBasedFilter<StatefulSessionFilter, FilterEndpoint::kClient,
-                           kFilterExaminesServerInitialMetadata>(
-        "stateful_session_filter");
+                           kFilterExaminesServerInitialMetadata>();
 
 absl::StatusOr<std::unique_ptr<StatefulSessionFilter>>
 StatefulSessionFilter::Create(const ChannelArgs&,
diff --git a/src/core/ext/filters/stateful_session/stateful_session_filter.h b/src/core/ext/filters/stateful_session/stateful_session_filter.h
index 64c488bce33..3bffbaa8547 100644
--- a/src/core/ext/filters/stateful_session/stateful_session_filter.h
+++ b/src/core/ext/filters/stateful_session/stateful_session_filter.h
@@ -74,6 +74,8 @@ class StatefulSessionFilter
  public:
   static const grpc_channel_filter kFilter;
 
+  static absl::string_view TypeName() { return "stateful_session_filter"; }
+
   static absl::StatusOr<std::unique_ptr<StatefulSessionFilter>> Create(
       const ChannelArgs& args, ChannelFilter::Args filter_args);
 
diff --git a/src/core/lib/channel/channel_stack.cc b/src/core/lib/channel/channel_stack.cc
index 63e322d6b93..36e3461700a 100644
--- a/src/core/lib/channel/channel_stack.cc
+++ b/src/core/lib/channel/channel_stack.cc
@@ -262,7 +262,9 @@ void grpc_call_stack_destroy(grpc_call_stack* stack,
 void grpc_call_next_op(grpc_call_element* elem,
                        grpc_transport_stream_op_batch* op) {
   grpc_call_element* next_elem = elem + 1;
-  GRPC_CALL_LOG_OP(GPR_INFO, next_elem, op);
+  GRPC_TRACE_LOG(channel, INFO)
+      << "OP[" << elem->filter->name << ":" << elem
+      << "]: " << grpc_transport_stream_op_batch_string(op, false);
   next_elem->filter->start_transport_stream_op_batch(next_elem, op);
 }
 
@@ -292,10 +294,3 @@ grpc_call_stack* grpc_call_stack_from_top_element(grpc_call_element* elem) {
 
 void grpc_channel_stack_no_post_init(grpc_channel_stack*,
                                      grpc_channel_element*) {}
-
-void grpc_call_log_op(const char* file, int line, gpr_log_severity severity,
-                      grpc_call_element* elem,
-                      grpc_transport_stream_op_batch* op) {
-  gpr_log(file, line, severity, "OP[%s:%p]: %s", elem->filter->name, elem,
-          grpc_transport_stream_op_batch_string(op, false).c_str());
-}
diff --git a/src/core/lib/channel/channel_stack.h b/src/core/lib/channel/channel_stack.h
index ff0fc291c0a..f21c1dc0d8e 100644
--- a/src/core/lib/channel/channel_stack.h
+++ b/src/core/lib/channel/channel_stack.h
@@ -63,6 +63,7 @@
 #include "src/core/lib/gprpp/manual_constructor.h"
 #include "src/core/lib/gprpp/ref_counted_ptr.h"
 #include "src/core/lib/gprpp/time.h"
+#include "src/core/lib/gprpp/unique_type_name.h"
 #include "src/core/lib/iomgr/call_combiner.h"
 #include "src/core/lib/iomgr/closure.h"
 #include "src/core/lib/iomgr/error.h"
@@ -159,7 +160,7 @@ struct grpc_channel_filter {
                            const grpc_channel_info* channel_info);
 
   // The name of this filter
-  const char* name;
+  grpc_core::UniqueTypeName name;
 };
 // A channel_element tracks its filter and the filter requested memory within
 // a channel allocation
@@ -357,18 +358,7 @@ grpc_channel_stack* grpc_channel_stack_from_top_element(
 // Given the top element of a call stack, get the call stack itself
 grpc_call_stack* grpc_call_stack_from_top_element(grpc_call_element* elem);
 
-void grpc_call_log_op(const char* file, int line, gpr_log_severity severity,
-                      grpc_call_element* elem,
-                      grpc_transport_stream_op_batch* op);
-
 void grpc_channel_stack_no_post_init(grpc_channel_stack* stk,
                                      grpc_channel_element* elem);
 
-#define GRPC_CALL_LOG_OP(sev, elem, op)     \
-  do {                                      \
-    if (GRPC_TRACE_FLAG_ENABLED(channel)) { \
-      grpc_call_log_op(sev, elem, op);      \
-    }                                       \
-  } while (0)
-
 #endif  // GRPC_SRC_CORE_LIB_CHANNEL_CHANNEL_STACK_H
diff --git a/src/core/lib/channel/connected_channel.cc b/src/core/lib/channel/connected_channel.cc
index 5507e1ef65e..f24304bac89 100644
--- a/src/core/lib/channel/connected_channel.cc
+++ b/src/core/lib/channel/connected_channel.cc
@@ -267,7 +267,7 @@ const grpc_channel_filter kConnectedFilter{
     },
     connected_channel_destroy_channel_elem,
     connected_channel_get_channel_info,
-    "connected",
+    GRPC_UNIQUE_TYPE_NAME_HERE("connected"),
 };
 
 // noop filter for the v3 stack: placeholder for now because other code requires
@@ -288,7 +288,7 @@ const grpc_channel_filter kPromiseBasedTransportFilter = {
     +[](grpc_channel_stack*, grpc_channel_element*) {},
     connected_channel_destroy_channel_elem,
     connected_channel_get_channel_info,
-    "connected",
+    GRPC_UNIQUE_TYPE_NAME_HERE("connected"),
 };
 
 bool TransportSupportsClientPromiseBasedCalls(const ChannelArgs& args) {
diff --git a/src/core/lib/channel/promise_based_filter.cc b/src/core/lib/channel/promise_based_filter.cc
index e2d9d8cffff..946be3b2af7 100644
--- a/src/core/lib/channel/promise_based_filter.cc
+++ b/src/core/lib/channel/promise_based_filter.cc
@@ -1316,7 +1316,7 @@ ClientCallData::~ClientCallData() {
 }
 
 std::string ClientCallData::DebugTag() const {
-  return absl::StrFormat("PBF_CLIENT[%p]: [%s] ", this, elem()->filter->name);
+  return absl::StrFormat("PBF_CLIENT[%p]: [%v] ", this, elem()->filter->name);
 }
 
 // Activity implementation.
@@ -2012,7 +2012,7 @@ ServerCallData::~ServerCallData() {
 }
 
 std::string ServerCallData::DebugTag() const {
-  return absl::StrFormat("PBF_SERVER[%p]: [%s] ", this, elem()->filter->name);
+  return absl::StrFormat("PBF_SERVER[%p]: [%v] ", this, elem()->filter->name);
 }
 
 // Activity implementation.
diff --git a/src/core/lib/channel/promise_based_filter.h b/src/core/lib/channel/promise_based_filter.h
index c40b1fb0964..046b6976448 100644
--- a/src/core/lib/channel/promise_based_filter.h
+++ b/src/core/lib/channel/promise_based_filter.h
@@ -1659,7 +1659,7 @@ template <typename F, FilterEndpoint kEndpoint, uint8_t kFlags = 0>
 absl::enable_if_t<std::is_base_of<ChannelFilter, F>::value &&
                       !std::is_base_of<ImplementChannelFilterTag, F>::value,
                   grpc_channel_filter>
-MakePromiseBasedFilter(const char* name) {
+MakePromiseBasedFilter() {
   using CallData = promise_filter_detail::CallData<kEndpoint>;
 
   return grpc_channel_filter{
@@ -1690,14 +1690,14 @@ MakePromiseBasedFilter(const char* name) {
       // get_channel_info
       promise_filter_detail::ChannelFilterMethods::GetChannelInfo,
       // name
-      name,
+      UniqueTypeNameFor<F>(),
   };
 }
 
 template <typename F, FilterEndpoint kEndpoint, uint8_t kFlags = 0>
 absl::enable_if_t<std::is_base_of<ImplementChannelFilterTag, F>::value,
                   grpc_channel_filter>
-MakePromiseBasedFilter(const char* name) {
+MakePromiseBasedFilter() {
   using CallData = promise_filter_detail::CallData<kEndpoint>;
 
   return grpc_channel_filter{
@@ -1728,7 +1728,7 @@ MakePromiseBasedFilter(const char* name) {
       // get_channel_info
       promise_filter_detail::ChannelFilterMethods::GetChannelInfo,
       // name
-      name,
+      UniqueTypeNameFor<F>(),
   };
 }
 
diff --git a/src/core/lib/gprpp/unique_type_name.h b/src/core/lib/gprpp/unique_type_name.h
index 2e71ab73f07..c60d8ea26fa 100644
--- a/src/core/lib/gprpp/unique_type_name.h
+++ b/src/core/lib/gprpp/unique_type_name.h
@@ -64,7 +64,7 @@ class UniqueTypeName {
     Factory(const Factory&) = delete;
     Factory& operator=(const Factory&) = delete;
 
-    UniqueTypeName Create() { return UniqueTypeName(*name_); }
+    UniqueTypeName Create() const { return UniqueTypeName(*name_); }
 
    private:
     std::string* name_;
@@ -93,12 +93,33 @@ class UniqueTypeName {
 
   absl::string_view name() const { return name_; }
 
+  template <typename Sink>
+  friend void AbslStringify(Sink& sink, const UniqueTypeName& name) {
+    sink.Append(name.name_);
+  }
+
  private:
   explicit UniqueTypeName(absl::string_view name) : name_(name) {}
 
   absl::string_view name_;
 };
 
+// Given a type with a member `static absl::string_view TypeName()`, returns a
+// UniqueTypeName instance who's string value is the value of TypeName.
+template <typename T>
+UniqueTypeName UniqueTypeNameFor() {
+  static UniqueTypeName::Factory factory(T::TypeName());
+  return factory.Create();
+}
+
 }  // namespace grpc_core
 
+// Creates a one-off UniqueTypeName in-place.
+// Duplicate calls yield different UniqueTypeName instances.
+#define GRPC_UNIQUE_TYPE_NAME_HERE(name)                               \
+  ([] {                                                                \
+    static const ::grpc_core::UniqueTypeName::Factory factory((name)); \
+    return factory.Create();                                           \
+  }())
+
 #endif  // GRPC_SRC_CORE_LIB_GPRPP_UNIQUE_TYPE_NAME_H
diff --git a/src/core/lib/security/authorization/grpc_server_authz_filter.cc b/src/core/lib/security/authorization/grpc_server_authz_filter.cc
index 176f49fdb78..04733c341a2 100644
--- a/src/core/lib/security/authorization/grpc_server_authz_filter.cc
+++ b/src/core/lib/security/authorization/grpc_server_authz_filter.cc
@@ -114,7 +114,6 @@ absl::Status GrpcServerAuthzFilter::Call::OnClientInitialMetadata(
 }
 
 const grpc_channel_filter GrpcServerAuthzFilter::kFilter =
-    MakePromiseBasedFilter<GrpcServerAuthzFilter, FilterEndpoint::kServer>(
-        "grpc-server-authz");
+    MakePromiseBasedFilter<GrpcServerAuthzFilter, FilterEndpoint::kServer>();
 
 }  // namespace grpc_core
diff --git a/src/core/lib/security/authorization/grpc_server_authz_filter.h b/src/core/lib/security/authorization/grpc_server_authz_filter.h
index 742b3979d88..cfd9c3bbd26 100644
--- a/src/core/lib/security/authorization/grpc_server_authz_filter.h
+++ b/src/core/lib/security/authorization/grpc_server_authz_filter.h
@@ -37,6 +37,8 @@ class GrpcServerAuthzFilter final
  public:
   static const grpc_channel_filter kFilter;
 
+  static absl::string_view TypeName() { return "grpc-server-authz"; }
+
   static absl::StatusOr<std::unique_ptr<GrpcServerAuthzFilter>> Create(
       const ChannelArgs& args, ChannelFilter::Args);
 
diff --git a/src/core/lib/security/transport/auth_filters.h b/src/core/lib/security/transport/auth_filters.h
index 3970ae1e4f3..c3421f98876 100644
--- a/src/core/lib/security/transport/auth_filters.h
+++ b/src/core/lib/security/transport/auth_filters.h
@@ -43,6 +43,8 @@ class ClientAuthFilter final : public ChannelFilter {
  public:
   static const grpc_channel_filter kFilter;
 
+  static absl::string_view TypeName() { return "client-auth-filter"; }
+
   ClientAuthFilter(
       RefCountedPtr<grpc_channel_security_connector> security_connector,
       RefCountedPtr<grpc_auth_context> auth_context);
@@ -96,6 +98,8 @@ class ServerAuthFilter final : public ImplementChannelFilter<ServerAuthFilter> {
  public:
   static const grpc_channel_filter kFilter;
 
+  static absl::string_view TypeName() { return "server-auth"; }
+
   ServerAuthFilter(RefCountedPtr<grpc_server_credentials> server_credentials,
                    RefCountedPtr<grpc_auth_context> auth_context);
 
diff --git a/src/core/lib/security/transport/client_auth_filter.cc b/src/core/lib/security/transport/client_auth_filter.cc
index a3d25294e96..dcbeeccf149 100644
--- a/src/core/lib/security/transport/client_auth_filter.cc
+++ b/src/core/lib/security/transport/client_auth_filter.cc
@@ -216,7 +216,6 @@ absl::StatusOr<std::unique_ptr<ClientAuthFilter>> ClientAuthFilter::Create(
 }
 
 const grpc_channel_filter ClientAuthFilter::kFilter =
-    MakePromiseBasedFilter<ClientAuthFilter, FilterEndpoint::kClient>(
-        "client-auth-filter");
+    MakePromiseBasedFilter<ClientAuthFilter, FilterEndpoint::kClient>();
 
 }  // namespace grpc_core
diff --git a/src/core/lib/security/transport/server_auth_filter.cc b/src/core/lib/security/transport/server_auth_filter.cc
index 15a5e0d15fe..3b44a84edc2 100644
--- a/src/core/lib/security/transport/server_auth_filter.cc
+++ b/src/core/lib/security/transport/server_auth_filter.cc
@@ -62,8 +62,7 @@
 namespace grpc_core {
 
 const grpc_channel_filter ServerAuthFilter::kFilter =
-    MakePromiseBasedFilter<ServerAuthFilter, FilterEndpoint::kServer>(
-        "server-auth");
+    MakePromiseBasedFilter<ServerAuthFilter, FilterEndpoint::kServer>();
 
 const NoInterceptor ServerAuthFilter::Call::OnClientToServerMessage;
 const NoInterceptor ServerAuthFilter::Call::OnClientToServerHalfClose;
diff --git a/src/core/lib/surface/channel_init.cc b/src/core/lib/surface/channel_init.cc
index 4adb4241402..24cebf260e5 100644
--- a/src/core/lib/surface/channel_init.cc
+++ b/src/core/lib/surface/channel_init.cc
@@ -43,13 +43,15 @@
 
 namespace grpc_core {
 
-const char* (*NameFromChannelFilter)(const grpc_channel_filter*);
+UniqueTypeName (*NameFromChannelFilter)(const grpc_channel_filter*);
 
 namespace {
 struct CompareChannelFiltersByName {
   bool operator()(const grpc_channel_filter* a,
                   const grpc_channel_filter* b) const {
-    return strcmp(NameFromChannelFilter(a), NameFromChannelFilter(b)) < 0;
+    // Compare lexicographically instead of by pointer value so that different
+    // builds make the same choices.
+    return NameFromChannelFilter(a).name() < NameFromChannelFilter(b).name();
   }
 };
 }  // namespace
@@ -260,8 +262,8 @@ ChannelInit::StackConfig ChannelInit::BuildStackConfig(
     auto add_loc_str = [&max_loc_str_len, &loc_strs, &filter_to_registration,
                         &max_filter_name_len](
                            const grpc_channel_filter* filter) {
-      max_filter_name_len =
-          std::max(strlen(NameFromChannelFilter(filter)), max_filter_name_len);
+      max_filter_name_len = std::max(
+          NameFromChannelFilter(filter).name().length(), max_filter_name_len);
       const auto registration =
           filter_to_registration[filter]->registration_source_;
       absl::string_view file = registration.file();
@@ -300,14 +302,16 @@ ChannelInit::StackConfig ChannelInit::BuildStackConfig(
       std::string after_str;
       if (dep_it != original.end() && !dep_it->second.empty()) {
         after_str = absl::StrCat(
-            std::string(max_filter_name_len + 1 -
-                            strlen(NameFromChannelFilter(filter.filter)),
-                        ' '),
+            std::string(
+                max_filter_name_len + 1 -
+                    NameFromChannelFilter(filter.filter).name().length(),
+                ' '),
             "after ",
             absl::StrJoin(
                 dep_it->second, ", ",
                 [](std::string* out, const grpc_channel_filter* filter) {
-                  out->append(NameFromChannelFilter(filter));
+                  out->append(
+                      std::string(NameFromChannelFilter(filter).name()));
                 }));
       }
       const auto filter_str =
@@ -321,9 +325,10 @@ ChannelInit::StackConfig ChannelInit::BuildStackConfig(
       const auto filter_str = absl::StrCat(
           "  ", loc_strs[terminal.filter],
           NameFromChannelFilter(terminal.filter),
-          std::string(max_filter_name_len + 1 -
-                          strlen(NameFromChannelFilter(terminal.filter)),
-                      ' '),
+          std::string(
+              max_filter_name_len + 1 -
+                  NameFromChannelFilter(terminal.filter).name().length(),
+              ' '),
           "[terminal]");
       LOG(INFO) << filter_str;
     }
diff --git a/src/core/lib/surface/channel_init.h b/src/core/lib/surface/channel_init.h
index c5067394014..e756160108a 100644
--- a/src/core/lib/surface/channel_init.h
+++ b/src/core/lib/surface/channel_init.h
@@ -36,6 +36,7 @@
 #include "src/core/lib/channel/channel_fwd.h"
 #include "src/core/lib/channel/channel_stack_builder.h"
 #include "src/core/lib/gprpp/debug_location.h"
+#include "src/core/lib/gprpp/unique_type_name.h"
 #include "src/core/lib/surface/channel_stack_type.h"
 #include "src/core/lib/transport/call_filters.h"
 #include "src/core/lib/transport/interception_chain.h"
@@ -61,7 +62,7 @@ namespace grpc_core {
 // TODO(ctiller): remove this. When we define a FilterFactory type, that type
 // can be specified with the right constraints to be depended upon by this code,
 // and that type can export a `string_view Name()` method.
-extern const char* (*NameFromChannelFilter)(const grpc_channel_filter*);
+extern UniqueTypeName (*NameFromChannelFilter)(const grpc_channel_filter*);
 
 class ChannelInit {
  public:
diff --git a/src/core/lib/surface/filter_stack_call.cc b/src/core/lib/surface/filter_stack_call.cc
index 40bc6ef3e9d..e8aa3562650 100644
--- a/src/core/lib/surface/filter_stack_call.cc
+++ b/src/core/lib/surface/filter_stack_call.cc
@@ -298,7 +298,9 @@ void FilterStackCall::ExecuteBatch(grpc_transport_stream_op_batch* batch,
     auto* call =
         static_cast<FilterStackCall*>(batch->handler_private.extra_arg);
     grpc_call_element* elem = call->call_elem(0);
-    GRPC_CALL_LOG_OP(GPR_INFO, elem, batch);
+    GRPC_TRACE_LOG(channel, INFO)
+        << "OP[" << elem->filter->name << ":" << elem
+        << "]: " << grpc_transport_stream_op_batch_string(batch, false);
     elem->filter->start_transport_stream_op_batch(elem, batch);
   };
   batch->handler_private.extra_arg = this;
diff --git a/src/core/lib/surface/lame_client.cc b/src/core/lib/surface/lame_client.cc
index f573194a42e..5eaa6dc7547 100644
--- a/src/core/lib/surface/lame_client.cc
+++ b/src/core/lib/surface/lame_client.cc
@@ -57,7 +57,7 @@ namespace grpc_core {
 
 const grpc_channel_filter LameClientFilter::kFilter =
     MakePromiseBasedFilter<LameClientFilter, FilterEndpoint::kClient,
-                           kFilterIsLast>("lame-client");
+                           kFilterIsLast>();
 
 absl::StatusOr<std::unique_ptr<LameClientFilter>> LameClientFilter::Create(
     const ChannelArgs& args, ChannelFilter::Args) {
diff --git a/src/core/lib/surface/lame_client.h b/src/core/lib/surface/lame_client.h
index 1f8d323d352..c5ff64d2a4d 100644
--- a/src/core/lib/surface/lame_client.h
+++ b/src/core/lib/surface/lame_client.h
@@ -47,6 +47,8 @@ class LameClientFilter : public ChannelFilter {
  public:
   static const grpc_channel_filter kFilter;
 
+  static absl::string_view TypeName() { return "lame-client"; }
+
   explicit LameClientFilter(absl::Status error);
 
   static absl::StatusOr<std::unique_ptr<LameClientFilter>> Create(
diff --git a/src/core/load_balancing/grpclb/client_load_reporting_filter.cc b/src/core/load_balancing/grpclb/client_load_reporting_filter.cc
index e03fe8d70ce..bb86bdc1048 100644
--- a/src/core/load_balancing/grpclb/client_load_reporting_filter.cc
+++ b/src/core/load_balancing/grpclb/client_load_reporting_filter.cc
@@ -46,8 +46,7 @@ const NoInterceptor ClientLoadReportingFilter::Call::OnFinalize;
 
 const grpc_channel_filter ClientLoadReportingFilter::kFilter =
     MakePromiseBasedFilter<ClientLoadReportingFilter, FilterEndpoint::kClient,
-                           kFilterExaminesServerInitialMetadata>(
-        "client_load_reporting");
+                           kFilterExaminesServerInitialMetadata>();
 
 absl::StatusOr<std::unique_ptr<ClientLoadReportingFilter>>
 ClientLoadReportingFilter::Create(const ChannelArgs&, ChannelFilter::Args) {
diff --git a/src/core/load_balancing/grpclb/client_load_reporting_filter.h b/src/core/load_balancing/grpclb/client_load_reporting_filter.h
index f8c5b7fbcc4..a9d979634ff 100644
--- a/src/core/load_balancing/grpclb/client_load_reporting_filter.h
+++ b/src/core/load_balancing/grpclb/client_load_reporting_filter.h
@@ -36,6 +36,8 @@ class ClientLoadReportingFilter final
  public:
   static const grpc_channel_filter kFilter;
 
+  static absl::string_view TypeName() { return "client_load_reporting"; }
+
   class Call {
    public:
     void OnClientInitialMetadata(ClientMetadata& client_initial_metadata);
diff --git a/src/core/resolver/xds/xds_resolver.cc b/src/core/resolver/xds/xds_resolver.cc
index 286f4e0dedd..a91708c67f4 100644
--- a/src/core/resolver/xds/xds_resolver.cc
+++ b/src/core/resolver/xds/xds_resolver.cc
@@ -318,6 +318,8 @@ class XdsResolver final : public Resolver {
    public:
     const static grpc_channel_filter kFilter;
 
+    static absl::string_view TypeName() { return "cluster_selection_filter"; }
+
     static absl::StatusOr<std::unique_ptr<ClusterSelectionFilter>> Create(
         const ChannelArgs& /* unused */,
         ChannelFilter::Args /* filter_args */) {
@@ -866,8 +868,7 @@ XdsResolver::XdsRouteStateAttributeImpl::LockAndGetCluster(
 
 const grpc_channel_filter XdsResolver::ClusterSelectionFilter::kFilter =
     MakePromiseBasedFilter<ClusterSelectionFilter, FilterEndpoint::kClient,
-                           kFilterExaminesServerInitialMetadata>(
-        "cluster_selection_filter");
+                           kFilterExaminesServerInitialMetadata>();
 
 void XdsResolver::ClusterSelectionFilter::Call::OnClientInitialMetadata(
     ClientMetadata&) {
diff --git a/src/core/server/server.cc b/src/core/server/server.cc
index c4796d6ae9b..6b1ead984db 100644
--- a/src/core/server/server.cc
+++ b/src/core/server/server.cc
@@ -779,7 +779,7 @@ const grpc_channel_filter Server::kServerTopFilter = {
     grpc_channel_stack_no_post_init,
     Server::ChannelData::DestroyChannelElement,
     grpc_channel_next_get_info,
-    "server",
+    GRPC_UNIQUE_TYPE_NAME_HERE("server"),
 };
 
 namespace {
diff --git a/src/core/server/server_call_tracer_filter.cc b/src/core/server/server_call_tracer_filter.cc
index 1454a4f5e92..78f8589cea0 100644
--- a/src/core/server/server_call_tracer_filter.cc
+++ b/src/core/server/server_call_tracer_filter.cc
@@ -49,6 +49,8 @@ class ServerCallTracerFilter
  public:
   static const grpc_channel_filter kFilter;
 
+  static absl::string_view TypeName() { return "server_call_tracer"; }
+
   static absl::StatusOr<std::unique_ptr<ServerCallTracerFilter>> Create(
       const ChannelArgs& /*args*/, ChannelFilter::Args /*filter_args*/);
 
@@ -90,8 +92,7 @@ const NoInterceptor ServerCallTracerFilter::Call::OnServerToClientMessage;
 
 const grpc_channel_filter ServerCallTracerFilter::kFilter =
     MakePromiseBasedFilter<ServerCallTracerFilter, FilterEndpoint::kServer,
-                           kFilterExaminesServerInitialMetadata>(
-        "server_call_tracer");
+                           kFilterExaminesServerInitialMetadata>();
 
 absl::StatusOr<std::unique_ptr<ServerCallTracerFilter>>
 ServerCallTracerFilter::Create(const ChannelArgs& /*args*/,
diff --git a/src/core/server/server_config_selector_filter.cc b/src/core/server/server_config_selector_filter.cc
index d04b10a0d86..4dfe26fb5c5 100644
--- a/src/core/server/server_config_selector_filter.cc
+++ b/src/core/server/server_config_selector_filter.cc
@@ -55,6 +55,10 @@ class ServerConfigSelectorFilter final
       RefCountedPtr<ServerConfigSelectorProvider>
           server_config_selector_provider);
 
+  static absl::string_view TypeName() {
+    return "server_config_selector_filter";
+  }
+
   ServerConfigSelectorFilter(const ServerConfigSelectorFilter&) = delete;
   ServerConfigSelectorFilter& operator=(const ServerConfigSelectorFilter&) =
       delete;
@@ -164,7 +168,7 @@ const NoInterceptor ServerConfigSelectorFilter::Call::OnFinalize;
 }  // namespace
 
 const grpc_channel_filter kServerConfigSelectorFilter =
-    MakePromiseBasedFilter<ServerConfigSelectorFilter, FilterEndpoint::kServer>(
-        "server_config_selector_filter");
+    MakePromiseBasedFilter<ServerConfigSelectorFilter,
+                           FilterEndpoint::kServer>();
 
 }  // namespace grpc_core
diff --git a/src/core/server/xds_channel_stack_modifier.cc b/src/core/server/xds_channel_stack_modifier.cc
index f9e280ea28a..15d2d3378f3 100644
--- a/src/core/server/xds_channel_stack_modifier.cc
+++ b/src/core/server/xds_channel_stack_modifier.cc
@@ -63,7 +63,7 @@ void XdsChannelStackModifier::ModifyChannelStack(ChannelStackBuilder& builder) {
   for (auto it = builder.mutable_stack()->begin();
        it != builder.mutable_stack()->end(); ++it) {
     for (absl::string_view predicate_name : {"server", "census_server"}) {
-      if (predicate_name == (*it)->name) insert_before = it + 1;
+      if (predicate_name == (*it)->name.name()) insert_before = it + 1;
     }
   }
   for (const grpc_channel_filter* filter : filters_) {
diff --git a/src/core/service_config/service_config_channel_arg_filter.cc b/src/core/service_config/service_config_channel_arg_filter.cc
index 8b06f26ebcf..96a5b3f8b81 100644
--- a/src/core/service_config/service_config_channel_arg_filter.cc
+++ b/src/core/service_config/service_config_channel_arg_filter.cc
@@ -58,6 +58,8 @@ class ServiceConfigChannelArgFilter final
  public:
   static const grpc_channel_filter kFilter;
 
+  static absl::string_view TypeName() { return "service_config_channel_arg"; }
+
   static absl::StatusOr<std::unique_ptr<ServiceConfigChannelArgFilter>> Create(
       const ChannelArgs& args, ChannelFilter::Args) {
     return std::make_unique<ServiceConfigChannelArgFilter>(args);
@@ -119,8 +121,7 @@ void ServiceConfigChannelArgFilter::Call::OnClientInitialMetadata(
 
 const grpc_channel_filter ServiceConfigChannelArgFilter::kFilter =
     MakePromiseBasedFilter<ServiceConfigChannelArgFilter,
-                           FilterEndpoint::kClient>(
-        "service_config_channel_arg");
+                           FilterEndpoint::kClient>();
 
 }  // namespace
 
diff --git a/src/cpp/ext/filters/census/client_filter.cc b/src/cpp/ext/filters/census/client_filter.cc
index 9ef8bf5a557..1f15fd4d70f 100644
--- a/src/cpp/ext/filters/census/client_filter.cc
+++ b/src/cpp/ext/filters/census/client_filter.cc
@@ -81,8 +81,7 @@ constexpr uint32_t
 
 const grpc_channel_filter OpenCensusClientFilter::kFilter =
     grpc_core::MakePromiseBasedFilter<OpenCensusClientFilter,
-                                      grpc_core::FilterEndpoint::kClient, 0>(
-        "opencensus_client");
+                                      grpc_core::FilterEndpoint::kClient, 0>();
 
 absl::StatusOr<std::unique_ptr<OpenCensusClientFilter>>
 OpenCensusClientFilter::Create(const grpc_core::ChannelArgs& args,
diff --git a/src/cpp/ext/filters/census/client_filter.h b/src/cpp/ext/filters/census/client_filter.h
index a549510bbe2..8e2f4057c3b 100644
--- a/src/cpp/ext/filters/census/client_filter.h
+++ b/src/cpp/ext/filters/census/client_filter.h
@@ -38,6 +38,8 @@ class OpenCensusClientFilter : public grpc_core::ChannelFilter {
  public:
   static const grpc_channel_filter kFilter;
 
+  static absl::string_view TypeName() { return "opencensus_client"; }
+
   static absl::StatusOr<std::unique_ptr<OpenCensusClientFilter>> Create(
       const grpc_core::ChannelArgs& args, ChannelFilter::Args /*filter_args*/);
 
diff --git a/test/core/channel/channel_stack_builder_test.cc b/test/core/channel/channel_stack_builder_test.cc
index 2c7dff9526e..82bda202df4 100644
--- a/test/core/channel/channel_stack_builder_test.cc
+++ b/test/core/channel/channel_stack_builder_test.cc
@@ -19,6 +19,7 @@
 #include "src/core/lib/channel/channel_stack_builder.h"
 
 #include <map>
+#include <memory>
 #include <utility>
 
 #include "absl/status/status.h"
@@ -53,19 +54,24 @@ void CallDestroyFunc(grpc_call_element* /*elem*/,
                      const grpc_call_final_info* /*final_info*/,
                      grpc_closure* /*ignored*/) {}
 
-const grpc_channel_filter* FilterNamed(const char* name) {
+const grpc_channel_filter* FilterNamed(absl::string_view name) {
   static auto* filters =
       new std::map<absl::string_view, const grpc_channel_filter*>;
   auto it = filters->find(name);
   if (it != filters->end()) return it->second;
+  static auto* name_factories =
+      new std::vector<std::unique_ptr<UniqueTypeName::Factory>>();
+  name_factories->emplace_back(std::make_unique<UniqueTypeName::Factory>(name));
+  auto unique_type_name = name_factories->back()->Create();
   return filters
-      ->emplace(name,
-                new grpc_channel_filter{
-                    grpc_call_next_op, grpc_channel_next_op, 0, CallInitFunc,
-                    grpc_call_stack_ignore_set_pollset_or_pollset_set,
-                    CallDestroyFunc, 0, ChannelInitFunc,
-                    [](grpc_channel_stack*, grpc_channel_element*) {},
-                    ChannelDestroyFunc, grpc_channel_next_get_info, name})
+      ->emplace(
+          name,
+          new grpc_channel_filter{
+              grpc_call_next_op, grpc_channel_next_op, 0, CallInitFunc,
+              grpc_call_stack_ignore_set_pollset_or_pollset_set,
+              CallDestroyFunc, 0, ChannelInitFunc,
+              [](grpc_channel_stack*, grpc_channel_element*) {},
+              ChannelDestroyFunc, grpc_channel_next_get_info, unique_type_name})
       .first->second;
 }
 
diff --git a/test/core/channel/channel_stack_test.cc b/test/core/channel/channel_stack_test.cc
index bc94f262aaf..10d4ee8e5fb 100644
--- a/test/core/channel/channel_stack_test.cc
+++ b/test/core/channel/channel_stack_test.cc
@@ -92,7 +92,7 @@ TEST(ChannelStackTest, CreateChannelStack) {
       grpc_channel_stack_no_post_init,
       channel_destroy_func,
       grpc_channel_next_get_info,
-      "some_test_filter"};
+      GRPC_UNIQUE_TYPE_NAME_HERE("some_test_filter")};
   const grpc_channel_filter* filters = &filter;
   grpc_channel_stack* channel_stack;
   grpc_call_stack* call_stack;
diff --git a/test/core/channel/minimal_stack_is_minimal_test.cc b/test/core/channel/minimal_stack_is_minimal_test.cc
index ebf0f66c82c..cf1a7b08339 100644
--- a/test/core/channel/minimal_stack_is_minimal_test.cc
+++ b/test/core/channel/minimal_stack_is_minimal_test.cc
@@ -101,9 +101,7 @@ std::vector<std::string> MakeStack(const char* transport_name,
 
   std::vector<std::string> parts;
   for (const auto& entry : *builder.mutable_stack()) {
-    const char* name = entry->name;
-    if (name == nullptr) continue;
-    parts.push_back(name);
+    parts.push_back(std::string(entry->name.name()));
   }
 
   return parts;
diff --git a/test/core/end2end/tests/filter_causes_close.cc b/test/core/end2end/tests/filter_causes_close.cc
index 0e96e1213d7..8a77719e401 100644
--- a/test/core/end2end/tests/filter_causes_close.cc
+++ b/test/core/end2end/tests/filter_causes_close.cc
@@ -52,6 +52,7 @@ namespace {
 class TestFilter : public ImplementChannelFilter<TestFilter> {
  public:
   static const grpc_channel_filter kFilter;
+  static absl::string_view TypeName() { return "filter_causes_close"; }
   static absl::StatusOr<std::unique_ptr<TestFilter>> Create(
       const ChannelArgs&, ChannelFilter::Args) {
     return std::make_unique<TestFilter>();
@@ -81,8 +82,7 @@ const NoInterceptor TestFilter::Call::OnServerToClientMessage;
 const NoInterceptor TestFilter::Call::OnFinalize;
 
 const grpc_channel_filter TestFilter::kFilter =
-    MakePromiseBasedFilter<TestFilter, FilterEndpoint::kServer>(
-        "filter_causes_close");
+    MakePromiseBasedFilter<TestFilter, FilterEndpoint::kServer>();
 
 CORE_END2END_TEST(CoreEnd2endTest, FilterCausesClose) {
   CoreConfiguration::RegisterBuilder([](CoreConfiguration::Builder* builder) {
diff --git a/test/core/end2end/tests/filter_init_fails.cc b/test/core/end2end/tests/filter_init_fails.cc
index 9d2b272a236..c2b08486fee 100644
--- a/test/core/end2end/tests/filter_init_fails.cc
+++ b/test/core/end2end/tests/filter_init_fails.cc
@@ -85,7 +85,7 @@ const grpc_channel_filter test_filter = {
     // last one.
     // Filter ordering code falls back to lexical ordering in the absense of
     // other dependencies, so name this appropriately.
-    "zzzzzz_filter_init_fails"};
+    GRPC_UNIQUE_TYPE_NAME_HERE("zzzzzz_filter_init_fails")};
 
 void RegisterFilter(grpc_channel_stack_type type) {
   CoreConfiguration::RegisterBuilder(
diff --git a/test/core/end2end/tests/retry_cancel_with_multiple_send_batches.cc b/test/core/end2end/tests/retry_cancel_with_multiple_send_batches.cc
index 1ee77a489fc..a5b932a7ea0 100644
--- a/test/core/end2end/tests/retry_cancel_with_multiple_send_batches.cc
+++ b/test/core/end2end/tests/retry_cancel_with_multiple_send_batches.cc
@@ -172,7 +172,7 @@ grpc_channel_filter FailSendOpsFilter::kFilterVtable = {
     grpc_channel_stack_no_post_init,
     Destroy,
     grpc_channel_next_get_info,
-    "FailSendOpsFilter",
+    GRPC_UNIQUE_TYPE_NAME_HERE("FailSendOpsFilter"),
 };
 
 void RegisterFilter() {
diff --git a/test/core/end2end/tests/retry_recv_message_replay.cc b/test/core/end2end/tests/retry_recv_message_replay.cc
index 902b52800dd..c3057f88161 100644
--- a/test/core/end2end/tests/retry_recv_message_replay.cc
+++ b/test/core/end2end/tests/retry_recv_message_replay.cc
@@ -32,6 +32,7 @@
 #include "src/core/lib/config/core_configuration.h"
 #include "src/core/lib/gprpp/status_helper.h"
 #include "src/core/lib/gprpp/time.h"
+#include "src/core/lib/gprpp/unique_type_name.h"
 #include "src/core/lib/iomgr/call_combiner.h"
 #include "src/core/lib/iomgr/closure.h"
 #include "src/core/lib/iomgr/error.h"
@@ -118,7 +119,7 @@ grpc_channel_filter FailFirstSendOpFilter::kFilterVtable = {
     grpc_channel_stack_no_post_init,
     Destroy,
     grpc_channel_next_get_info,
-    "FailFirstSendOpFilter",
+    GRPC_UNIQUE_TYPE_NAME_HERE("FailFirstSendOpFilter"),
 };
 
 // Tests the fix for a bug found in real-world code where recv_message
diff --git a/test/core/end2end/tests/retry_recv_trailing_metadata_error.cc b/test/core/end2end/tests/retry_recv_trailing_metadata_error.cc
index ec3f3b8ede7..cdbd9b75449 100644
--- a/test/core/end2end/tests/retry_recv_trailing_metadata_error.cc
+++ b/test/core/end2end/tests/retry_recv_trailing_metadata_error.cc
@@ -113,7 +113,7 @@ grpc_channel_filter InjectStatusFilter::kFilterVtable = {
     grpc_channel_stack_no_post_init,
     Destroy,
     grpc_channel_next_get_info,
-    "InjectStatusFilter",
+    GRPC_UNIQUE_TYPE_NAME_HERE("InjectStatusFilter"),
 };
 
 // Tests that we honor the error passed to recv_trailing_metadata_ready
diff --git a/test/core/end2end/tests/retry_send_op_fails.cc b/test/core/end2end/tests/retry_send_op_fails.cc
index 840525ef57f..825745ab96a 100644
--- a/test/core/end2end/tests/retry_send_op_fails.cc
+++ b/test/core/end2end/tests/retry_send_op_fails.cc
@@ -119,7 +119,7 @@ grpc_channel_filter FailFirstCallFilter::kFilterVtable = {
     grpc_channel_stack_no_post_init,
     Destroy,
     grpc_channel_next_get_info,
-    "FailFirstCallFilter",
+    GRPC_UNIQUE_TYPE_NAME_HERE("FailFirstCallFilter"),
 };
 
 // Tests failure on a send op batch:
diff --git a/test/core/end2end/tests/retry_transparent_goaway.cc b/test/core/end2end/tests/retry_transparent_goaway.cc
index ef3c9561c58..be68169cc26 100644
--- a/test/core/end2end/tests/retry_transparent_goaway.cc
+++ b/test/core/end2end/tests/retry_transparent_goaway.cc
@@ -29,6 +29,7 @@
 #include "src/core/lib/config/core_configuration.h"
 #include "src/core/lib/gprpp/status_helper.h"
 #include "src/core/lib/gprpp/time.h"
+#include "src/core/lib/gprpp/unique_type_name.h"
 #include "src/core/lib/iomgr/call_combiner.h"
 #include "src/core/lib/iomgr/closure.h"
 #include "src/core/lib/iomgr/error.h"
@@ -125,7 +126,7 @@ grpc_channel_filter FailFirstCallFilter::kFilterVtable = {
     grpc_channel_stack_no_post_init,
     Destroy,
     grpc_channel_next_get_info,
-    "FailFirstCallFilter",
+    GRPC_UNIQUE_TYPE_NAME_HERE("FailFirstCallFilter"),
 };
 
 // Tests transparent retries when the call was never sent out on the wire.
diff --git a/test/core/end2end/tests/retry_transparent_not_sent_on_wire.cc b/test/core/end2end/tests/retry_transparent_not_sent_on_wire.cc
index 735be66f6e9..b55ee605c4c 100644
--- a/test/core/end2end/tests/retry_transparent_not_sent_on_wire.cc
+++ b/test/core/end2end/tests/retry_transparent_not_sent_on_wire.cc
@@ -31,6 +31,7 @@
 #include "src/core/lib/config/core_configuration.h"
 #include "src/core/lib/gprpp/status_helper.h"
 #include "src/core/lib/gprpp/time.h"
+#include "src/core/lib/gprpp/unique_type_name.h"
 #include "src/core/lib/iomgr/call_combiner.h"
 #include "src/core/lib/iomgr/closure.h"
 #include "src/core/lib/iomgr/error.h"
@@ -124,7 +125,7 @@ grpc_channel_filter FailFirstTenCallsFilter::kFilterVtable = {
     grpc_channel_stack_no_post_init,
     Destroy,
     grpc_channel_next_get_info,
-    "FailFirstTenCallsFilter",
+    GRPC_UNIQUE_TYPE_NAME_HERE("FailFirstTenCallsFilter"),
 };
 
 // Tests transparent retries when the call was never sent out on the wire.
diff --git a/test/core/gprpp/unique_type_name_test.cc b/test/core/gprpp/unique_type_name_test.cc
index bce147edd32..83737c8c6a2 100644
--- a/test/core/gprpp/unique_type_name_test.cc
+++ b/test/core/gprpp/unique_type_name_test.cc
@@ -93,6 +93,26 @@ TEST(UniqueTypeNameTest, CanUseAsMapKey) {
                                               ::testing::Pair(bar.type(), 2)));
 }
 
+struct Filter1 {
+  static absl::string_view TypeName() { return "Filter1"; }
+};
+
+struct Filter2 {
+  static absl::string_view TypeName() { return "Filter2"; }
+};
+
+TEST(UniqueTypeNameTest, UniqueTypeNameFor) {
+  EXPECT_EQ(UniqueTypeNameFor<Filter1>(), UniqueTypeNameFor<Filter1>());
+  EXPECT_NE(UniqueTypeNameFor<Filter1>(), UniqueTypeNameFor<Filter2>());
+}
+
+TEST(UniqueTypeNameTest, UniqueTypeNameHere) {
+  auto name1 = GRPC_UNIQUE_TYPE_NAME_HERE("name");
+  auto name2 = GRPC_UNIQUE_TYPE_NAME_HERE("name");
+  EXPECT_EQ(name1.name(), name2.name());
+  EXPECT_NE(name1, name2);
+}
+
 }  // namespace
 }  // namespace grpc_core
 
diff --git a/test/core/server/xds_channel_stack_modifier_test.cc b/test/core/server/xds_channel_stack_modifier_test.cc
index 4c1e9f0919d..16f0e6e4e81 100644
--- a/test/core/server/xds_channel_stack_modifier_test.cc
+++ b/test/core/server/xds_channel_stack_modifier_test.cc
@@ -70,8 +70,8 @@ TEST(XdsChannelStackModifierTest, ChannelArgsCompare) {
   grpc_shutdown();
 }
 
-constexpr char kTestFilter1[] = "test_filter_1";
-constexpr char kTestFilter2[] = "test_filter_2";
+const UniqueTypeName kTestFilter1 = GRPC_UNIQUE_TYPE_NAME_HERE("test_filter_1");
+const UniqueTypeName kTestFilter2 = GRPC_UNIQUE_TYPE_NAME_HERE("test_filter_2");
 
 namespace {
 class FakeTransport final : public Transport {
@@ -117,11 +117,12 @@ TEST(XdsChannelStackModifierTest, XdsHttpFiltersInsertion) {
   }
   std::vector<std::string> filters;
   for (const auto& entry : *builder.mutable_stack()) {
-    filters.push_back(entry->name);
+    filters.push_back(std::string(entry->name.name()));
   }
   filters.resize(3);
-  EXPECT_EQ(filters,
-            std::vector<std::string>({"server", kTestFilter1, kTestFilter2}));
+  EXPECT_EQ(filters, std::vector<std::string>(
+                         {"server", std::string(kTestFilter1.name()),
+                          std::string(kTestFilter2.name())}));
   grpc_shutdown();
 }
 
diff --git a/test/core/surface/channel_init_test.cc b/test/core/surface/channel_init_test.cc
index b0b84323d47..39a8781f00b 100644
--- a/test/core/surface/channel_init_test.cc
+++ b/test/core/surface/channel_init_test.cc
@@ -37,10 +37,15 @@ const grpc_channel_filter* FilterNamed(const char* name) {
       new std::map<absl::string_view, const grpc_channel_filter*>;
   auto it = filters->find(name);
   if (it != filters->end()) return it->second;
+  static auto* name_factories =
+      new std::vector<std::unique_ptr<UniqueTypeName::Factory>>();
+  name_factories->emplace_back(std::make_unique<UniqueTypeName::Factory>(name));
+  auto unique_type_name = name_factories->back()->Create();
   return filters
-      ->emplace(name, new grpc_channel_filter{nullptr, nullptr, 0, nullptr,
-                                              nullptr, nullptr, 0, nullptr,
-                                              nullptr, nullptr, nullptr, name})
+      ->emplace(name,
+                new grpc_channel_filter{nullptr, nullptr, 0, nullptr, nullptr,
+                                        nullptr, 0, nullptr, nullptr, nullptr,
+                                        nullptr, unique_type_name})
       .first->second;
 }
 
@@ -51,7 +56,7 @@ std::vector<std::string> GetFilterNames(const ChannelInit& init,
   if (!init.CreateStack(&b)) return {};
   std::vector<std::string> names;
   for (auto f : b.stack()) {
-    names.push_back(f->name);
+    names.push_back(std::string(f->name.name()));
   }
   EXPECT_NE(names, std::vector<std::string>());
   return names;
@@ -239,8 +244,9 @@ class TestFilter1 {
 };
 
 const grpc_channel_filter TestFilter1::kFilter = {
-    nullptr, nullptr, 0,       nullptr, nullptr, nullptr,
-    0,       nullptr, nullptr, nullptr, nullptr, "test_filter1"};
+    nullptr, nullptr, 0,       nullptr,
+    nullptr, nullptr, 0,       nullptr,
+    nullptr, nullptr, nullptr, GRPC_UNIQUE_TYPE_NAME_HERE("test_filter1")};
 const NoInterceptor TestFilter1::Call::OnClientInitialMetadata;
 const NoInterceptor TestFilter1::Call::OnServerInitialMetadata;
 const NoInterceptor TestFilter1::Call::OnServerTrailingMetadata;
diff --git a/test/core/surface/secure_channel_create_test.cc b/test/core/surface/secure_channel_create_test.cc
index 89f21615e98..baa1e8d05d1 100644
--- a/test/core/surface/secure_channel_create_test.cc
+++ b/test/core/surface/secure_channel_create_test.cc
@@ -37,7 +37,7 @@ void test_unknown_scheme_target(void) {
   grpc_channel* chan = grpc_channel_create("blah://blah", creds, nullptr);
   grpc_channel_element* elem = grpc_channel_stack_element(
       grpc_core::Channel::FromC(chan)->channel_stack(), 0);
-  ASSERT_STREQ(elem->filter->name, "lame-client");
+  ASSERT_EQ(elem->filter->name.name(), "lame-client");
   grpc_core::ExecCtx exec_ctx;
   grpc_core::Channel::FromC(chan)->Unref();
   creds->Unref();
@@ -51,7 +51,7 @@ void test_security_connector_already_in_arg(void) {
   grpc_channel* chan = grpc_channel_create(nullptr, nullptr, &args);
   grpc_channel_element* elem = grpc_channel_stack_element(
       grpc_core::Channel::FromC(chan)->channel_stack(), 0);
-  ASSERT_STREQ(elem->filter->name, "lame-client");
+  ASSERT_EQ(elem->filter->name.name(), "lame-client");
   grpc_core::ExecCtx exec_ctx;
   grpc_core::Channel::FromC(chan)->Unref();
 }
@@ -60,7 +60,7 @@ void test_null_creds(void) {
   grpc_channel* chan = grpc_channel_create(nullptr, nullptr, nullptr);
   grpc_channel_element* elem = grpc_channel_stack_element(
       grpc_core::Channel::FromC(chan)->channel_stack(), 0);
-  ASSERT_STREQ(elem->filter->name, "lame-client");
+  ASSERT_EQ(elem->filter->name.name(), "lame-client");
   grpc_core::ExecCtx exec_ctx;
   grpc_core::Channel::FromC(chan)->Unref();
 }
diff --git a/test/core/test_util/fake_stats_plugin.cc b/test/core/test_util/fake_stats_plugin.cc
index 59546f9ce45..3ce9431cd66 100644
--- a/test/core/test_util/fake_stats_plugin.cc
+++ b/test/core/test_util/fake_stats_plugin.cc
@@ -24,6 +24,8 @@ class FakeStatsClientFilter : public ChannelFilter {
  public:
   static const grpc_channel_filter kFilter;
 
+  static absl::string_view TypeName() { return "fake_stats_client"; }
+
   explicit FakeStatsClientFilter(
       FakeClientCallTracerFactory* fake_client_call_tracer_factory);
 
@@ -38,8 +40,7 @@ class FakeStatsClientFilter : public ChannelFilter {
 };
 
 const grpc_channel_filter FakeStatsClientFilter::kFilter =
-    MakePromiseBasedFilter<FakeStatsClientFilter, FilterEndpoint::kClient>(
-        "fake_stats_client");
+    MakePromiseBasedFilter<FakeStatsClientFilter, FilterEndpoint::kClient>();
 
 absl::StatusOr<std::unique_ptr<FakeStatsClientFilter>>
 FakeStatsClientFilter::Create(const ChannelArgs& args,
diff --git a/test/core/transport/chttp2/streams_not_seen_test.cc b/test/core/transport/chttp2/streams_not_seen_test.cc
index f00ca984e51..98b78b3d628 100644
--- a/test/core/transport/chttp2/streams_not_seen_test.cc
+++ b/test/core/transport/chttp2/streams_not_seen_test.cc
@@ -215,7 +215,7 @@ grpc_channel_filter TrailingMetadataRecordingFilter::kFilterVtable = {
     // connected channel filter must be the last one.
     // Channel init code falls back to lexical ordering of filters if there are
     // otherwise no dependencies, so we leverage that.
-    "zzzzzz_trailing-metadata-recording-filter",
+    GRPC_UNIQUE_TYPE_NAME_HERE("zzzzzz_trailing-metadata-recording-filter"),
 };
 bool TrailingMetadataRecordingFilter::trailing_metadata_available_;
 absl::optional<GrpcStreamNetworkState::ValueType>
diff --git a/test/cpp/ext/otel/otel_test_library.cc b/test/cpp/ext/otel/otel_test_library.cc
index 043d8c2dbc9..e16ff6b9980 100644
--- a/test/cpp/ext/otel/otel_test_library.cc
+++ b/test/cpp/ext/otel/otel_test_library.cc
@@ -50,6 +50,8 @@ class AddLabelsFilter : public grpc_core::ChannelFilter {
  public:
   static const grpc_channel_filter kFilter;
 
+  static absl::string_view TypeName() { return "add_service_labels_filter"; }
+
   explicit AddLabelsFilter(
       std::map<grpc_core::ClientCallTracer::CallAttemptTracer::OptionalLabelKey,
                grpc_core::RefCountedStringValue>
@@ -85,8 +87,7 @@ class AddLabelsFilter : public grpc_core::ChannelFilter {
 
 const grpc_channel_filter AddLabelsFilter::kFilter =
     grpc_core::MakePromiseBasedFilter<AddLabelsFilter,
-                                      grpc_core::FilterEndpoint::kClient>(
-        "add_service_labels_filter");
+                                      grpc_core::FilterEndpoint::kClient>();
 
 OpenTelemetryPluginEnd2EndTest::MetricsCollectorThread::MetricsCollectorThread(
     OpenTelemetryPluginEnd2EndTest* test, grpc_core::Duration interval,
diff --git a/tools/distrib/check_namespace_qualification.py b/tools/distrib/check_namespace_qualification.py
index 51ccb71aeb8..f08f73c66fc 100755
--- a/tools/distrib/check_namespace_qualification.py
+++ b/tools/distrib/check_namespace_qualification.py
@@ -77,6 +77,7 @@ IGNORED_FILES = [
     "src/core/lib/gprpp/global_config_env.h",
     "src/core/lib/profiling/timers.h",
     "src/core/lib/gprpp/crash.h",
+    "src/core/lib/gprpp/unique_type_name.h",
     # The grpc_core::Server redundant namespace qualification is required for
     # older gcc versions.
     "src/core/ext/transport/chttp2/server/chttp2_server.h",