Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions MODULE.bazel.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 6 additions & 4 deletions bazel/repositories.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -162,13 +162,15 @@ def data_dependency():
url = "https://github.com/redpanda-data/CRoaring/archive/c433d1c70c10fb2e40f049e019e2abbcafa6e69d.tar.gz",
)

# branch: v26.2.x-pre
# branch: rp_log_filter (adds force_tag overloads for the per-callsite
# log filter). Flip back to redpanda-data/seastar once the upstream PR
# merges.
http_archive(
name = "seastar",
build_file = "//bazel/thirdparty:seastar.BUILD",
sha256 = "9c572c5111ef6b4f0afc6ba358696c0e2a78e118bc3c3617cf6454a9d98970de",
strip_prefix = "seastar-617d3c421a949f449942d7ce0d275af0997efb48",
url = "https://github.com/redpanda-data/seastar/archive/617d3c421a949f449942d7ce0d275af0997efb48.tar.gz",
sha256 = "77feafdc928dc12b6a261ece933c19e070b901061fa56ff2114c1ded850afb1e",
strip_prefix = "seastar-8948822a046413306b8da155ab85674545ab7f04",
url = "https://github.com/WillemKauf/seastar/archive/8948822a046413306b8da155ab85674545ab7f04.tar.gz",
)

http_archive(
Expand Down
16 changes: 16 additions & 0 deletions proto/redpanda/core/admin/internal/v1/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,19 @@ redpanda_proto_library(
protos = [":breakglass_proto"],
visibility = ["//visibility:public"],
)

proto_library(
name = "log_filter_proto",
srcs = ["log_filter.proto"],
visibility = ["//visibility:public"],
deps = [
"//proto/redpanda/core/pbgen:options_proto",
"//proto/redpanda/core/pbgen:rpc_proto",
],
)

redpanda_proto_library(
name = "log_filter_redpanda_proto",
protos = [":log_filter_proto"],
visibility = ["//visibility:public"],
)
128 changes: 128 additions & 0 deletions proto/redpanda/core/admin/internal/v1/log_filter.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
// Copyright 2026 Redpanda Data, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";

package redpanda.core.admin.v2.internal;

import "proto/redpanda/core/pbgen/options.proto";
import "proto/redpanda/core/pbgen/rpc.proto";

option (pbgen.cpp_namespace) = "proto::admin";

// State value written onto every callsite a LogFilterRule matches, or
// reported by ListLogCallsites as the resolved state for a callsite.
enum LogFilterState {
// Proto3 default — rejected by SetLogFilter as INVALID_ARGUMENT,
// never returned by ListLogCallsites.
LOG_FILTER_STATE_UNSPECIFIED = 0;
// Callsite falls through to the logger's configured level gate.
LOG_FILTER_STATE_INHERITED = 1;
// Callsite emits regardless of the configured level.
LOG_FILTER_STATE_FORCE_ON = 2;
// Callsite is suppressed regardless of the configured level.
LOG_FILTER_STATE_FORCE_OFF = 3;
}

// A filter rule applied to every registered vlog callsite. Every populated
// predicate must match for the rule to apply: file is an fnmatch(3) glob
// against the callsite's __FILE__, line matches __LINE__ as described
// below, and contains is a substring search against the format-string
// literal. An empty rule (no predicates set) matches every callsite.
// Rules in a list are applied in order; the last matching rule's state
// value wins. A callsite matching no rule resolves to
// LOG_FILTER_STATE_INHERITED.
message LogFilterRule {
// fnmatch(3) glob pattern matched against the callsite's __FILE__.
optional string file = 1;
// Predicate on __LINE__. Accepts exactly one or two entries: a
// single value matches that line, two values [lo, hi] match the
// inclusive range lo <= __LINE__ <= hi. Any other size is rejected
// with INVALID_ARGUMENT.
repeated uint32 line = 2;
// Substring that must appear in the format-string literal.
optional string contains = 3;
// State written to every site the rule matches.
LogFilterState state = 4;
}

// A registered vlog callsite and its current enabled state.
message LogCallsiteInfo {
// Source-file basename (path stripped at compile time).
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The LogCallsiteInfo.file field comment says the value is a basename with the path stripped, but cs.file() comes from __FILE__ (and the PR description suggests matching on paths like src/v/storage/*). Either update the comment to describe the actual value (e.g. __FILE__ path as compiled), or change the implementation to strip to basename before returning it to clients so the API matches its documentation.

Suggested change
// Source-file basename (path stripped at compile time).
// Callsite source file path as compiled into __FILE__.

Copilot uses AI. Check for mistakes.
string file = 1;
// Source line.
uint32 line = 2;
// Format-string literal at the call site.
string fmt = 3;
// Resolved state for this callsite.
LogFilterState state = 4;
}

message SetLogFilterRequest {
// Rule list that replaces the currently active rules. Every registered
// callsite is re-evaluated against the new set. To add a rule to the
// active set, fetch the current rules with GetLogFilter, append to
// that list client-side, and resubmit here.
repeated LogFilterRule rules = 1;
}
message SetLogFilterResponse {}

message ResetLogFilterRequest {}
message ResetLogFilterResponse {}

message GetLogFilterRequest {}
message GetLogFilterResponse {
// Current active rules, in application order (last match wins).
repeated LogFilterRule rules = 1;
}

message ListLogCallsitesRequest {
// If set, only return callsites whose file matches this fnmatch(3) glob.
optional string file_filter = 1;
}
message ListLogCallsitesResponse {
repeated LogCallsiteInfo callsites = 1;
}

// LogFilterService controls the per-callsite vlog filter on the node that
// handles the RPC. Filter state is a per-node property — to apply the same
// filter cluster-wide, call each broker directly.
service LogFilterService {
// Replace the active rule set with the supplied rules and re-evaluate
// every registered callsite against them.
rpc SetLogFilter(SetLogFilterRequest) returns (SetLogFilterResponse) {
option (pbgen.rpc) = {
authz: SUPERUSER,
};
}
// Clear every rule and re-enable every callsite.
rpc ResetLogFilter(ResetLogFilterRequest) returns (ResetLogFilterResponse) {
option (pbgen.rpc) = {
authz: SUPERUSER,
};
}
// Return the currently active filter rules in application order.
rpc GetLogFilter(GetLogFilterRequest) returns (GetLogFilterResponse) {
option (pbgen.rpc) = {
authz: SUPERUSER,
};
}
// Enumerate all registered callsites and their current enabled state.
rpc ListLogCallsites(ListLogCallsitesRequest)
returns (ListLogCallsitesResponse) {
option (pbgen.rpc) = {
authz: SUPERUSER,
};
}
}
3 changes: 3 additions & 0 deletions src/v/base/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ redpanda_cc_library(
name = "base",
srcs = [
"vassert.cc",
"vlog_callsite.cc",
],
hdrs = [
"compiler_utils.h",
Expand All @@ -21,6 +22,8 @@ redpanda_cc_library(
"vassert.h",
"vassert-register.h",
"vlog.h",
"vlog_callsite.h",
"vlog_filter.h",
],
visibility = ["//visibility:public"],
deps = [
Expand Down
14 changes: 14 additions & 0 deletions src/v/base/tests/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,17 @@ redpanda_cc_gtest(
"@seastar",
],
)

redpanda_cc_gtest(
name = "vlog_filter_test",
timeout = "short",
srcs = [
"vlog_filter_test.cc",
],
deps = [
"//src/v/base",
"//src/v/test_utils:gtest",
"@googletest//:gtest",
"@seastar",
],
)
Loading
Loading