-
Notifications
You must be signed in to change notification settings - Fork 2.1k
/
Copy pathEventManagement.h
576 lines (520 loc) · 25.3 KB
/
EventManagement.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
/*
*
* Copyright (c) 2021 Project CHIP Authors
* Copyright (c) 2015-2017 Nest Labs, Inc.
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file
*
* @brief
* Management of the CHIP Event Logging.
*
*/
#pragma once
#include "EventLoggingDelegate.h"
#include <access/SubjectDescriptor.h>
#include <app/EventLoggingTypes.h>
#include <app/EventReporter.h>
#include <app/MessageDef/EventDataIB.h>
#include <app/MessageDef/StatusIB.h>
#include <app/data-model-provider/EventsGenerator.h>
#include <app/util/basic-types.h>
#include <lib/core/TLVCircularBuffer.h>
#include <lib/support/CHIPCounter.h>
#include <lib/support/LinkedList.h>
#include <messaging/ExchangeMgr.h>
#include <platform/CHIPDeviceConfig.h>
#include <system/SystemClock.h>
/**
* Events are stored in the LogStorageResources provided to
* EventManagement::Init.
*
* A newly generated event will be placed in the lowest-priority (in practice
* DEBUG) buffer, the one associated with the first LogStorageResource. If
* there is no space in that buffer, space will be created by evicting the
* oldest event currently in that buffer, until enough space is available.
*
* When an event is evicted from a buffer, there are two possibilities:
*
* 1) If the next LogStorageResource has a priority that is no higher than the
* event's priority, the event will be moved to that LogStorageResource's
* buffer. This may in turn require events to be evicted from that buffer.
* 2) If the next LogStorageResource has a priority that is higher than the
* event's priority, then the event is just dropped.
*
* This means that LogStorageResources at a given priority level are reserved
* for events of that priority level or higher priority.
*
* As a simple example, assume there are only two priority levels, DEBUG and
* CRITICAL, and two LogStorageResources with those priorities. In that case,
* old CRITICAL events will not start getting dropped until both buffers are
* full, while old DEBUG events will start getting dropped once the DEBUG
* LogStorageResource buffer is full.
*/
#define CHIP_CONFIG_EVENT_GLOBAL_PRIORITY PriorityLevel::Debug
namespace chip {
namespace app {
inline constexpr const uint32_t kEventManagementProfile = 0x1;
inline constexpr const uint32_t kFabricIndexTag = 0x1;
inline constexpr size_t kMaxEventSizeReserve = 512;
constexpr uint16_t kRequiredEventField =
(1 << to_underlying(EventDataIB::Tag::kPriority)) | (1 << to_underlying(EventDataIB::Tag::kPath));
/**
* @brief
* Internal event buffer, built around the TLV::TLVCircularBuffer
*/
class CircularEventBuffer : public TLV::TLVCircularBuffer
{
public:
/**
* @brief
* A constructor for the CircularEventBuffer (internal API).
*/
CircularEventBuffer() : TLVCircularBuffer(nullptr, 0){};
/**
* @brief
* A Init for the CircularEventBuffer (internal API).
*
* @param[in] apBuffer The actual storage to use for event storage.
*
* @param[in] aBufferLength The length of the \c apBuffer in bytes.
*
* @param[in] apPrev The pointer to CircularEventBuffer storing
* events of lesser priority.
*
* @param[in] apNext The pointer to CircularEventBuffer storing
* events of greater priority.
*
* @param[in] aPriorityLevel CircularEventBuffer priority level
*/
void Init(uint8_t * apBuffer, uint32_t aBufferLength, CircularEventBuffer * apPrev, CircularEventBuffer * apNext,
PriorityLevel aPriorityLevel);
/**
* @brief
* A helper function that determines whether the event of
* specified priority is final destination
*
* @param[in] aPriority Priority of the event.
*
* @retval true/false event's priority is same as current buffer's priority, otherwise, false
*/
bool IsFinalDestinationForPriority(PriorityLevel aPriority) const;
PriorityLevel GetPriority() { return mPriority; }
CircularEventBuffer * GetPreviousCircularEventBuffer() { return mpPrev; }
CircularEventBuffer * GetNextCircularEventBuffer() { return mpNext; }
void SetRequiredSpaceforEvicted(size_t aRequiredSpace) { mRequiredSpaceForEvicted = aRequiredSpace; }
size_t GetRequiredSpaceforEvicted() const { return mRequiredSpaceForEvicted; }
~CircularEventBuffer() override = default;
private:
CircularEventBuffer * mpPrev = nullptr; ///< A pointer CircularEventBuffer storing events less important events
CircularEventBuffer * mpNext = nullptr; ///< A pointer CircularEventBuffer storing events more important events
PriorityLevel mPriority = PriorityLevel::Invalid; ///< The buffer is the final bucket for events of this priority. Events of
///< lesser priority are dropped when they get bumped out of this buffer
size_t mRequiredSpaceForEvicted = 0; ///< Required space for previous buffer to evict event to new buffer
CHIP_ERROR OnInit(TLV::TLVWriter & writer, uint8_t *& bufStart, uint32_t & bufLen) override;
};
class CircularEventReader;
/**
* @brief
* A CircularEventBufferWrapper which has a pointer to the "current CircularEventBuffer". When trying to locate next buffer,
* if nothing left there update its CircularEventBuffer until the buffer with data has been found,
* the tlv reader will have a pointer to this impl.
*/
class CircularEventBufferWrapper : public TLV::TLVCircularBuffer
{
public:
CircularEventBufferWrapper() : TLVCircularBuffer(nullptr, 0), mpCurrent(nullptr){};
CircularEventBuffer * mpCurrent;
private:
CHIP_ERROR GetNextBuffer(chip::TLV::TLVReader & aReader, const uint8_t *& aBufStart, uint32_t & aBufLen) override;
};
enum class EventManagementStates
{
Idle = 1, // No log offload in progress, log offload can begin without any constraints
InProgress = 2, // Log offload in progress
Shutdown = 3 // Not capable of performing any logging operation
};
/**
* @brief
* A helper class used in initializing logging management.
*
* The class is used to encapsulate the resources allocated by the caller and denotes
* resources to be used in logging events of a particular priority. Note that
* while resources referring to the counters are used exclusively by the
* particular priority level, the buffers are shared between `this` priority
* level and events that are "more" important.
*/
struct LogStorageResources
{
// TODO: Update TLVCircularBuffer with size_t for buffer size, then use ByteSpan
uint8_t * mpBuffer =
nullptr; // Buffer to be used as a storage at the particular priority level and shared with more important events.
// Must not be nullptr. Must be large enough to accommodate the largest event emitted by the system.
uint32_t mBufferSize = 0; ///< The size, in bytes, of the `mBuffer`.
PriorityLevel mPriority =
PriorityLevel::Invalid; // Log priority level associated with the resources provided in this structure.
};
/**
* @brief
* A class for managing the in memory event logs. See documentation at the
* top of the file describing the eviction policy for events when there is no
* more space for new events.
*/
class EventManagement : public DataModel::EventsGenerator
{
public:
/**
* Initialize the EventManagement with an array of LogStorageResources and
* an equal-length array of CircularEventBuffers that correspond to those
* LogStorageResources. The array of LogStorageResources must provide a
* resource for each valid priority level, the elements of the array must be
* in increasing numerical value of priority (and in increasing priority);
* the first element in the array corresponds to the resources allocated for
* least important events, and the last element corresponds to the most
* critical events.
*
* @param[in] apExchangeManager ExchangeManager to be used with this logging subsystem
*
* @param[in] aNumBuffers Number of elements in the apLogStorageResources
* and apCircularEventBuffer arrays.
*
* @param[in] apCircularEventBuffer An array of CircularEventBuffer for each priority level.
*
* @param[in] apLogStorageResources An array of LogStorageResources for each priority level.
*
* @param[in] apEventNumberCounter A counter to use for event numbers.
*
* @param[in] aMonotonicStartupTime Time we should consider as "monotonic
* time 0" for cases when we use
* system-time event timestamps.
*
* @param[in] apEventReporter Event reporter to be notified when events are generated.
*
* @return CHIP_ERROR CHIP Error Code
*
*/
CHIP_ERROR Init(Messaging::ExchangeManager * apExchangeManager, uint32_t aNumBuffers,
CircularEventBuffer * apCircularEventBuffer, const LogStorageResources * const apLogStorageResources,
MonotonicallyIncreasingCounter<EventNumber> * apEventNumberCounter,
System::Clock::Milliseconds64 aMonotonicStartupTime, EventReporter * apEventReporter);
static EventManagement & GetInstance();
/**
* @brief Create EventManagement object and initialize the logging management
* subsystem with provided resources.
*
* Initialize the EventManagement with an array of LogStorageResources. The
* array must provide a resource for each valid priority level, the elements
* of the array must be in increasing numerical value of priority (and in
* decreasing priority); the first element in the array corresponds to the
* resources allocated for the most critical events, and the last element
* corresponds to the least important events.
*
* @param[in] apExchangeManager ExchangeManager to be used with this logging subsystem
*
* @param[in] aNumBuffers Number of elements in inLogStorageResources array
*
* @param[in] apCircularEventBuffer An array of CircularEventBuffer for each priority level.
* @param[in] apLogStorageResources An array of LogStorageResources for each priority level.
*
* @param[in] apEventNumberCounter A counter to use for event numbers.
*
* @param[in] aMonotonicStartupTime Time we should consider as "monotonic
* time 0" for cases when we use
* system-time event timestamps.
*
* @note This function must be called prior to the logging being used.
*/
static void
CreateEventManagement(Messaging::ExchangeManager * apExchangeManager, uint32_t aNumBuffers,
CircularEventBuffer * apCircularEventBuffer, const LogStorageResources * const apLogStorageResources,
MonotonicallyIncreasingCounter<EventNumber> * apEventNumberCounter,
System::Clock::Milliseconds64 aMonotonicStartupTime = System::SystemClock().GetMonotonicMilliseconds64());
static void DestroyEventManagement();
/**
* @brief
* Log an event via a EventLoggingDelegate, with options.
*
* The EventLoggingDelegate writes the event metadata and calls the `apDelegate`
* with an TLV::TLVWriter reference so that the user code can emit
* the event data directly into the event log. This form of event
* logging minimizes memory consumption, as event data is serialized
* directly into the target buffer. The event data MUST contain
* context tags to be interpreted within the schema identified by
* `ClusterID` and `EventId`. The tag of the first element will be
* ignored; the event logging system will replace it with the
* eventData tag.
*
* The event is logged if the schema priority exceeds the logging
* threshold specified in the LoggingConfiguration. If the event's
* priority does not meet the current threshold, it is dropped and
* the function returns a `0` as the resulting event ID.
*
* This variant of the invocation permits the caller to set any
* combination of `EventOptions`:
* - timestamp, when 0 defaults to the current time at the point of
* the call,
* - "root" section of the event source (event source and cluster ID);
* if NULL, it defaults to the current device. the event is marked as
* relating to the device that is making the call,
*
* @param[in] apDelegate The EventLoggingDelegate to serialize the event data
*
* @param[in] aEventOptions The options for the event metadata.
*
* @param[out] aEventNumber The event Number if the event was written to the
* log, 0 otherwise.
*
* @return CHIP_ERROR CHIP Error Code
*/
CHIP_ERROR LogEvent(EventLoggingDelegate * apDelegate, const EventOptions & aEventOptions, EventNumber & aEventNumber);
/**
* @brief
* A helper method to get tlv reader along with buffer has data from particular priority
*
* @param[in,out] aReader A reference to the reader that will be
* initialized with the backing storage from
* the event log
*
* @param[in] aPriority The starting priority for the reader.
* Note that in this case the starting
* priority is somewhat counter intuitive:
* more important events share the buffers
* with less priority events, in addition to
* their dedicated buffers. As a result, the
* reader will traverse the least data when
* the Debug priority is passed in.
*
* @param[in] apBufWrapper CircularEventBufferWrapper
* @return #CHIP_NO_ERROR Unconditionally.
*/
CHIP_ERROR GetEventReader(chip::TLV::TLVReader & aReader, PriorityLevel aPriority,
app::CircularEventBufferWrapper * apBufWrapper);
/**
* @brief
* A function to retrieve events of specified priority since a specified event ID.
*
* Given a TLV::TLVWriter, an priority type, and an event ID, the
* function will fetch events since the
* specified event number. The function will continue fetching events until
* it runs out of space in the TLV::TLVWriter or in the log. The function
* will terminate the event writing on event boundary. The function would filter out event based upon interested path
* specified by read/subscribe request.
*
* @param[in] aWriter The writer to use for event storage
* @param[in] apEventPathList the interested EventPathParams list
*
* @param[in,out] aEventMin On input, the Event number is the one we're fetching. On
* completion, the event number of the next one we plan to fetch.
*
* @param[out] aEventCount The number of fetched event
* @param[in] aSubjectDescriptor Subject descriptor for current read handler
* @retval #CHIP_END_OF_TLV The function has reached the end of the
* available log entries at the specified
* priority level
*
* @retval #CHIP_ERROR_NO_MEMORY The function ran out of space in the
* aWriter, more events in the log are
* available.
*
* @retval #CHIP_ERROR_BUFFER_TOO_SMALL The function ran out of space in the
* aWriter, more events in the log are
* available.
*
*/
CHIP_ERROR FetchEventsSince(chip::TLV::TLVWriter & aWriter, const SingleLinkedListNode<EventPathParams> * apEventPathList,
EventNumber & aEventMin, size_t & aEventCount,
const Access::SubjectDescriptor & aSubjectDescriptor);
/**
* @brief brief Iterate all events and invalidate the fabric-sensitive events whose associated fabric has the given fabric
* index.
*/
CHIP_ERROR FabricRemoved(FabricIndex aFabricIndex);
/**
* @brief
* Fetch the most recently vended Number for a particular priority level
*
* @return EventNumber most recently vended event Number for that event priority
*/
EventNumber GetLastEventNumber() const { return mLastEventNumber; }
/**
* @brief
* IsValid returns whether the EventManagement instance is valid
*/
bool IsValid(void) { return EventManagementStates::Shutdown != mState; };
/**
* Logger would save last logged event number and initial written event bytes number into schedule event number array
*/
void SetScheduledEventInfo(EventNumber & aEventNumber, uint32_t & aInitialWrittenEventBytes) const;
/* EventsGenerator implementation */
CHIP_ERROR GenerateEvent(EventLoggingDelegate * eventPayloadWriter, const EventOptions & options,
EventNumber & generatedEventNumber) override;
private:
/**
* @brief
* Internal structure for traversing events.
*/
struct EventEnvelopeContext
{
EventEnvelopeContext() {}
int mFieldsToRead = 0;
/* PriorityLevel and DeltaTime are there if that is not first event when putting events in report*/
#if CHIP_DEVICE_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS
Timestamp mCurrentTime = Timestamp::Epoch(System::Clock::kZero);
#else // CHIP_DEVICE_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS
Timestamp mCurrentTime = Timestamp::System(System::Clock::kZero);
#endif // CHIP_DEVICE_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS
PriorityLevel mPriority = PriorityLevel::First;
ClusterId mClusterId = 0;
EndpointId mEndpointId = 0;
EventId mEventId = 0;
EventNumber mEventNumber = 0;
Optional<FabricIndex> mFabricIndex;
};
void VendEventNumber();
CHIP_ERROR CalculateEventSize(EventLoggingDelegate * apDelegate, const EventOptions * apOptions, uint32_t & requiredSize);
/**
* @brief Helper function for writing event header and data according to event
* logging protocol.
*
* @param[in,out] apContext EventLoadOutContext, initialized with stateful
* information for the buffer. State is updated
* and preserved by ConstructEvent using this context.
*
* @param[in] apDelegate The EventLoggingDelegate to serialize the event data
*
* @param[in] apOptions EventOptions describing timestamp and other tags
* relevant to this event.
*
*/
CHIP_ERROR ConstructEvent(EventLoadOutContext * apContext, EventLoggingDelegate * apDelegate, const EventOptions * apOptions);
// Internal function to log event
CHIP_ERROR LogEventPrivate(EventLoggingDelegate * apDelegate, const EventOptions & aEventOptions, EventNumber & aEventNumber);
/**
* @brief copy the event outright to next buffer with higher priority
*
* @param[in] apEventBuffer CircularEventBuffer
*
*/
CHIP_ERROR CopyToNextBuffer(CircularEventBuffer * apEventBuffer);
/**
* @brief Ensure that:
*
* 1) There could be aRequiredSpace bytes available (if enough things were
* evicted) in all buffers that can hold events with priority aPriority.
*
* 2) There are in fact aRequiredSpace bytes available in our
* lowest-priority buffer. This might involve evicting some events to
* higher-priority buffers or dropping them.
*
* @param[in] aRequiredSpace required space
* @param[in] aPriority priority of the event we are making space for.
*
*/
CHIP_ERROR EnsureSpaceInCircularBuffer(size_t aRequiredSpace, PriorityLevel aPriority);
/**
* @brief Iterate the event elements inside event tlv and mark the fabric index as kUndefinedFabricIndex if
* it matches the FabricIndex apFabricIndex points to.
*
* @param[in] aReader event tlv reader
* @param[in] apFabricIndex A FabricIndex* pointing to the fabric index for which we want to effectively evict events.
*
*/
static CHIP_ERROR FabricRemovedCB(const TLV::TLVReader & aReader, size_t, void * apFabricIndex);
/**
* @brief
* Internal API used to implement #FetchEventsSince
*
* Iterator function to used to copy an event from the log into a
* TLVWriter. The included apContext contains the context of the copy
* operation, including the TLVWriter that will hold the copy of an
* event. If event cannot be written as a whole, the TLVWriter will
* be rolled back to event boundary.
*
* @retval #CHIP_END_OF_TLV Function reached the end of the event
* @retval #CHIP_ERROR_NO_MEMORY Function could not write a portion of
* the event to the TLVWriter.
* @retval #CHIP_ERROR_BUFFER_TOO_SMALL Function could not write a
* portion of the event to the TLVWriter.
*/
static CHIP_ERROR CopyEventsSince(const TLV::TLVReader & aReader, size_t aDepth, void * apContext);
/**
* @brief Internal iterator function used to scan and filter though event logs
*
* The function is used to scan through the event log to find events matching the spec in the supplied context.
* Particularly, it would check against mStartingEventNumber, and skip fetched event.
*/
static CHIP_ERROR EventIterator(const TLV::TLVReader & aReader, size_t aDepth, EventLoadOutContext * apEventLoadOutContext,
EventEnvelopeContext * event);
/**
* @brief Internal iterator function used to fetch event into EventEnvelopeContext, then EventIterator would filter event
* based upon EventEnvelopeContext
*
*/
static CHIP_ERROR FetchEventParameters(const TLV::TLVReader & aReader, size_t aDepth, void * apContext);
/**
* @brief Internal iterator function used to scan and filter though event logs
* First event gets a timestamp, subsequent ones get a delta T
* First event in the sequence gets a event number neatly packaged
*/
static CHIP_ERROR CopyAndAdjustDeltaTime(const TLV::TLVReader & aReader, size_t aDepth, void * apContext);
/**
* @brief checking if the tail's event can be moved to higher priority, if not, dropped, if yes, note how much space it
* requires, and return.
*/
static CHIP_ERROR EvictEvent(chip::TLV::TLVCircularBuffer & aBuffer, void * apAppData, TLV::TLVReader & aReader);
static CHIP_ERROR AlwaysFail(chip::TLV::TLVCircularBuffer & aBuffer, void * apAppData, TLV::TLVReader & aReader)
{
return CHIP_ERROR_NO_MEMORY;
};
/**
* @brief Check whether the event instance represented by the EventEnvelopeContext should be included in the report.
*
* @retval CHIP_ERROR_UNEXPECTED_EVENT This path should be excluded in the generated event report.
* @retval CHIP_EVENT_ID_FOUND This path should be included in the generated event report.
* @retval CHIP_ERROR_ACCESS_DENIED This path should be included in the generated event report, but the client does not have
* . enough privilege to access it.
*
* TODO: Consider using CHIP_NO_ERROR, CHIP_ERROR_SKIP_EVENT, CHIP_ERROR_ACCESS_DENINED or some enum to represent the checking
* result.
*/
static CHIP_ERROR CheckEventContext(EventLoadOutContext * eventLoadOutContext, const EventEnvelopeContext & event);
/**
* @brief copy event from circular buffer to target buffer for report
*/
static CHIP_ERROR CopyEvent(const TLV::TLVReader & aReader, TLV::TLVWriter & aWriter, EventLoadOutContext * apContext);
/**
* @brief
* A function to get the circular buffer for particular priority
*
* @param aPriority PriorityLevel
*
* @return A pointer for the CircularEventBuffer
*/
CircularEventBuffer * GetPriorityBuffer(PriorityLevel aPriority) const;
// EventBuffer for debug level,
CircularEventBuffer * mpEventBuffer = nullptr;
Messaging::ExchangeManager * mpExchangeMgr = nullptr;
EventManagementStates mState = EventManagementStates::Shutdown;
uint32_t mBytesWritten = 0;
// The counter we're going to use for event numbers.
MonotonicallyIncreasingCounter<EventNumber> * mpEventNumberCounter = nullptr;
EventNumber mLastEventNumber = 0; ///< Last event Number vended
Timestamp mLastEventTimestamp; ///< The timestamp of the last event in this buffer
System::Clock::Milliseconds64 mMonotonicStartupTime;
EventReporter * mpEventReporter = nullptr;
};
} // namespace app
} // namespace chip