Line data Source code
1 : /*
2 : * Copyright (c) 2020-2023 Project CHIP Authors
3 : * Copyright (c) 2013-2017 Nest Labs, Inc.
4 : *
5 : * Licensed under the Apache License, Version 2.0 (the "License");
6 : * you may not use this file except in compliance with the License.
7 : * You may obtain a copy of the License at
8 : *
9 : * http://www.apache.org/licenses/LICENSE-2.0
10 : *
11 : * Unless required by applicable law or agreed to in writing, software
12 : * distributed under the License is distributed on an "AS IS" BASIS,
13 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 : * See the License for the specific language governing permissions and
15 : * limitations under the License.
16 : */
17 :
18 : /**
19 : * @file
20 : * This file implements macros, constants, and interfaces for a
21 : * platform-independent logging interface for the chip SDK.
22 : *
23 : */
24 :
25 : #include "TextOnlyLogging.h"
26 :
27 : #include <lib/core/CHIPConfig.h>
28 : #include <lib/support/CHIPMem.h>
29 :
30 : #include <platform/logging/LogV.h>
31 :
32 : #include <stdarg.h>
33 : #include <stdio.h>
34 : #include <string.h>
35 :
36 : #include <atomic>
37 :
38 : #if CHIP_PW_TOKENIZER_LOGGING
39 : #include "pw_tokenizer/encode_args.h"
40 : #endif
41 :
42 : namespace chip {
43 : namespace Logging {
44 :
45 : #if _CHIP_USE_LOGGING
46 :
47 : #if CHIP_PW_TOKENIZER_LOGGING
48 :
49 : void HandleTokenizedLog(uint32_t levels, pw_tokenizer_Token token, pw_tokenizer_ArgTypes types, ...)
50 : {
51 : uint8_t encoded_message[PW_TOKENIZER_CFG_ENCODING_BUFFER_SIZE_BYTES];
52 :
53 : memcpy(encoded_message, &token, sizeof(token));
54 :
55 : va_list args;
56 : va_start(args, types);
57 : // Use the C argument encoding API, since the C++ API requires C++17.
58 : const size_t encoded_size = sizeof(token) +
59 : pw_tokenizer_EncodeArgs(types, args, encoded_message + sizeof(token), sizeof(encoded_message) - sizeof(token));
60 : va_end(args);
61 :
62 : uint8_t log_category = levels >> 8 & 0xFF;
63 : uint8_t log_module = levels & 0xFF;
64 : char * logging_buffer = nullptr;
65 :
66 : // To reduce the number of alloc/free that is happening we will use a stack
67 : // buffer when buffer required to log is small.
68 : char stack_buffer[32];
69 : char * allocated_buffer = nullptr;
70 : size_t required_buffer_size = 2 * encoded_size + 1;
71 :
72 : if (required_buffer_size > sizeof(stack_buffer))
73 : {
74 : allocated_buffer = (char *) chip::Platform::MemoryAlloc(required_buffer_size);
75 : if (allocated_buffer)
76 : {
77 : logging_buffer = allocated_buffer;
78 : }
79 : }
80 : else
81 : {
82 : logging_buffer = stack_buffer;
83 : }
84 :
85 : if (logging_buffer)
86 : {
87 : for (size_t i = 0; i < encoded_size; i++)
88 : {
89 : sprintf(logging_buffer + 2 * i, "%02x", encoded_message[i]);
90 : }
91 : logging_buffer[2 * encoded_size] = '\0';
92 : Log(log_module, log_category, "%s", logging_buffer);
93 : }
94 : if (allocated_buffer)
95 : {
96 : chip::Platform::MemoryFree(allocated_buffer);
97 : }
98 : }
99 :
100 : #endif
101 :
102 : namespace {
103 :
104 : std::atomic<LogRedirectCallback_t> sLogRedirectCallback{ nullptr };
105 :
106 : /*
107 : * Array of strings containing the names for each of the chip log modules.
108 : *
109 : * NOTE: The names must be in the order defined in the LogModule enumeration.
110 : */
111 : static const char ModuleNames[kLogModule_Max][kMaxModuleNameLen + 1] = {
112 : "-", // None
113 : "IN", // Inet
114 : "BLE", // BLE
115 : "ML", // MessageLayer
116 : "SM", // SecurityManager
117 : "EM", // ExchangeManager
118 : "TLV", // TLV
119 : "ASN", // ASN1
120 : "CR", // Crypto
121 : "CTL", // Controller
122 : "AL", // Alarm
123 : "SC", // SecureChannel
124 : "BDX", // BulkDataTransfer
125 : "DMG", // DataManagement
126 : "DC", // DeviceControl
127 : "DD", // DeviceDescription
128 : "ECH", // Echo
129 : "FP", // FabricProvisioning
130 : "NP", // NetworkProvisioning
131 : "SD", // ServiceDirectory
132 : "SP", // ServiceProvisioning
133 : "SWU", // SoftwareUpdate
134 : "FS", // FailSafe
135 : "TS", // TimeService
136 : "HB", // Heartbeat
137 : "CSL", // chipSystemLayer
138 : "EVL", // Event Logging
139 : "SPT", // Support
140 : "TOO", // chipTool
141 : "ZCL", // Zcl
142 : "SH", // Shell
143 : "DL", // DeviceLayer
144 : "SPL", // SetupPayload
145 : "SVR", // AppServer
146 : "DIS", // Discovery
147 : "IM", // InteractionModel
148 : "TST", // Test
149 : "OSS", // OperationalSessionSetup
150 : "ATM", // Automation
151 : "CSM", // CASESessionManager
152 : "ICD", // ICD
153 : "FS", // FabricSync
154 : };
155 :
156 : } // namespace
157 :
158 1161652 : const char * GetModuleName(LogModule module)
159 : {
160 1161652 : return ModuleNames[(module < kLogModule_Max) ? module : kLogModule_NotSpecified];
161 : }
162 :
163 10 : void SetLogRedirectCallback(LogRedirectCallback_t callback)
164 : {
165 10 : sLogRedirectCallback.store(callback);
166 10 : }
167 :
168 : /**
169 : * Log, to the platform-specified mechanism, the specified log
170 : * message, @a msg, for the specified module, @a module, in the
171 : * provided category, @a category.
172 : *
173 : * @param[in] module A LogModule enumeration indicating the
174 : * source of the chip package module that
175 : * generated the log message. This must be
176 : * translated within the function to a module
177 : * name for inclusion in the log message.
178 : * @param[in] category A LogCategory enumeration indicating the
179 : * category of the log message. The category
180 : * may be filtered in or out if
181 : * CHIP_LOG_FILTERING was asserted.
182 : * @param[in] msg A pointer to a NULL-terminated C string with
183 : * C Standard Library-style format specifiers
184 : * containing the log message to be formatted and
185 : * logged.
186 : * @param[in] ... A variadic argument list whose elements should
187 : * correspond to the format specifiers in @a msg.
188 : *
189 : */
190 1161652 : void Log(uint8_t module, uint8_t category, const char * msg, ...)
191 : {
192 :
193 : va_list v;
194 1161652 : va_start(v, msg);
195 1161652 : LogV(module, category, msg, v);
196 1161652 : va_end(v);
197 1161652 : }
198 :
199 1161652 : void LogV(uint8_t module, uint8_t category, const char * msg, va_list args)
200 : {
201 1161652 : const char * moduleName = GetModuleName(static_cast<LogModule>(module));
202 1161652 : LogRedirectCallback_t redirect = sLogRedirectCallback.load();
203 1161652 : if (redirect != nullptr)
204 : {
205 11 : redirect(moduleName, category, msg, args);
206 : }
207 : else
208 : {
209 1161641 : Platform::LogV(moduleName, category, msg, args);
210 : }
211 1161652 : }
212 :
213 : #if CHIP_LOG_FILTERING
214 : std::atomic<uint8_t> gLogFilter(kLogCategory_Max);
215 :
216 1161648 : uint8_t GetLogFilter()
217 : {
218 1161648 : return gLogFilter.load();
219 : }
220 :
221 0 : void SetLogFilter(uint8_t category)
222 : {
223 0 : gLogFilter.store(category);
224 0 : }
225 :
226 1161648 : bool IsCategoryEnabled(uint8_t category)
227 : {
228 1161648 : return (category <= GetLogFilter());
229 : }
230 : #endif // CHIP_LOG_FILTERING
231 :
232 : #endif // _CHIP_USE_LOGGING
233 :
234 : } // namespace Logging
235 : } // namespace chip
|