• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2020 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// the License at
6//
7//     https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14
15syntax = "proto2";
16
17package pw.log;
18
19option java_package = "pw.rpc.proto";
20option java_outer_classname = "Log";
21
22// A log with a tokenized message, a string message, or dropped indicator.  A
23// message can be one of three types:
24//
25//  1. A tokenized log message (recommended for production)
26//  2. A non-tokenized log message (good for development)
27//  3. A "log missed" tombstone, indicating that some logs were dropped
28//
29// Size analysis:
30//
31// For tokenized log messages in the common case; including the proto tag for
32// the field (so adding the fields gives the total proto message size):
33//
34//  - message_tokenized  - 6-12 bytes, depending on # and value of arguments
35//  - line_level         - 3 bytes; 4 bytes if line > 2048 (uncommon)
36//  - timestamp          - 3 bytes; assuming delta encoding
37//  - thread_tokenized   - 3 bytes
38//
39// Total:
40//
41//    6-12 bytes - log
42//    9-15 bytes - log + level + line
43//   12-18 bytes - log + level + line + timestamp
44//   15-21 bytes - log + level + line + timestamp + task
45//
46// An analysis of a project's log token database revealed the following
47// distribution of the number of arguments to log messages:
48//
49//   # args   # messages
50//     0         2,700
51//     1         2,400
52//     2         1,200
53//     3+        1,000
54//
55// Note: The below proto makes some compromises compared to what one might
56// expect for a "clean" proto design, in order to shave bytes off of the
57// messages. It is critical that the log messages are as small as possible to
58// enable storing more logs in limited memory. This is why, for example, there
59// is no separate "DroppedLog" type, or a "TokenizedLog" and "StringLog", which
60// would add at least 2 extra bytes per message
61// Note: Time-related fields will likely support specifying the time as a ratio
62// (period) and an absolute time separate from the current delta fields.
63message LogEntry {
64  // The tokenized log message. Internally, the format has a 32-bit token
65  // followed by the arguments for that message. The unformatted log string
66  // corresponding to the token in the token database must follow this format:
67  //
68  //   file|module|message
69  //
70  // For example:
71  //
72  //   ../boot/bluetooth.cc|BOOT|Bluetooth is on the fritz; error code: %d
73  //
74  // Note: The level and flags are not included since level and flags are
75  // runtime values and so cannot be tokenized.
76  //
77  // Size analysis:
78  //
79  //   tag+wire = 1 byte
80  //   size     = 1 byte; payload will almost always be < 127 bytes
81  //   payload  = N bytes; typically 4-10 in practice
82  //
83  // Total: 2 + N ~= 6-12 bytes
84  optional bytes message_tokenized = 1;
85
86  // Packed log level and line number. Structure:
87  //
88  //   Level: Bottom 3 bits; level = line_level & 0x7
89  //   Line: Remaining bits; line = (line_level >> 3)
90  //
91  // Note: This packing saves two bytes per log message in most cases compared
92  // to having line and level separately; and is zero-cost if the log backend
93  // omits the line number.
94  optional uint32 line_level = 2;
95
96  // Some log messages have flags to indicate for example assert or PII. The
97  // particular flags are product- and implementation-dependent. When no flags
98  // are present, the field is omitted entirely.
99  optional uint32 flags = 3;
100
101  // The task or thread that created the log message.
102  //
103  // In practice, the task token and tag should be just 3 bytes, since a 14 bit
104  // token for the task name should be enough.
105  optional uint32 thread_tokenized = 4;
106
107  // Timestamp. Note: The units here are TBD and will likely require a separate
108  // mechanism to indicate units. This field is likely to change as we figure
109  // out the right strategy for timestamps in Pigweed. This is a variable-sized
110  // integer to enable scaling this up to a uint64 later on without impacting
111  // the wire format.
112  optional int64 timestamp = 5;
113
114  // Time since the last entry. Generally, one of timestamp or this field will
115  // be specified. This enables delta encoding when batching entries together.
116  //
117  // Size analysis for this field including tag and varint:
118  //
119  //           < 127 ms gap == 127 ms      ==  7 bits == 2 bytes
120  //        < 16,000 ms gap ==  16 seconds == 14 bits == 3 bytes
121  //     < 2,000,000 ms gap ==  35 minutes == 21 bits == 4 bytes
122  //   < 300,000,000 ms gap ==  74 hours   == 28 bits == 5 bytes
123  //
124  // Log bursts will thus consume just 2 bytes (tag + up to 127ms delta) for
125  // the timestamp, which is a good improvement over timestamp in many cases.
126  // Note: The units of this field are TBD and will likely require a separate
127  // mechanism to indicate units. The calculations above assume milliseconds
128  // and may change if the units differ.
129  optional int64 elapsed_time_since_last_entry = 6;
130
131  // Fully formatted textual log message.
132  optional string message_string = 16;
133
134  // For non-tokenized logging, the file name.
135  optional string file = 17;
136
137  // String representation of the task that created the log message.
138  optional string thread_string = 18;
139
140  // When the log buffers are full but more logs come in, the logs are counted
141  // and a special log message is omitted with only counts for the number of
142  // messages dropped. The timestamp indicates the time that the "missed logs"
143  // message was inserted into the queue.
144  //
145  // Missed logs messages will only have one of the timestamp fields and these
146  // counters specified.
147  optional uint32 dropped = 19;
148  optional uint32 dropped_warning_or_above = 20;
149
150  // Some messages are associated with trace events, which may carry additional
151  // contextual data. This is a tuple of a data format string which could be
152  // used by the decoder to identify the data (e.g. printf-style tokens) and the
153  // data itself in bytes.
154  optional string data_format_string = 21;
155  optional bytes data = 22;
156}
157
158message LogRequest {}
159message LogEntries {
160  repeated LogEntry entries = 1;
161}
162
163service Logs {
164  rpc Get(LogRequest) returns (stream LogEntries) {}
165}
166