4
4
#include < lib/support/PersistentData.h>
5
5
6
6
#if !CONFIG_BUILD_FOR_HOST_UNIT_TEST
7
- #include < silabs_utils .h> // for isLogInitialized
7
+ #include < Logging .h> // for isLogInitialized
8
8
#endif
9
9
10
10
// The following functions needs to be implemented by the application to allows logging or storing the traces /
@@ -18,6 +18,8 @@ namespace chip {
18
18
namespace Tracing {
19
19
namespace Silabs {
20
20
21
+ // TODO add string mapping to log the operation names and types
22
+
21
23
static constexpr size_t kPersistentTimeTrackerBufferMax = SERIALIZED_TIME_TRACKERS_SIZE_BYTES;
22
24
23
25
struct TimeTrackerStorage : public TimeTracker , PersistentData<kPersistentTimeTrackerBufferMax >
@@ -29,14 +31,50 @@ SilabsTracer SilabsTracer::sInstance;
29
31
30
32
SilabsTracer::SilabsTracer ()
31
33
{
32
- Init ();
34
+ VerifyOrDie ( Init () == CHIP_NO_ERROR );
33
35
}
34
36
35
- void SilabsTracer::Init ()
37
+ CHIP_ERROR SilabsTracer::TraceBufferClear ()
36
38
{
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
39
70
memset (mWatermark , 0 , sizeof (mWatermark ));
71
+
72
+ return CHIP_NO_ERROR;
73
+ }
74
+
75
+ CHIP_ERROR SilabsTracer::StartLogging ()
76
+ {
77
+ return TraceBufferFlush ();
40
78
}
41
79
42
80
CHIP_ERROR SilabsTracer::StartTraceStorage (PersistentStorageDelegate * storage)
@@ -52,96 +90,175 @@ void SilabsTracer::TimeTraceBegin(TimeTraceOperation aOperation)
52
90
auto & tracker = mWatermark [static_cast <size_t >(aOperation)];
53
91
tracker.mTotalCount ++;
54
92
tracker.mStartTime = System::SystemClock ().GetMonotonicTimestamp ();
93
+ OutputTrace (aOperation, OperationType::kBegin , CHIP_NO_ERROR);
55
94
}
56
95
57
96
void SilabsTracer::TimeTraceEnd (TimeTraceOperation aOperation, CHIP_ERROR error)
58
97
{
59
98
if (error != CHIP_NO_ERROR)
60
99
{
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);
64
101
return ;
65
102
}
66
103
67
104
// Calculate the duration and update the time tracker
68
105
auto & tracker = mWatermark [static_cast <size_t >(aOperation)];
69
106
tracker.mEndTime = System::SystemClock ().GetMonotonicTimestamp ();
70
- auto duration = ( tracker.mEndTime - tracker.mStartTime ). count () ;
107
+ auto duration = tracker.mEndTime - tracker.mStartTime ;
71
108
72
109
tracker.mTotalDuration += System::Clock::Milliseconds64 (duration);
73
110
74
- if (duration > tracker.mMaxTimeMs . count () )
111
+ if (duration > tracker.mMaxTimeMs )
75
112
{
76
113
tracker.mMaxTimeMs = System::Clock::Milliseconds32 (duration);
77
114
}
78
115
79
- if (tracker.mMinTimeMs .count () == 0 || duration < tracker.mMinTimeMs . count () )
116
+ if (tracker.mMinTimeMs .count () == 0 || duration < tracker.mMinTimeMs )
80
117
{
81
118
tracker.mMinTimeMs = System::Clock::Milliseconds32 (duration);
82
119
}
83
120
84
121
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 )
87
124
{
88
125
tracker.mCountAboveAvg ++;
89
126
}
127
+
128
+ OutputTrace (aOperation, OperationType::kEnd , CHIP_NO_ERROR);
90
129
}
91
130
92
131
void SilabsTracer::TimeTraceInstant (TimeTraceOperation aOperation, CHIP_ERROR error)
93
132
{
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 )
95
184
{
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 ++;
100
199
}
101
200
else
102
201
{
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" );
106
203
}
107
204
}
108
205
109
- void SilabsTracer::OutputTraces ( )
206
+ CHIP_ERROR SilabsTracer::OutputWaterMark (TimeTraceOperation aOperation, CHIP_ERROR error )
110
207
{
208
+ size_t index = static_cast <size_t >(aOperation);
209
+ auto & tracker = mWatermark [index ];
210
+
111
211
if (isLogInitialized ())
112
212
{
113
- // Output the traces from the buffer
114
- for (size_t i = 0 ; i < kNumTraces ; ++i)
213
+ if (error == CHIP_NO_ERROR)
115
214
{
116
- auto & tracker = mWatermark [i];
117
215
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 (),
120
219
tracker.mMinTimeMs .count (), tracker.mMovingAverage .count (), tracker.mCountAboveAvg );
121
220
}
221
+ else
222
+ {
223
+ ChipLogError (DeviceLayer, " Trace %zu: Error: %" CHIP_ERROR_FORMAT, index , error.Format ());
224
+ return CHIP_ERROR_INTERNAL;
225
+ }
122
226
}
123
227
else
124
228
{
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)
128
241
{
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;
139
243
}
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)
141
253
{
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
+ }
143
258
}
144
259
}
260
+
261
+ return TraceBufferClear ();
145
262
}
146
263
147
264
// Save the traces in the NVM
@@ -159,6 +276,23 @@ CHIP_ERROR SilabsTracer::LoadWatermarks()
159
276
return CHIP_NO_ERROR;
160
277
}
161
278
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
+
162
296
} // namespace Silabs
163
297
} // namespace Tracing
164
298
} // namespace chip
0 commit comments