Skip to content

Commit b8f12dd

Browse files
Modified the logging methods, added helpers and switched to a dynamical allocation for the trace buffer
1 parent 984f6ee commit b8f12dd

File tree

6 files changed

+266
-50
lines changed

6 files changed

+266
-50
lines changed

examples/platform/silabs/silabs_utils.h

-2
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@
2424
extern "C" {
2525
#endif
2626

27-
bool isLogInitialized(void);
28-
2927
void silabsInitLog(void);
3028

3129
void silabsLog(const char * aFormat, ...);

src/platform/silabs/Logging.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ extern "C" void silabsLog(const char * aFormat, ...)
201201
}
202202

203203
#ifdef SILABS_LOG_ENABLED
204-
extern bool isLogInitialized()
204+
bool isLogInitialized()
205205
{
206206
return sLogInitialized;
207207
}

src/platform/silabs/Logging.h

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
*
3+
* Copyright (c) 2024 Silabs.
4+
* All rights reserved.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
#pragma once
20+
21+
bool isLogInitialized(void);

src/platform/silabs/tracing/SilabsTracing.cpp

+176-42
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#include <lib/support/PersistentData.h>
55

66
#if !CONFIG_BUILD_FOR_HOST_UNIT_TEST
7-
#include <silabs_utils.h> // for isLogInitialized
7+
#include <Logging.h> // for isLogInitialized
88
#endif
99

