Skip to content

Commit 9bf974a

Browse files
[SL-ONLY] Feature/silabs tracing logs formating (#114)
1 parent a70f40e commit 9bf974a

File tree

3 files changed

+345
-66
lines changed

3 files changed

+345
-66
lines changed

src/platform/silabs/tracing/SilabsTracing.cpp

+133-28
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,78 @@ namespace chip {
3434
namespace Tracing {
3535
namespace Silabs {
3636

37-
// TODO add string mapping to log the operation names and types
37+
const char * TimeTraceOperationToString(TimeTraceOperation operation)
38+
{
39+
switch (operation)
40+
{
41+
case TimeTraceOperation::kSpake2p:
42+
return "Spake2p";
43+
case TimeTraceOperation::kPake1:
44+
return "Pake1";
45+
case TimeTraceOperation::kPake2:
46+
return "Pake2";
47+
case TimeTraceOperation::kPake3:
48+
return "Pake3";
49+
case TimeTraceOperation::kOperationalCredentials:
50+
return "OperationalCredentials";
51+
case TimeTraceOperation::kAttestationVerification:
52+
return "AttestationVerification";
53+
case TimeTraceOperation::kCSR:
54+
return "CSR";
55+
case TimeTraceOperation::kNOC:
56+
return "NOC";
57+
case TimeTraceOperation::kTransportLayer:
58+
return "TransportLayer";
59+
case TimeTraceOperation::kTransportSetup:
60+
return "TransportSetup";
61+
case TimeTraceOperation::kFindOperational:
62+
return "FindOperational";
63+
case TimeTraceOperation::kCaseSession:
64+
return "CaseSession";
65+
case TimeTraceOperation::kSigma1:
66+
return "Sigma1";
67+
case TimeTraceOperation::kSigma2:
68+
return "Sigma2";
69+
case TimeTraceOperation::kSigma3:
70+
return "Sigma3";
71+
case TimeTraceOperation::kOTA:
72+
return "OTA";
73+
case TimeTraceOperation::kImageUpload:
74+
return "ImageUpload";
75+
case TimeTraceOperation::kImageVerification:
76+
return "ImageVerification";
77+
case TimeTraceOperation::kAppApplyTime:
78+
return "AppApplyTime";
79+
case TimeTraceOperation::kBootup:
80+
return "Bootup";
81+
case TimeTraceOperation::kSilabsInit:
82+
return "SilabsInit";
83+
case TimeTraceOperation::kMatterInit:
84+
return "MatterInit";
85+
case TimeTraceOperation::kNumTraces:
86+
return "NumTraces";
87+
case TimeTraceOperation::kBufferFull:
88+
return "BufferFull";
89+
default:
90+
return "Unknown";
91+
}
92+
}
93+
94+
const char * OperationTypeToString(OperationType type)
95+
{
96+
switch (type)
97+
{
98+
case OperationType::kBegin:
99+
return "Begin";
100+
case OperationType::kEnd:
101+
return "End";
102+
case OperationType::kInstant:
103+
return "Instant";
104+
default:
105+
return "Unknown";
106+
}
107+
}
108+
38109
namespace {
39110
constexpr size_t kPersistentTimeTrackerBufferMax = SERIALIZED_TIME_TRACKERS_SIZE_BYTES;
40111
} // namespace
@@ -43,6 +114,29 @@ struct TimeTrackerStorage : public TimeTracker, PersistentData<kPersistentTimeTr
43114
// TODO implement the Persistent Array class and use it here for logging the watermark array
44115
};
45116

117+
int TimeTracker::ToCharArray(MutableByteSpan & buffer) const
118+
{
119+
switch (mType)
120+
{
121+
case OperationType::kBegin:
122+
return snprintf(reinterpret_cast<char *>(buffer.data()), buffer.size(),
123+
"TimeTracker - StartTime: %" PRIu32 ", Operation: %s, Type: %s, Error: 0x%" PRIx32, mStartTime.count(),
124+
TimeTraceOperationToString(mOperation), OperationTypeToString(mType), mError.AsInteger());
125+
case OperationType::kEnd:
126+
return snprintf(reinterpret_cast<char *>(buffer.data()), buffer.size(),
127+
"TimeTracker - StartTime: %" PRIu32 ", EndTime: %" PRIu32 ", Duration: %" PRIu32
128+
" ms, Operation: %s, Type: %s, Error: 0x%" PRIx32,
129+
mStartTime.count(), mEndTime.count(), (mEndTime - mStartTime).count(),
130+
TimeTraceOperationToString(mOperation), OperationTypeToString(mType), mError.AsInteger());
131+
case OperationType::kInstant:
132+
return snprintf(reinterpret_cast<char *>(buffer.data()), buffer.size(),
133+
"TimeTracker - EventTime: %" PRIu32 ", Operation: %s, Type: %s, Error: 0x%" PRIx32, mStartTime.count(),
134+
TimeTraceOperationToString(mOperation), OperationTypeToString(mType), mError.AsInteger());
135+
default:
136+
return snprintf(reinterpret_cast<char *>(buffer.data()), buffer.size(), "TimeTracker - Unknown operation type");
137+
}
138+
}
139+
46140
SilabsTracer SilabsTracer::sInstance;
47141

48142
SilabsTracer::SilabsTracer()
@@ -78,7 +172,7 @@ CHIP_ERROR SilabsTracer::StartWatermarksStorage(PersistentStorageDelegate * stor
78172
return CHIP_NO_ERROR;
79173
}
80174

81-
void SilabsTracer::TimeTraceBegin(TimeTraceOperation aOperation)
175+
CHIP_ERROR SilabsTracer::TimeTraceBegin(TimeTraceOperation aOperation)
82176
{
83177
// Log the start time of the operation
84178
auto & tracker = mLatestTimeTrackers[static_cast<size_t>(aOperation)];
@@ -90,10 +184,10 @@ void SilabsTracer::TimeTraceBegin(TimeTraceOperation aOperation)
90184
auto & watermark = mWatermarks[static_cast<size_t>(aOperation)];
91185
watermark.mTotalCount++;
92186

93-
OutputTrace(tracker);
187+
return OutputTrace(tracker);
94188
}
95189

96-
void SilabsTracer::TimeTraceEnd(TimeTraceOperation aOperation, CHIP_ERROR error)
190+
CHIP_ERROR SilabsTracer::TimeTraceEnd(TimeTraceOperation aOperation, CHIP_ERROR error)
97191
{
98192
auto & tracker = mLatestTimeTrackers[static_cast<size_t>(aOperation)];
99193
tracker.mEndTime = System::SystemClock().GetMonotonicTimestamp();
@@ -127,28 +221,28 @@ void SilabsTracer::TimeTraceEnd(TimeTraceOperation aOperation, CHIP_ERROR error)
127221
}
128222
}
129223

130-
OutputTrace(tracker);
224+
return OutputTrace(tracker);
131225
}
132226

133-
void SilabsTracer::TimeTraceInstant(TimeTraceOperation aOperation, CHIP_ERROR error)
227+
CHIP_ERROR SilabsTracer::TimeTraceInstant(TimeTraceOperation aOperation, CHIP_ERROR error)
134228
{
135229
TimeTracker tracker;
136230
tracker.mStartTime = System::SystemClock().GetMonotonicTimestamp();
137231
tracker.mEndTime = tracker.mStartTime;
138232
tracker.mOperation = aOperation;
139233
tracker.mType = OperationType::kInstant;
140234
tracker.mError = error;
141-
OutputTrace(tracker);
235+
return OutputTrace(tracker);
142236
}
143237

144238
CHIP_ERROR SilabsTracer::OutputTimeTracker(const TimeTracker & tracker)
145239
{
146240
VerifyOrReturnError(isLogInitialized(), CHIP_ERROR_UNINITIALIZED);
147-
ChipLogProgress(DeviceLayer,
148-
"TimeTracker - StartTime: %" PRIu32 ", EndTime: %" PRIu32 ", Operation: %" PRIu8 ", Type: %" PRIu8
149-
", Error: %" CHIP_ERROR_FORMAT,
150-
tracker.mStartTime.count(), tracker.mEndTime.count(), static_cast<uint8_t>(tracker.mOperation),
151-
static_cast<uint8_t>(tracker.mType), tracker.mError.Format());
241+
// Allocate a buffer to store the trace
242+
uint8_t buffer[kMaxTraceSize];
243+
MutableByteSpan span(buffer);
244+
tracker.ToCharArray(span);
245+
ChipLogProgress(DeviceLayer, "%s", buffer); // Use format string literal
152246
return CHIP_NO_ERROR;
153247
}
154248

@@ -168,10 +262,11 @@ CHIP_ERROR SilabsTracer::OutputTrace(const TimeTracker & tracker)
168262
TimeTracker resourceExhaustedTracker = tracker;
169263
resourceExhaustedTracker.mStartTime = System::SystemClock().GetMonotonicTimestamp();
170264
resourceExhaustedTracker.mEndTime = resourceExhaustedTracker.mStartTime;
171-
resourceExhaustedTracker.mOperation = TimeTraceOperation::kNumTraces;
265+
resourceExhaustedTracker.mOperation = TimeTraceOperation::kBufferFull;
172266
resourceExhaustedTracker.mType = OperationType::kInstant;
173267
resourceExhaustedTracker.mError = CHIP_ERROR_BUFFER_TOO_SMALL;
174268
mTimeTrackerList.Insert(resourceExhaustedTracker);
269+
mBufferedTrackerCount++;
175270
return CHIP_ERROR_BUFFER_TOO_SMALL;
176271
}
177272
else
@@ -189,10 +284,11 @@ CHIP_ERROR SilabsTracer::OutputWaterMark(TimeTraceOperation aOperation)
189284

