Skip to content

Commit dc8cb19

Browse files
Updated the tracing structures, added metrics for OTA and now using a list and buffering traces of events
1 parent 40d903f commit dc8cb19

File tree

3 files changed

+405
-336
lines changed

3 files changed

+405
-336
lines changed

src/platform/silabs/tracing/SilabsTracing.cpp

+131-153
Original file line numberDiff line numberDiff line change
@@ -34,50 +34,28 @@ SilabsTracer::SilabsTracer()
3434
VerifyOrDie(Init() == CHIP_NO_ERROR);
3535
}
3636

37-
CHIP_ERROR SilabsTracer::TraceBufferClear()
37+
void SilabsTracer::TraceBufferClear()
3838
{
39-
// Free the allocated memory for the trace buffer
40-
if (nullptr != mTraceBuffer)
39+
// Clear the time tracker list
40+
while (mTimeTrackerList.head != nullptr)
4141
{
42-
for (size_t i = 0; i < kBufferedTracesNumber; ++i)
43-
{
44-
free(mTraceBuffer[i]);
45-
}
46-
free(mTraceBuffer);
47-
mTraceBuffer = nullptr;
48-
mBufferIndex = 0;
42+
mTimeTrackerList.Remove(0);
4943
}
50-
return CHIP_NO_ERROR;
44+
mBufferedTrackerCount = 0;
5145
}
5246

5347
CHIP_ERROR SilabsTracer::Init()
5448
{
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-
}
49+
TraceBufferClear();
6850

6951
// Initialize the time trackers
70-
memset(mWatermark, 0, sizeof(mWatermark));
52+
memset(mTimeTrackers, 0, sizeof(mTimeTrackers));
53+
memset(mWatermarks, 0, sizeof(mWatermarks));
7154

7255
return CHIP_NO_ERROR;
7356
}
7457