1010
// The following functions needs to be implemented by the application to allows logging or storing the traces /
@@ -18,6 +18,8 @@ namespace chip {
1818
namespace Tracing {
1919
namespace Silabs {
2020

21+
// TODO add string mapping to log the operation names and types
22+
2123
static constexpr size_t kPersistentTimeTrackerBufferMax = SERIALIZED_TIME_TRACKERS_SIZE_BYTES;
2224

2325
struct TimeTrackerStorage : public TimeTracker, PersistentData<kPersistentTimeTrackerBufferMax>
@@ -29,14 +31,50 @@ SilabsTracer SilabsTracer::sInstance;
2931

3032
SilabsTracer::SilabsTracer()
3133
{
32-
Init();
34+
VerifyOrDie(Init() == CHIP_NO_ERROR);
3335
}
3436

35-
void SilabsTracer::Init()
37+
CHIP_ERROR SilabsTracer::TraceBufferClear()
3638
{
37-
// Initialize the trace buffer and time trackers
38-
memset(mTraceBuffer, 0, sizeof(mTraceBuffer));
39+
// Free the allocated memory for the trace buffer
40+
if (nullptr != mTraceBuffer)
41+
{
42+
for (size_t i = 0; i < kBufferedTracesNumber; ++i)
43+
{
44+
free(mTraceBuffer[i]);
45+
}
46+
free(mTraceBuffer);
47+
mTraceBuffer = nullptr;
48+
mBufferIndex = 0;
49+
}
50+
return CHIP_NO_ERROR;
51+
}
52+
53+
CHIP_ERROR SilabsTracer::Init()
54+
{
55+
// Allows to use Init as a Reset function
56+
ReturnErrorOnFailure(TraceBufferClear());
57+
58+
// Allocate memory for the trace buffer
59+
mTraceBuffer = static_cast<uint8_t **>(malloc(kBufferedTracesNumber * sizeof(uint8_t *)));
60+
VerifyOrReturnError(nullptr != mTraceBuffer, CHIP_ERROR_NO_MEMORY);
61+
62+
for (size_t i = 0; i < kBufferedTracesNumber; ++i)
63+
{
64+
mTraceBuffer[i] = static_cast<uint8_t *>(malloc(kBufferedTraceSize * sizeof(uint8_t)));
65+
VerifyOrReturnError(nullptr != mTraceBuffer[i], CHIP_ERROR_NO_MEMORY);
66+
memset(mTraceBuffer[i], 0, kBufferedTraceSize);
67+
}
68+
69+
// Initialize the time trackers
3970
memset(mWatermark, 0, sizeof(mWatermark));
71+
72+
return CHIP_NO_ERROR;
73+
}
74+
75+
CHIP_ERROR SilabsTracer::StartLogging()
76+
{
77+
return TraceBufferFlush();
4078
}
4179

4280
CHIP_ERROR SilabsTracer::StartTraceStorage(PersistentStorageDelegate * storage)
@@ -52,96 +90,175 @@ void SilabsTracer::TimeTraceBegin(TimeTraceOperation aOperation)
5290
auto & tracker = mWatermark[static_cast<size_t>(aOperation)];
5391
tracker.mTotalCount++;
5492
tracker.mStartTime = System::SystemClock().GetMonotonicTimestamp();
93+
OutputTrace(aOperation, OperationType::kBegin, CHIP_NO_ERROR);
5594
}
5695

5796
void SilabsTracer::TimeTraceEnd(TimeTraceOperation aOperation, CHIP_ERROR error)
5897
{
5998
if (error != CHIP_NO_ERROR)
6099
{
61-
// Log the error, no need to update the watermark for now as we can get the error count from the
62-
// total count - successfull count. We might want to have a separate count for errors in the future.
63-
TimeTraceInstant(aOperation);
100+
OutputTrace(aOperation, OperationType::kEnd, error);
64101
return;
65102
}
66103

67104
// Calculate the duration and update the time tracker
68105
auto & tracker = mWatermark[static_cast<size_t>(aOperation)];
69106
tracker.mEndTime = System::SystemClock().GetMonotonicTimestamp();
70-
auto duration = (tracker.mEndTime - tracker.mStartTime).count();
107+
auto duration = tracker.mEndTime - tracker.mStartTime;
71108

72109
tracker.mTotalDuration += System::Clock::Milliseconds64(duration);
73110

74-
if (duration > tracker.mMaxTimeMs.count())
111+
if (duration > tracker.mMaxTimeMs)
75112
{
76113
tracker.mMaxTimeMs = System::Clock::Milliseconds32(duration);
77114
}
78115

79-
if (tracker.mMinTimeMs.count() == 0 || duration < tracker.mMinTimeMs.count())
116+
if (tracker.mMinTimeMs.count() == 0 || duration < tracker.mMinTimeMs)
80117
{
81118
tracker.mMinTimeMs = System::Clock::Milliseconds32(duration);
82119
}
83120

84121
tracker.mSuccessfullCount++;
85-
tracker.mMovingAverage = System::Clock::Milliseconds32(tracker.mTotalDuration.count() / tracker.mSuccessfullCount);
86-
if (duration > tracker.mMovingAverage.count())
122+
tracker.mMovingAverage = System::Clock::Milliseconds32(tracker.mTotalDuration / tracker.mSuccessfullCount);
123+
if (duration > tracker.mMovingAverage)
87124
{
88125
tracker.mCountAboveAvg++;
89126
}
127+
128+
OutputTrace(aOperation, OperationType::kEnd, CHIP_NO_ERROR);
90129
}
91130

92131
void SilabsTracer::TimeTraceInstant(TimeTraceOperation aOperation, CHIP_ERROR error)
93132
{
94-
if (CHIP_NO_ERROR == error)
133+
OutputTrace(aOperation, OperationType::kInstant, error);
134+
}
135+
136+
CHIP_ERROR SilabsTracer::OutputTrace(TimeTraceOperation aOperation, OperationType type, CHIP_ERROR error)
137+
{
138+
uint64_t timestamp = System::SystemClock().GetMonotonicTimestamp().count();
139+
uint8_t operation = static_cast<uint8_t>(aOperation);
140+
uint8_t opType = static_cast<uint8_t>(type);
141+
142+
if (isLogInitialized())
143+
{
144+
if (error == CHIP_NO_ERROR)
145+
{
146+
ChipLogProgress(DeviceLayer, "Time: %llu, Operation: %u, Type: %u", timestamp, operation, opType);
147+
}
148+
else
149+
{
150+
ChipLogError(DeviceLayer, "Time: %llu, Operation: %u, Type: %u, Error: %" CHIP_ERROR_FORMAT, timestamp, operation,
151+
opType, error.Format());
152+
return CHIP_ERROR_INTERNAL;
153+
}
154+
}
155+
else
156+
{
157+
if (mBufferIndex < kBufferedTracesNumber - 1)
158+
{
159+
if (error == CHIP_NO_ERROR)
160+
{
161+
snprintf(reinterpret_cast<char *>(mTraceBuffer[mBufferIndex]), kBufferedTraceSize,
162+
"Time: %llu, Operation: %u, Type: %u", timestamp, operation, opType);
163+
}
164+
else
165+
{
166+
snprintf(reinterpret_cast<char *>(mTraceBuffer[mBufferIndex]), kBufferedTraceSize,
167+
"Time: %llu, Operation: %u, Type: %u, Error: %" CHIP_ERROR_FORMAT, timestamp, operation, opType,
168+
error.Format());
169+
}
170+
mBufferIndex++;
171+
}
172+
else
173+
{
174+
snprintf(reinterpret_cast<char *>(mTraceBuffer[mBufferIndex]), kBufferedTraceSize, "Buffer overflow: logs were lost");
175+
}
176+
}
177+
178+
return CHIP_NO_ERROR;
179+
}
180+
181+
void SilabsTracer::BufferTrace(size_t index, const TimeTracker & tracker, CHIP_ERROR error)
182+
{
183+
if (mBufferIndex < kBufferedTracesNumber - 1)
95184
{
96-
// Will be used to implement count for instant events that do not require watermarks such as failures and others
97-
// For now, just log in that order the timestamp and the operation
98-
ChipLogProgress(DeviceLayer, "Time: %llu, Instant Trace: %u, ", System::SystemClock().GetMonotonicTimestamp().count(),
99-
static_cast<uint8_t>(aOperation));
185+
if (error == CHIP_NO_ERROR)
186+
{
187+
snprintf(reinterpret_cast<char *>(mTraceBuffer[mBufferIndex]), kBufferedTraceSize,
188+
"Trace %zu: TotalCount=%" PRIu32 ", SuccessFullCount=%" PRIu32 ", MaxTime=%" PRIu32 ", MinTime=%" PRIu32
189+
", AvgTime=%" PRIu32 ", CountAboveAvg=%" PRIu32 "",
190+
index, tracker.mTotalCount, tracker.mSuccessfullCount, tracker.mMaxTimeMs.count(), tracker.mMinTimeMs.count(),
191+
tracker.mMovingAverage.count(), tracker.mCountAboveAvg);
192+
}
193+
else
194+
{
195+
snprintf(reinterpret_cast<char *>(mTraceBuffer[mBufferIndex]), kBufferedTraceSize,
196+
"Trace %zu: Error: %" CHIP_ERROR_FORMAT, index, error.Format());
197+
}
198+
mBufferIndex++;
100199
}
101200
else
102201
{
103-
// Log the error with timestamp and operation
104-
ChipLogError(DeviceLayer, "Time: %llu, Instant Trace: %u, Error: %" CHIP_ERROR_FORMAT,
105-
System::SystemClock().GetMonotonicTimestamp().count(), static_cast<uint8_t>(aOperation), error.Format());
202+
snprintf(reinterpret_cast<char *>(mTraceBuffer[mBufferIndex]), kBufferedTraceSize, "Buffer overflow: logs were lost");
106203
}
107204
}
108205

109-
void SilabsTracer::OutputTraces()
206+
CHIP_ERROR SilabsTracer::OutputWaterMark(TimeTraceOperation aOperation, CHIP_ERROR error)
110207
{
208+
size_t index = static_cast<size_t>(aOperation);
209+
auto & tracker = mWatermark[index];
210+
111211
if (isLogInitialized())
112212
{
113-
// Output the traces from the buffer
114-
for (size_t i = 0; i < kNumTraces; ++i)
213+
if (error == CHIP_NO_ERROR)
115214
{
116-
auto & tracker = mWatermark[i];
117215
ChipLogProgress(DeviceLayer,
118-
"Trace %zu: TotalCount=%u, SuccessFullCount=%u, MaxTime=%u, MinTime=%u, AvgTime=%u, CountAboveAvg=%u",
119-
i, tracker.mTotalCount, tracker.mSuccessfullCount, tracker.mMaxTimeMs.count(),
216+
"Trace %zu: TotalCount=%" PRIu32 ", SuccessFullCount=%" PRIu32 ", MaxTime=%" PRIu32 ", MinTime=%" PRIu32
217+
", AvgTime=%" PRIu32 ", CountAboveAvg=%" PRIu32 "",
218+
index, tracker.mTotalCount, tracker.mSuccessfullCount, tracker.mMaxTimeMs.count(),
120219
tracker.mMinTimeMs.count(), tracker.mMovingAverage.count(), tracker.mCountAboveAvg);
121220
}
221+
else
222+
{
223+
ChipLogError(DeviceLayer, "Trace %zu: Error: %" CHIP_ERROR_FORMAT, index, error.Format());
224+
return CHIP_ERROR_INTERNAL;
225+
}
122226
}
123227
else
124228
{
125-
// Buffer the traces if logs are not initialized
126-
static size_t bufferIndex = 0;
127-
if (bufferIndex < kBufferedTracesNumber - 1)
229+
BufferTrace(index, tracker, error);
230+
}
231+
232+
return CHIP_NO_ERROR;
233+
}
234+
235+
CHIP_ERROR SilabsTracer::OutputAllWaterMarks()
236+
{
237+
for (size_t i = 0; i < kNumTraces; ++i)
238+
{
239+
CHIP_ERROR err = OutputWaterMark(static_cast<TimeTraceOperation>(i), CHIP_NO_ERROR);
240+
if (err != CHIP_NO_ERROR)
128241
{
129-
for (size_t i = 0; i < kNumTraces; ++i)
130-
{
131-
auto & tracker = mWatermark[i];
132-
// TODO use c++ copy string
133-
snprintf(reinterpret_cast<char *>(mTraceBuffer[bufferIndex]), kBufferedTraceSize,
134-
"Trace %zu: TotalCount=%u, SuccessFullCount=%u, MaxTime=%u, MinTime=%u, AvgTime=%u, CountAboveAvg=%u", i,
135-
tracker.mTotalCount, tracker.mSuccessfullCount, tracker.mMaxTimeMs.count(), tracker.mMinTimeMs.count(),
136-
tracker.mMovingAverage.count(), tracker.mCountAboveAvg);
137-
bufferIndex++;
138-
}
242+
return err;
139243
}
140-
else
244+
}
245+
return CHIP_NO_ERROR;
246+
}
247+
248+
CHIP_ERROR SilabsTracer::TraceBufferFlush()
249+
{
250+
if (isLogInitialized() && (nullptr != mTraceBuffer))
251+
{
252+
for (size_t i = 0; i < kBufferedTracesNumber; ++i)
141253
{
142-
snprintf(reinterpret_cast<char *>(mTraceBuffer[bufferIndex]), kBufferedTraceSize, "Buffer overflow: logs were lost");
254+
if (mTraceBuffer[i][0] != '\0') // Check if the buffer is not empty
255+
{
256+
ChipLogProgress(DeviceLayer, "%s", mTraceBuffer[i]);
257+
}
143258
}
144259
}
260+
261+
return TraceBufferClear();
145262
}
146263

147264
// Save the traces in the NVM
@@ -159,6 +276,23 @@ CHIP_ERROR SilabsTracer::LoadWatermarks()
159276
return CHIP_NO_ERROR;
160277
}
161278

279+
#if CONFIG_BUILD_FOR_HOST_UNIT_TEST
280+
CHIP_ERROR SilabsTracer::GetTraceCount(size_t & count) const
281+
{
282+
VerifyOrReturnError(nullptr != mTraceBuffer, CHIP_ERROR_INCORRECT_STATE);
283+
count = mBufferIndex;
284+
return CHIP_NO_ERROR;
285+
}
286+
287+
CHIP_ERROR SilabsTracer::GetTraceByIndex(size_t index, const char *& trace) const
288+
{
289+
VerifyOrReturnError(nullptr != mTraceBuffer, CHIP_ERROR_INCORRECT_STATE);
290+
VerifyOrReturnError(index < mBufferIndex, CHIP_ERROR_INVALID_ARGUMENT);
291+
trace = reinterpret_cast<const char *>(mTraceBuffer[index]);
292+
return CHIP_NO_ERROR;
293+
}
294+
#endif
295+
162296
} // namespace Silabs
163297
} // namespace Tracing
164298
} // namespace chip

0 commit comments

Comments
 (0)