190285
VerifyOrReturnError(isLogInitialized(), CHIP_ERROR_UNINITIALIZED);
191286
ChipLogProgress(DeviceLayer,
192-
"Trace %zu: TotalCount=%" PRIu32 ", SuccessFullCount=%" PRIu32 ", MaxTime=%" PRIu32 ", MinTime=%" PRIu32
287+
"Operation: %s, TotalCount=%" PRIu32 ", SuccessFullCount=%" PRIu32 ", MaxTime=%" PRIu32 ", MinTime=%" PRIu32
193288
", AvgTime=%" PRIu32 ", CountAboveAvg=%" PRIu32 "",
194-
index, watermark.mTotalCount, watermark.mSuccessfullCount, watermark.mMaxTimeMs.count(),
195-
watermark.mMinTimeMs.count(), watermark.mMovingAverage.count(), watermark.mCountAboveAvg);
289+
TimeTraceOperationToString(aOperation), watermark.mTotalCount, watermark.mSuccessfullCount,
290+
watermark.mMaxTimeMs.count(), watermark.mMinTimeMs.count(), watermark.mMovingAverage.count(),
291+
watermark.mCountAboveAvg);
196292

197293
return CHIP_NO_ERROR;
198294
}
@@ -272,24 +368,33 @@ CHIP_ERROR SilabsTracer::LoadWatermarks()
272368
return CHIP_NO_ERROR;
273369
}
274370