75-
CHIP_ERROR SilabsTracer::StartLogging()
76-
{
77-
return TraceBufferFlush();
78-
}
79-
80-
CHIP_ERROR SilabsTracer::StartTraceStorage(PersistentStorageDelegate * storage)
58+
CHIP_ERROR SilabsTracer::StartWatermarksStorage(PersistentStorageDelegate * storage)
8159
{
8260
VerifyOrReturnError(nullptr != storage, CHIP_ERROR_INCORRECT_STATE);
8361
mStorage = storage;
@@ -87,148 +65,114 @@ CHIP_ERROR SilabsTracer::StartTraceStorage(PersistentStorageDelegate * storage)
8765
void SilabsTracer::TimeTraceBegin(TimeTraceOperation aOperation)
8866
{
8967
// Log the start time of the operation
90-
auto & tracker = mWatermark[static_cast<size_t>(aOperation)];
91-
tracker.mTotalCount++;
68+
auto & tracker = mTimeTrackers[static_cast<size_t>(aOperation)];
9269
tracker.mStartTime = System::SystemClock().GetMonotonicTimestamp();
93-
OutputTrace(aOperation, OperationType::kBegin, CHIP_NO_ERROR);
70+
tracker.mOperation = aOperation;
71+
tracker.mType = OperationType::kBegin;
72+
tracker.mError = CHIP_NO_ERROR;
73+
74+
auto & watermark = mWatermarks[static_cast<size_t>(aOperation)];
75+
watermark.mTotalCount++;
76+
77+
OutputTrace(tracker);
9478
}
9579

9680
void SilabsTracer::TimeTraceEnd(TimeTraceOperation aOperation, CHIP_ERROR error)
9781
{
98-
if (error != CHIP_NO_ERROR)
99-
{
100-
OutputTrace(aOperation, OperationType::kEnd, error);
101-
return;
102-
}
103-
104-
// Calculate the duration and update the time tracker
105-
auto & tracker = mWatermark[static_cast<size_t>(aOperation)];
82+
auto & tracker = mTimeTrackers[static_cast<size_t>(aOperation)];
10683
tracker.mEndTime = System::SystemClock().GetMonotonicTimestamp();
107-
auto duration = tracker.mEndTime - tracker.mStartTime;
108-
109-
tracker.mTotalDuration += System::Clock::Milliseconds64(duration);
84+
tracker.mType = OperationType::kEnd;
85+
tracker.mError = error;
11086

111-
if (duration > tracker.mMaxTimeMs)
87+
if (error == CHIP_NO_ERROR)
11288
{
113-
tracker.mMaxTimeMs = System::Clock::Milliseconds32(duration);
114-
}
89+
// Calculate the duration and update the time tracker
90+
auto duration = tracker.mEndTime - tracker.mStartTime;
11591

116-
if (tracker.mMinTimeMs.count() == 0 || duration < tracker.mMinTimeMs)
117-
{
118-
tracker.mMinTimeMs = System::Clock::Milliseconds32(duration);
119-
}
92+
auto & watermark = mWatermarks[static_cast<size_t>(aOperation)];
93+
watermark.mSuccessfullCount++;
94+
watermark.mMovingAverage = System::Clock::Milliseconds32(
95+
(watermark.mMovingAverage.count() * (watermark.mSuccessfullCount - 1) + duration.count()) /
96+
watermark.mSuccessfullCount);
12097

121-
tracker.mSuccessfullCount++;
122-
tracker.mMovingAverage = System::Clock::Milliseconds32(tracker.mTotalDuration / tracker.mSuccessfullCount);
123-
if (duration > tracker.mMovingAverage)
124-
{
125-
tracker.mCountAboveAvg++;
98+
if (duration > watermark.mMaxTimeMs)
99+
{
100+
watermark.mMaxTimeMs = System::Clock::Milliseconds32(duration);
101+
}
102+
103+
if (watermark.mMinTimeMs.count() == 0 || duration < watermark.mMinTimeMs)
104+
{
105+
watermark.mMinTimeMs = System::Clock::Milliseconds32(duration);
106+
}
107+
108+
if (duration > watermark.mMovingAverage)
109+
{
110+
watermark.mCountAboveAvg++;
111+
}
126112
}
127113

128-
OutputTrace(aOperation, OperationType::kEnd, CHIP_NO_ERROR);
114+
OutputTrace(tracker);
129115
}
130116

131117
void SilabsTracer::TimeTraceInstant(TimeTraceOperation aOperation, CHIP_ERROR error)
132118
{
133-
OutputTrace(aOperation, OperationType::kInstant, error);
119+
auto & tracker = mTimeTrackers[static_cast<size_t>(aOperation)];
120+
tracker.mStartTime = System::SystemClock().GetMonotonicTimestamp();
121+
tracker.mEndTime = tracker.mStartTime;
122+
tracker.mOperation = aOperation;
123+
tracker.mType = OperationType::kInstant;
124+
tracker.mError = error;
125+
OutputTrace(tracker);
134126
}
135127

136-
CHIP_ERROR SilabsTracer::OutputTrace(TimeTraceOperation aOperation, OperationType type, CHIP_ERROR error)
128+
CHIP_ERROR SilabsTracer::OutputTimeTracker(const TimeTracker & tracker)
137129
{
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: %" PRIu64 ", Operation: %" PRIu32 ", Type: %" PRIu32 "", timestamp, operation,
147-
opType);
148-
}
149-
else
150-
{
151-
ChipLogError(DeviceLayer, "Time: %" PRIu64 ", Operation: %" PRIu32 ", Type: %" PRIu32 ", Error: %" CHIP_ERROR_FORMAT,
152-
timestamp, operation, opType, error.Format());
153-
return CHIP_ERROR_INTERNAL;
154-
}
155-
}
156-
else
157-
{
158-
if (mBufferIndex < kBufferedTracesNumber - 1)
159-
{
160-
if (error == CHIP_NO_ERROR)
161-
{
162-
snprintf(reinterpret_cast<char *>(mTraceBuffer[mBufferIndex]), kBufferedTraceSize,
163-
"Time: %" PRIu64 ", Operation: %" PRIu32 ", Type: %" PRIu32 "", timestamp, operation, opType);
164-
}
165-
else
166-
{
167-
snprintf(reinterpret_cast<char *>(mTraceBuffer[mBufferIndex]), kBufferedTraceSize,
168-
"Time: %" PRIu64 ", Operation: %" PRIu32 ", Type: %" PRIu32 ", Error: %" CHIP_ERROR_FORMAT, timestamp,
169-
operation, opType, error.Format());
170-
}
171-
mBufferIndex++;
172-
}
173-
else
174-
{
175-
snprintf(reinterpret_cast<char *>(mTraceBuffer[mBufferIndex]), kBufferedTraceSize, "Buffer overflow: logs were lost");
176-
}
177-
}
178-
130+
VerifyOrReturnError(isLogInitialized(), CHIP_ERROR_UNINITIALIZED);
131+
ChipLogProgress(DeviceLayer,
132+
"TimeTracker - StartTime: %" PRIu32 ", EndTime: %" PRIu32 ", Operation: %" PRIu8 ", Type: %" PRIu8
133+
", Error: %" CHIP_ERROR_FORMAT,
134+
tracker.mStartTime.count(), tracker.mEndTime.count(), static_cast<uint8_t>(tracker.mOperation),
135+
static_cast<uint8_t>(tracker.mType), tracker.mError.Format());
179136
return CHIP_NO_ERROR;
180137
}
181138

