diff --git a/envoy/config/rbac/v3/rbac.proto b/envoy/config/rbac/v3/rbac.proto
index 10520b1b..278e6857 100644
--- a/envoy/config/rbac/v3/rbac.proto
+++ b/envoy/config/rbac/v3/rbac.proto
@@ -24,8 +24,14 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE;
 // [#protodoc-title: Role Based Access Control (RBAC)]
 
 // Role Based Access Control (RBAC) provides service-level and method-level access control for a
-// service. RBAC policies are additive. The policies are examined in order. A request is allowed
-// once a matching policy is found (suppose the `action` is ALLOW).
+// service. RBAC policies are additive. The policies are examined in order. Requests are allowed
+// or denied based on the `action` and whether a matching policy is found. For instance, if the
+// action is ALLOW and a matching policy is found the request should be allowed.
+//
+// RBAC can also be used to make access logging decisions by communicating with access loggers
+// through dynamic metadata. When the action is LOG and at least one policy matches, the
+// `access_log_hint` value in the shared key namespace 'envoy.common' is set to `true` indicating
+// the request should be logged.
 //
 // Here is an example of RBAC configuration. It has two policies:
 //
@@ -68,39 +74,55 @@ message RBAC {
 
   // Should we do safe-list or block-list style access control?
   enum Action {
-    // The policies grant access to principals. The rest is denied. This is safe-list style
+    // The policies grant access to principals. The rest are denied. This is safe-list style
     // access control. This is the default type.
     ALLOW = 0;
 
-    // The policies deny access to principals. The rest is allowed. This is block-list style
+    // The policies deny access to principals. The rest are allowed. This is block-list style
     // access control.
     DENY = 1;
+
+    // The policies set the `access_log_hint` dynamic metadata key based on if requests match.
+    // All requests are allowed.
+    LOG = 2;
   }
 
-  // The action to take if a policy matches. The request is allowed if and only if:
+  // The action to take if a policy matches. Every action either allows or denies a request,
+  // and can also carry out action-specific operations.
+  //
+  // Actions:
+  //
+  //  * ALLOW: Allows the request if and only if there is a policy that matches
+  //    the request.
+  //  * DENY: Allows the request if and only if there are no policies that
+  //    match the request.
+  //  * LOG: Allows all requests. If at least one policy matches, the dynamic
+  //    metadata key `access_log_hint` is set to the value `true` under the shared
+  //    key namespace 'envoy.common'. If no policies match, it is set to `false`.
+  //    Other actions do not modify this key.
   //
-  //   * `action` is "ALLOWED" and at least one policy matches
-  //   * `action` is "DENY" and none of the policies match
   Action action = 1;
 
   // Maps from policy name to policy. A match occurs when at least one policy matches the request.
   map<string, Policy> policies = 2;
 }
 