275-
#if CONFIG_BUILD_FOR_HOST_UNIT_TEST
276-
size_t SilabsTracer::GetTraceCount()
277-
{
278-
return mBufferedTrackerCount;
279-
}
280-
281-
CHIP_ERROR SilabsTracer::GetTraceByIndex(size_t index, const char *& trace) const
371+
CHIP_ERROR SilabsTracer::GetTraceByOperation(TimeTraceOperation aOperation, MutableByteSpan & buffer) const
282372
{
283373
auto * current = mTimeTrackerList.head;
284-
for (size_t i = 0; i < index && current != nullptr; ++i)
374+
while (current != nullptr)
285375
{
376+
if (current->mValue.mOperation == aOperation)
377+
{
378+
// Check if the buffer is large enough
379+
auto requiredSize = current->mValue.GetSize();
380+
381+
if (requiredSize < 0)
382+
{
383+
return CHIP_ERROR_INTERNAL;
384+
}
385+
386+
if (static_cast<size_t>(requiredSize) >= buffer.size())
387+
{
388+
return CHIP_ERROR_BUFFER_TOO_SMALL;
389+
}
390+
391+
current->mValue.ToCharArray(buffer);
392+
return CHIP_NO_ERROR;
393+
}
286394
current = current->mpNext;
287395
}
288-
VerifyOrReturnError(current != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
289-
trace = reinterpret_cast<const char *>(&current->mValue);
290-
return CHIP_NO_ERROR;
396+
return CHIP_ERROR_NOT_FOUND;
291397
}
292-
#endif
293398

294399
} // namespace Silabs
295400
} // namespace Tracing