182-
void SilabsTracer::BufferTrace(size_t index, const TimeTracker & tracker, CHIP_ERROR error)
139+
CHIP_ERROR SilabsTracer::OutputTrace(const TimeTracker & tracker)
183140
{
184-
if (mBufferIndex < kBufferedTracesNumber - 1)
141+
// We allow error here as we want to buffer even if the logs are currently uninitialized
142+
OutputTimeTracker(tracker);
143+
144+
if (mBufferedTrackerCount < kMaxBufferedTraces - 1)
185145
{
186-
if (error == CHIP_NO_ERROR)
187-
{
188-
snprintf(reinterpret_cast<char *>(mTraceBuffer[mBufferIndex]), kBufferedTraceSize,
189-
"Trace %zu: TotalCount=%" PRIu32 ", SuccessFullCount=%" PRIu32 ", MaxTime=%" PRIu32 ", MinTime=%" PRIu32
190-
", AvgTime=%" PRIu32 ", CountAboveAvg=%" PRIu32 "",
191-
index, tracker.mTotalCount, tracker.mSuccessfullCount, tracker.mMaxTimeMs.count(), tracker.mMinTimeMs.count(),
192-
tracker.mMovingAverage.count(), tracker.mCountAboveAvg);
193-
}
194-
else
195-
{
196-
snprintf(reinterpret_cast<char *>(mTraceBuffer[mBufferIndex]), kBufferedTraceSize,
197-
"Trace %zu: Error: %" CHIP_ERROR_FORMAT, index, error.Format());
198-
}
199-
mBufferIndex++;
146+
mTimeTrackerList.Insert(tracker);
147+
mBufferedTrackerCount++;
200148
}
201149
else
202150
{
203-
snprintf(reinterpret_cast<char *>(mTraceBuffer[mBufferIndex]), kBufferedTraceSize, "Buffer overflow: logs were lost");
151+
// Save a tracker with 0xFFFF to indicate that the buffer is full
152+
TimeTracker resourceExhaustedTracker = tracker;
153+
resourceExhaustedTracker.mStartTime = System::SystemClock().GetMonotonicTimestamp();
154+
resourceExhaustedTracker.mEndTime = resourceExhaustedTracker.mStartTime;
155+
resourceExhaustedTracker.mOperation = TimeTraceOperation::kNumTraces;
156+
resourceExhaustedTracker.mType = OperationType::kInstant;
157+
resourceExhaustedTracker.mError = CHIP_ERROR_BUFFER_TOO_SMALL;
158+
mTimeTrackerList.Insert(resourceExhaustedTracker);
159+
return CHIP_ERROR_BUFFER_TOO_SMALL;
204160
}
161+
162+
return CHIP_NO_ERROR;
205163
}
206164

