aboutsummaryrefslogtreecommitdiff
path: root/pw_log_rpc/public/pw_log_rpc/log_filter.h
blob: 56e01f75b68337af1a7b99c0c7c7c0eacfef3cf2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
// Copyright 2021 The Pigweed Authors
//
// 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
//
//     https://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.

#pragma once

#include <cstddef>
#include <cstring>
#include <span>

#include "pw_assert/assert.h"
#include "pw_bytes/span.h"
#include "pw_containers/vector.h"
#include "pw_log/proto/log.pwpb.h"
#include "pw_log_rpc/internal/config.h"
#include "pw_status/status.h"

namespace pw::log_rpc {

// A Filter is a collection of rules used to check if a log entry can be kept
// or dropped wherever the filter is placed in the log path.
class Filter {
 public:
  struct Rule {
    // Action to perform if the rule is met.
    enum class Action {
      kInactive = 0,  // Ignore this rule.
      kKeep = 1,
      kDrop = 2,
    };
    Action action = Action::kInactive;

    // Checks if the log level is greater or equal to this value when it
    // does not equal NOT_SET.
    log::FilterRule::Level level_greater_than_or_equal =
        log::FilterRule::Level::ANY_LEVEL;

    // Checks if the log entry has any flag is set when it doesn't equal 0.
    uint32_t any_flags_set = 0;

    // Checks if the log entry module equals this value when not empty.
    Vector<std::byte, cfg::kMaxModuleNameBytes> module_equals{};
  };

  Filter(std::span<const std::byte> id, std::span<Rule> rules) : rules_(rules) {
    PW_ASSERT(!id.empty());
    id_.assign(id.begin(), id.end());
  }

  // Not copyable.
  Filter(const Filter&) = delete;
  Filter& operator=(const Filter&) = delete;

  ConstByteSpan id() const { return ConstByteSpan(id_.data(), id_.size()); }
  std::span<const Rule> rules() const { return rules_; }

  // Verifies a log entry against the filter's rules in the order they were
  // provided, stopping at the first rule that matches.
  // Returns true when the log should be dropped, false otherwise. Defaults to
  // false if there are no rules, or no rules were matched.
  bool ShouldDropLog(ConstByteSpan entry) const;

  // Decodes and updates the filter's rules given a buffer with a proto-encoded
  // log::Filter message. If there are more rules than this filter can hold, the
  // extra rules are discarded.
  //
  // Return values:
  // OK - rules were updated successfully.
  // FAILED_PRECONDITION - the provided buffer is empty.
  // Forwarded errors from protobuff::decoder.
  Status UpdateRulesFromProto(ConstByteSpan buffer);

 private:
  Vector<std::byte, cfg::kMaxFilterIdBytes> id_;
  std::span<Rule> rules_;
};

}  // namespace pw::log_rpc