src/platform/silabs/tracing/SilabsTracing.h

+39-26
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <lib/core/CHIPError.h>
2222
#include <lib/core/CHIPPersistentStorageDelegate.h>
2323
#include <lib/support/LinkedList.h>
24+
#include <lib/support/Span.h>
2425
#include <stdint.h>
2526
#include <system/SystemClock.h>
2627

@@ -60,6 +61,7 @@ enum class TimeTraceOperation : uint8_t
6061
kBootup,
6162
kSilabsInit,
6263
kMatterInit,
64+
kBufferFull,
6365
kNumTraces,
6466
};
6567

@@ -78,6 +80,23 @@ struct TimeTracker
7880
TimeTraceOperation mOperation;
7981
OperationType mType;
8082
CHIP_ERROR mError;
83+
84+
/** @brief Convert the TimeTracker to a string for logs
85+
* Behaves like snprintf, but formats the output differently based on the OperationType
86+
* May be used with a buffer of size == 0 to get the required buffer size
87+
* @param buffer The buffer to write the string to
88+
* @return The number of characters written to the buffer, or the size of the buffer required if the buffer is too small
89+
*/
90+
int ToCharArray(MutableByteSpan & buffer) const;
91+
92+
/** @brief Get the size of the string representation of the TimeTracker
93+
* @return The size of the string representation of the TimeTracker
94+
*/
95+
int GetSize() const
96+
{
97+
MutableByteSpan temp;
98+
return ToCharArray(temp);
99+
}
81100
};
82101