207-
CHIP_ERROR SilabsTracer::OutputWaterMark(TimeTraceOperation aOperation, CHIP_ERROR error)
165+
CHIP_ERROR SilabsTracer::OutputWaterMark(TimeTraceOperation aOperation)
208166
{
209-
size_t index = static_cast<size_t>(aOperation);
210-
auto & tracker = mWatermark[index];
167+
size_t index = static_cast<size_t>(aOperation);
168+
auto & watermark = mWatermarks[index];
211169

212-
if (isLogInitialized())
213-
{
214-
if (error == CHIP_NO_ERROR)
215-
{
216-
ChipLogProgress(DeviceLayer,
217-
"Trace %zu: TotalCount=%" PRIu32 ", SuccessFullCount=%" PRIu32 ", MaxTime=%" PRIu32 ", MinTime=%" PRIu32
218-
", AvgTime=%" PRIu32 ", CountAboveAvg=%" PRIu32 "",
219-
index, tracker.mTotalCount, tracker.mSuccessfullCount, tracker.mMaxTimeMs.count(),
220-
tracker.mMinTimeMs.count(), tracker.mMovingAverage.count(), tracker.mCountAboveAvg);
221-
}
222-
else
223-
{
224-
ChipLogError(DeviceLayer, "Trace %zu: Error: %" CHIP_ERROR_FORMAT, index, error.Format());
225-
return CHIP_ERROR_INTERNAL;
226-
}
227-
}
228-
else
229-
{
230-
BufferTrace(index, tracker, error);
231-
}
170+
VerifyOrReturnError(isLogInitialized(), CHIP_ERROR_UNINITIALIZED);
171+
ChipLogProgress(DeviceLayer,
172+
"Trace %zu: TotalCount=%" PRIu32 ", SuccessFullCount=%" PRIu32 ", MaxTime=%" PRIu32 ", MinTime=%" PRIu32
173+
", AvgTime=%" PRIu32 ", CountAboveAvg=%" PRIu32 "",
174+
index, watermark.mTotalCount, watermark.mSuccessfullCount, watermark.mMaxTimeMs.count(),
175+
watermark.mMinTimeMs.count(), watermark.mMovingAverage.count(), watermark.mCountAboveAvg);
232176

233177
return CHIP_NO_ERROR;
234178
}
@@ -237,7 +181,7 @@ CHIP_ERROR SilabsTracer::OutputAllWaterMarks()
237181
{
238182
for (size_t i = 0; i < kNumTraces; ++i)
239183
{
240-
CHIP_ERROR err = OutputWaterMark(static_cast<TimeTraceOperation>(i), CHIP_NO_ERROR);
184+
CHIP_ERROR err = OutputWaterMark(static_cast<TimeTraceOperation>(i));
241185
if (err != CHIP_NO_ERROR)
242186
{
243187
return err;
@@ -246,20 +190,51 @@ CHIP_ERROR SilabsTracer::OutputAllWaterMarks()
246190
return CHIP_NO_ERROR;
247191
}
248192

249-
CHIP_ERROR SilabsTracer::TraceBufferFlush()
193+
CHIP_ERROR SilabsTracer::TraceBufferFlushAll()
250194
{
251-
if (isLogInitialized() && (nullptr != mTraceBuffer))
195+
auto * current = mTimeTrackerList.head;
196+
while (current != nullptr)
252197
{
253-
for (size_t i = 0; i < kBufferedTracesNumber; ++i)
198+
// We do not want to loose the traces if the logs are not initialized
199+
ReturnErrorOnFailure(OutputTimeTracker(current->mValue));
200+
current = current->mpNext;
201+
}
202+
203+
TraceBufferClear();
204+
return CHIP_NO_ERROR;
205+
}
206+
207+
CHIP_ERROR SilabsTracer::TraceBufferFlushByOperation(TimeTraceOperation aOperation)
208+
{
209+
210+
auto * current = mTimeTrackerList.head;
211+
auto * prev = static_cast<chip::SingleLinkedListNode<TimeTracker> *>(nullptr);
212+
while (current != nullptr)
213+
{
214+
if (current->mValue.mOperation == aOperation)
254215
{
255-
if (mTraceBuffer[i][0] != '\0') // Check if the buffer is not empty
216+
ReturnErrorOnFailure(OutputTimeTracker(current->mValue));
217+
if (prev == nullptr)
256218
{
257-
ChipLogProgress(DeviceLayer, "%s", mTraceBuffer[i]);
219+
mTimeTrackerList.head = current->mpNext;
258220
}
221+
else
222+
{
223+
prev->mpNext = current->mpNext;
224+
}
225+
auto * temp = current;
226+
current = current->mpNext;
227+
free(temp);
228+
mBufferedTrackerCount--;
229+
}
230+
else
231+
{
232+
prev = current;
233+
current = current->mpNext;
259234
}
260235
}
261236

262-
return TraceBufferClear();
237+
return CHIP_NO_ERROR;
263238
}
264239

265240
// Save the traces in the NVM
@@ -280,16 +255,19 @@ CHIP_ERROR SilabsTracer::LoadWatermarks()
280255
#if CONFIG_BUILD_FOR_HOST_UNIT_TEST
281256
CHIP_ERROR SilabsTracer::GetTraceCount(size_t & count) const
282257
{
283-
VerifyOrReturnError(nullptr != mTraceBuffer, CHIP_ERROR_INCORRECT_STATE);
284-
count = mBufferIndex;
258+
count = mBufferedTrackerCount;
285259
return CHIP_NO_ERROR;
286260
}
287261

288262
CHIP_ERROR SilabsTracer::GetTraceByIndex(size_t index, const char *& trace) const
289263
{
290-
VerifyOrReturnError(nullptr != mTraceBuffer, CHIP_ERROR_INCORRECT_STATE);
291-
VerifyOrReturnError(index < mBufferIndex, CHIP_ERROR_INVALID_ARGUMENT);
292-
trace = reinterpret_cast<const char *>(mTraceBuffer[index]);
264+
auto * current = mTimeTrackerList.head;
265+
for (size_t i = 0; i < index && current != nullptr; ++i)
266+
{
267+
current = current->mpNext;
268+
}
269+
VerifyOrReturnError(current != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
270+
trace = reinterpret_cast<const char *>(&current->mValue);
293271
return CHIP_NO_ERROR;
294272
}
295273
#endif

0 commit comments

Comments
 (0)