-// Policy specifies a role and the principals that are assigned/denied the role. A policy matches if
-// and only if at least one of its permissions match the action taking place AND at least one of its
-// principals match the downstream AND the condition is true if specified.
+// Policy specifies a role and the principals that are assigned/denied the role.
+// A policy matches if and only if at least one of its permissions match the
+// action taking place AND at least one of its principals match the downstream
+// AND the condition is true if specified.
 message Policy {
   option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v2.Policy";
 
-  // Required. The set of permissions that define a role. Each permission is matched with OR
-  // semantics. To match all actions for this policy, a single Permission with the `any` field set
-  // to true should be used.
+  // Required. The set of permissions that define a role. Each permission is
+  // matched with OR semantics. To match all actions for this policy, a single
+  // Permission with the `any` field set to true should be used.
   repeated Permission permissions = 1 [(validate.rules).repeated = {min_items: 1}];
 
-  // Required. The set of principals that are assigned/denied the role based on “action”. Each
-  // principal is matched with OR semantics. To match all downstreams for this policy, a single
-  // Principal with the `any` field set to true should be used.
+  // Required. The set of principals that are assigned/denied the role based on
+  // “action”. Each principal is matched with OR semantics. To match all
+  // downstreams for this policy, a single Principal with the `any` field set to
+  // true should be used.
   repeated Principal principals = 2 [(validate.rules).repeated = {min_items: 1}];
 
   // An optional symbolic expression specifying an access control
@@ -161,9 +183,9 @@ message Permission {
     // Metadata that describes additional information about the action.
     type.matcher.v3.MetadataMatcher metadata = 7;
 
-    // Negates matching the provided permission. For instance, if the value of `not_rule` would
-    // match, this permission would not match. Conversely, if the value of `not_rule` would not
-    // match, this permission would match.
+    // Negates matching the provided permission. For instance, if the value of
+    // `not_rule` would match, this permission would not match. Conversely, if
+    // the value of `not_rule` would not match, this permission would match.
     Permission not_rule = 8;
 
     // The request server from the client's connection request. This is
@@ -176,7 +198,8 @@ message Permission {
     //
     //   * If the :ref:`TLS Inspector <config_listener_filters_tls_inspector>`
     //     filter is not added, and if a `FilterChainMatch` is not defined for
-    //     the :ref:`server name <envoy_api_field_config.listener.v3.FilterChainMatch.server_names>`,
+    //     the :ref:`server name
+    //     <envoy_api_field_config.listener.v3.FilterChainMatch.server_names>`,
     //     a TLS connection's requested SNI server name will be treated as if it
     //     wasn't present.
     //
@@ -189,13 +212,14 @@ message Permission {
   }
 }
 
-// Principal defines an identity or a group of identities for a downstream subject.
+// Principal defines an identity or a group of identities for a downstream
+// subject.
 // [#next-free-field: 12]
 message Principal {
   option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v2.Principal";
 
-  // Used in the `and_ids` and `or_ids` fields in the `identifier` oneof. Depending on the context,
-  // each are applied with the associated behavior.
+  // Used in the `and_ids` and `or_ids` fields in the `identifier` oneof.
+  // Depending on the context, each are applied with the associated behavior.
   message Set {
     option (udpa.annotations.versioning).previous_message_type =
         "envoy.config.rbac.v2.Principal.Set";
@@ -210,19 +234,21 @@ message Principal {
 
     reserved 1;
 
-    // The name of the principal. If set, The URI SAN or DNS SAN in that order is used from the
-    // certificate, otherwise the subject field is used. If unset, it applies to any user that is
-    // authenticated.
+    // The name of the principal. If set, The URI SAN or DNS SAN in that order
+    // is used from the certificate, otherwise the subject field is used. If
+    // unset, it applies to any user that is authenticated.
     type.matcher.v3.StringMatcher principal_name = 2;
   }
 
   oneof identifier {
     option (validate.required) = true;
 
-    // A set of identifiers that all must match in order to define the downstream.
+    // A set of identifiers that all must match in order to define the
+    // downstream.
     Set and_ids = 1;
 
-    // A set of identifiers at least one must match in order to define the downstream.
+    // A set of identifiers at least one must match in order to define the
+    // downstream.
     Set or_ids = 2;
 
     // When any is set, it matches any downstream.
@@ -237,21 +263,23 @@ message Principal {
 
     // A CIDR block that describes the downstream remote/origin address.
     // Note: This is always the physical peer even if the
-    // :ref:`remote_ip <envoy_api_field_config.rbac.v3.Principal.remote_ip>` is inferred
-    // from for example the x-forwarder-for header, proxy protocol, etc.
+    // :ref:`remote_ip <envoy_api_field_config.rbac.v3.Principal.remote_ip>` is
+    // inferred from for example the x-forwarder-for header, proxy protocol,
+    // etc.
     core.v3.CidrRange direct_remote_ip = 10;
 
     // A CIDR block that describes the downstream remote/origin address.
     // Note: This may not be the physical peer and could be different from the
-    // :ref:`direct_remote_ip <envoy_api_field_config.rbac.v3.Principal.direct_remote_ip>`.
-    // E.g, if the remote ip is inferred from for example the x-forwarder-for header,
-    // proxy protocol, etc.
+    // :ref:`direct_remote_ip
+    // <envoy_api_field_config.rbac.v3.Principal.direct_remote_ip>`. E.g, if the
+    // remote ip is inferred from for example the x-forwarder-for header, proxy
+    // protocol, etc.
     core.v3.CidrRange remote_ip = 11;
 
-    // A header (or pseudo-header such as :path or :method) on the incoming HTTP request. Only
-    // available for HTTP request.
-    // Note: the pseudo-header :path includes the query and fragment string. Use the `url_path`
-    // field if you want to match the URL path without the query and fragment string.
+    // A header (or pseudo-header such as :path or :method) on the incoming HTTP
+    // request. Only available for HTTP request. Note: the pseudo-header :path
+    // includes the query and fragment string. Use the `url_path` field if you
+    // want to match the URL path without the query and fragment string.
     route.v3.HeaderMatcher header = 6;
 
     // A URL path on the incoming HTTP request. Only available for HTTP.
@@ -260,9 +288,9 @@ message Principal {
     // Metadata that describes additional information about the principal.
     type.matcher.v3.MetadataMatcher metadata = 7;
 
-    // Negates matching the provided principal. For instance, if the value of `not_id` would match,
-    // this principal would not match. Conversely, if the value of `not_id` would not match, this
-    // principal would match.
+    // Negates matching the provided principal. For instance, if the value of
+    // `not_id` would match, this principal would not match. Conversely, if the
+    // value of `not_id` would not match, this principal would match.
     Principal not_id = 8;
   }
 }
diff --git a/envoy/config/rbac/v4alpha/rbac.proto b/envoy/config/rbac/v4alpha/rbac.proto
index 11b69b16..cc9d8933 100644
--- a/envoy/config/rbac/v4alpha/rbac.proto
+++ b/envoy/config/rbac/v4alpha/rbac.proto
@@ -23,8 +23,14 @@ option (udpa.annotations.file_status).package_version_status = NEXT_MAJOR_VERSIO
 // [#protodoc-title: Role Based Access Control (RBAC)]
 
 // Role Based Access Control (RBAC) provides service-level and method-level access control for a
-// service. RBAC policies are additive. The policies are examined in order. A request is allowed
-// once a matching policy is found (suppose the `action` is ALLOW).
+// service. RBAC policies are additive. The policies are examined in order. Requests are allowed
+// or denied based on the `action` and whether a matching policy is found. For instance, if the
+// action is ALLOW and a matching policy is found the request should be allowed.
+//
+// RBAC can also be used to make access logging decisions by communicating with access loggers
+// through dynamic metadata. When the action is LOG and at least one policy matches, the
+// `access_log_hint` value in the shared key namespace 'envoy.common' is set to `true` indicating
+// the request should be logged.
 //
 // Here is an example of RBAC configuration. It has two policies:
 //
@@ -67,39 +73,55 @@ message RBAC {
 
   // Should we do safe-list or block-list style access control?
   enum Action {
-    // The policies grant access to principals. The rest is denied. This is safe-list style
+    // The policies grant access to principals. The rest are denied. This is safe-list style
     // access control. This is the default type.
     ALLOW = 0;
 
-    // The policies deny access to principals. The rest is allowed. This is block-list style
+    // The policies deny access to principals. The rest are allowed. This is block-list style
     // access control.
     DENY = 1;
+
+    // The policies set the `access_log_hint` dynamic metadata key based on if requests match.
+    // All requests are allowed.
+    LOG = 2;
   }
 
-  // The action to take if a policy matches. The request is allowed if and only if:
+  // The action to take if a policy matches. Every action either allows or denies a request,
+  // and can also carry out action-specific operations.
+  //
+  // Actions:
+  //
+  //  * ALLOW: Allows the request if and only if there is a policy that matches
+  //    the request.
+  //  * DENY: Allows the request if and only if there are no policies that
+  //    match the request.
+  //  * LOG: Allows all requests. If at least one policy matches, the dynamic
+  //    metadata key `access_log_hint` is set to the value `true` under the shared
+  //    key namespace 'envoy.common'. If no policies match, it is set to `false`.
+  //    Other actions do not modify this key.
   //
-  //   * `action` is "ALLOWED" and at least one policy matches
-  //   * `action` is "DENY" and none of the policies match
   Action action = 1;
 
   // Maps from policy name to policy. A match occurs when at least one policy matches the request.
   map<string, Policy> policies = 2;
 }
 
-// Policy specifies a role and the principals that are assigned/denied the role. A policy matches if
-// and only if at least one of its permissions match the action taking place AND at least one of its
-// principals match the downstream AND the condition is true if specified.
+// Policy specifies a role and the principals that are assigned/denied the role.
+// A policy matches if and only if at least one of its permissions match the
+// action taking place AND at least one of its principals match the downstream
+// AND the condition is true if specified.
 message Policy {
   option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v3.Policy";
 
-  // Required. The set of permissions that define a role. Each permission is matched with OR
-  // semantics. To match all actions for this policy, a single Permission with the `any` field set
-  // to true should be used.
+  // Required. The set of permissions that define a role. Each permission is
+  // matched with OR semantics. To match all actions for this policy, a single
+  // Permission with the `any` field set to true should be used.
   repeated Permission permissions = 1 [(validate.rules).repeated = {min_items: 1}];
 
-  // Required. The set of principals that are assigned/denied the role based on “action”. Each
-  // principal is matched with OR semantics. To match all downstreams for this policy, a single
-  // Principal with the `any` field set to true should be used.
+  // Required. The set of principals that are assigned/denied the role based on
+  // “action”. Each principal is matched with OR semantics. To match all
+  // downstreams for this policy, a single Principal with the `any` field set to
+  // true should be used.
   repeated Principal principals = 2 [(validate.rules).repeated = {min_items: 1}];
 
   oneof expression_specifier {
@@ -160,9 +182,9 @@ message Permission {
     // Metadata that describes additional information about the action.
     type.matcher.v4alpha.MetadataMatcher metadata = 7;
 
-    // Negates matching the provided permission. For instance, if the value of `not_rule` would
-    // match, this permission would not match. Conversely, if the value of `not_rule` would not
-    // match, this permission would match.
+    // Negates matching the provided permission. For instance, if the value of
+    // `not_rule` would match, this permission would not match. Conversely, if
+    // the value of `not_rule` would not match, this permission would match.
     Permission not_rule = 8;
 
     // The request server from the client's connection request. This is
@@ -175,7 +197,8 @@ message Permission {
     //
     //   * If the :ref:`TLS Inspector <config_listener_filters_tls_inspector>`
     //     filter is not added, and if a `FilterChainMatch` is not defined for
-    //     the :ref:`server name <envoy_api_field_config.listener.v4alpha.FilterChainMatch.server_names>`,
+    //     the :ref:`server name
+    //     <envoy_api_field_config.listener.v4alpha.FilterChainMatch.server_names>`,
     //     a TLS connection's requested SNI server name will be treated as if it
     //     wasn't present.
     //
@@ -188,13 +211,14 @@ message Permission {
   }
 }
 
-// Principal defines an identity or a group of identities for a downstream subject.
+// Principal defines an identity or a group of identities for a downstream
+// subject.
 // [#next-free-field: 12]
 message Principal {
   option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v3.Principal";
 
-  // Used in the `and_ids` and `or_ids` fields in the `identifier` oneof. Depending on the context,
-  // each are applied with the associated behavior.
+  // Used in the `and_ids` and `or_ids` fields in the `identifier` oneof.
+  // Depending on the context, each are applied with the associated behavior.
   message Set {
     option (udpa.annotations.versioning).previous_message_type =
         "envoy.config.rbac.v3.Principal.Set";
@@ -209,9 +233,9 @@ message Principal {
 
     reserved 1;
 
-    // The name of the principal. If set, The URI SAN or DNS SAN in that order is used from the
-    // certificate, otherwise the subject field is used. If unset, it applies to any user that is
-    // authenticated.
+    // The name of the principal. If set, The URI SAN or DNS SAN in that order
+    // is used from the certificate, otherwise the subject field is used. If
+    // unset, it applies to any user that is authenticated.
     type.matcher.v4alpha.StringMatcher principal_name = 2;
   }
 
@@ -222,10 +246,12 @@ message Principal {
   oneof identifier {
     option (validate.required) = true;
 
-    // A set of identifiers that all must match in order to define the downstream.
+    // A set of identifiers that all must match in order to define the
+    // downstream.
     Set and_ids = 1;
 
-    // A set of identifiers at least one must match in order to define the downstream.
+    // A set of identifiers at least one must match in order to define the
+    // downstream.
     Set or_ids = 2;
 
     // When any is set, it matches any downstream.
@@ -236,21 +262,23 @@ message Principal {
 
     // A CIDR block that describes the downstream remote/origin address.
     // Note: This is always the physical peer even if the
-    // :ref:`remote_ip <envoy_api_field_config.rbac.v4alpha.Principal.remote_ip>` is inferred
-    // from for example the x-forwarder-for header, proxy protocol, etc.
+    // :ref:`remote_ip <envoy_api_field_config.rbac.v4alpha.Principal.remote_ip>` is
+    // inferred from for example the x-forwarder-for header, proxy protocol,
+    // etc.
     core.v4alpha.CidrRange direct_remote_ip = 10;
 
     // A CIDR block that describes the downstream remote/origin address.
     // Note: This may not be the physical peer and could be different from the
-    // :ref:`direct_remote_ip <envoy_api_field_config.rbac.v4alpha.Principal.direct_remote_ip>`.
-    // E.g, if the remote ip is inferred from for example the x-forwarder-for header,
-    // proxy protocol, etc.
+    // :ref:`direct_remote_ip
+    // <envoy_api_field_config.rbac.v4alpha.Principal.direct_remote_ip>`. E.g, if the
+    // remote ip is inferred from for example the x-forwarder-for header, proxy
+    // protocol, etc.
     core.v4alpha.CidrRange remote_ip = 11;
 
-    // A header (or pseudo-header such as :path or :method) on the incoming HTTP request. Only
-    // available for HTTP request.
-    // Note: the pseudo-header :path includes the query and fragment string. Use the `url_path`
-    // field if you want to match the URL path without the query and fragment string.
+    // A header (or pseudo-header such as :path or :method) on the incoming HTTP
+    // request. Only available for HTTP request. Note: the pseudo-header :path
+    // includes the query and fragment string. Use the `url_path` field if you
+    // want to match the URL path without the query and fragment string.
     route.v4alpha.HeaderMatcher header = 6;
 
     // A URL path on the incoming HTTP request. Only available for HTTP.
@@ -259,9 +287,9 @@ message Principal {
     // Metadata that describes additional information about the principal.
     type.matcher.v4alpha.MetadataMatcher metadata = 7;
 
-    // Negates matching the provided principal. For instance, if the value of `not_id` would match,
-    // this principal would not match. Conversely, if the value of `not_id` would not match, this
-    // principal would match.
+    // Negates matching the provided principal. For instance, if the value of
+    // `not_id` would match, this principal would not match. Conversely, if the
+    // value of `not_id` would not match, this principal would match.
     Principal not_id = 8;
   }
 }