83102
struct Watermark
@@ -95,10 +114,11 @@ struct Watermark
95114
//
96115
class SilabsTracer
97116
{
117+
public:
98118
static constexpr size_t kNumTraces = to_underlying(TimeTraceOperation::kNumTraces);
99119
static constexpr size_t kMaxBufferedTraces = 64;
120+
static constexpr size_t kMaxTraceSize = 256;
100121

101-
public:
102122
/** @brief Get the singleton instance of SilabsTracer */
103123
static SilabsTracer & Instance() { return sInstance; }
104124

@@ -119,24 +139,27 @@ class SilabsTracer
119139
* This calls the OutputTrace method to log the trace if logs are enabled, and stores the time tracker in the buffer if the
120140
* buffer is not full.
121141
* @param aOperation
142+
* @return CHIP_ERROR, returns CHIP_ERROR_BUFFER_TOO_SMALL if the buffer is full
122143
*/
123-
void TimeTraceBegin(TimeTraceOperation aOperation);
144+
CHIP_ERROR TimeTraceBegin(TimeTraceOperation aOperation);
124145

125146
/** @brief End tracing a time operation
126147
* This calls the OutputTrace method to log the trace if logs are enabled, and stores the time tracker in the buffer if the
127148
* buffer is not full.
128149
* @param aOperation
129150
* @param error
151+
* @return CHIP_ERROR, returns CHIP_ERROR_BUFFER_TOO_SMALL if the buffer is full
130152
*/
131-
void TimeTraceEnd(TimeTraceOperation aOperation, CHIP_ERROR error = CHIP_NO_ERROR);
153+
CHIP_ERROR TimeTraceEnd(TimeTraceOperation aOperation, CHIP_ERROR error = CHIP_NO_ERROR);
132154

133155
/** @brief Trace an instant time operation
134156
* This calls the OutputTrace method to log the trace if logs are enabled, and stores the time tracker in the buffer if the
135157
* buffer is not full.
136158
* @param aOperation
137159
* @param error
160+
* @return CHIP_ERROR, returns CHIP_ERROR_BUFFER_TOO_SMALL if the buffer is full
138161
*/
139-
void TimeTraceInstant(TimeTraceOperation aOperation, CHIP_ERROR error = CHIP_NO_ERROR);
162+
CHIP_ERROR TimeTraceInstant(TimeTraceOperation aOperation, CHIP_ERROR error = CHIP_NO_ERROR);
140163

141164
/** @brief Output a time tracker
142165
* This will output the latest time tracker for a specific operation, without affecting the buffer.
@@ -175,18 +198,6 @@ class SilabsTracer
175198
SilabsTracer(SilabsTracer const &) = delete;
176199
SilabsTracer & operator=(SilabsTracer const &) = delete;
177200

178-
/** @brief Get the latest time tracker for a specific operation
179-
* @param aOperation The operation to get the time tracker for
180-
* @return TimeTracker, the latest time tracker for the operation
181-
*/
182-
TimeTracker GetTimeTracker(TimeTraceOperation aOperation) { return mLatestTimeTrackers[to_underlying(aOperation)]; }
183-
184-
/** @brief Get the watermark for a specific operation
185-
* @param aOperation The operation to get the watermark for
186-
* @return Watermark, the watermark for the operation
187-
*/
188-
Watermark GetWatermark(TimeTraceOperation aOperation) { return mWatermarks[to_underlying(aOperation)]; }
189-
190201
/** @brief Save the watermarks to persistent storage
191202
* @return CHIP_ERROR, returns an error if the storage is not initialized
192203
*/
@@ -197,19 +208,21 @@ class SilabsTracer
197208
*/
198209
CHIP_ERROR LoadWatermarks();
199210

200-
#if CONFIG_BUILD_FOR_HOST_UNIT_TEST
201-
/** @brief Get the count of buffered traces
202-
* @param count Reference to store the count of buffered traces
211+
// Methods to get the time trackers metrics values
212+
213+
/** @brief Get the latest time tracker for a specific operation
214+
* @param aOperation The operation to get the time tracker for
215+
* @return TimeTracker, the latest time tracker for the operation
203216
*/
204-
size_t GetTraceCount();
217+
TimeTracker GetTimeTracker(TimeTraceOperation aOperation) { return mLatestTimeTrackers[to_underlying(aOperation)]; }
205218

206-
/** @brief Get a trace by its index
207-
* @param index The index of the trace to retrieve
208-
* @param trace Reference to store the trace
209-
* @return CHIP_ERROR, returns CHIP_ERROR_INVALID_ARGUMENT if the index is invalid
219+
/** @brief Get the watermark for a specific operation
220+
* @param aOperation The operation to get the watermark for
221+
* @return Watermark, the watermark for the operation
210222
*/
211-
CHIP_ERROR GetTraceByIndex(size_t index, const char *& trace) const;
212-
#endif
223+
Watermark GetWatermark(TimeTraceOperation aOperation) { return mWatermarks[to_underlying(aOperation)]; }
224+
size_t GetTimeTracesCount() { return mBufferedTrackerCount; }
225+
CHIP_ERROR GetTraceByOperation(TimeTraceOperation aOperation, MutableByteSpan & buffer) const;
213226

214227
private:
215228
struct TimeTrackerList

0 commit comments

Comments
 (0)