blob: 167cf6d2bf4d4028b27768d8f9d37e861279700e [file] [log] [blame]
yunhanw-google6f89b9b2021-12-07 14:26:21 -08001/*
2 *
3 * Copyright (c) 2021 Project CHIP Authors
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#include <app/ConcreteEventPath.h>
22#include <app/EventLoggingDelegate.h>
23#include <app/EventManagement.h>
24#include <app/data-model/Encode.h>
yunhanw-googlee4508322022-01-26 18:27:51 -080025#include <app/data-model/FabricScoped.h>
yunhanw-google6f89b9b2021-12-07 14:26:21 -080026#include <app/data-model/List.h> // So we can encode lists
27
28namespace chip {
29namespace app {
30
31template <typename T>
32class EventLogger : public EventLoggingDelegate
33{
34public:
35 EventLogger(const T & aEventData) : mEventData(aEventData){};
36 CHIP_ERROR WriteEvent(chip::TLV::TLVWriter & aWriter) final override
37 {
Boris Zbarskye434c6a2023-03-01 12:35:37 -050038 return DataModel::Encode(aWriter, TLV::ContextTag(EventDataIB::Tag::kData), mEventData);
yunhanw-google6f89b9b2021-12-07 14:26:21 -080039 }
40
41private:
42 const T & mEventData;
43};
44
45/**
46 * @brief
47 * Log an event via a EventLoggingDelegate, with options.
48 *
49 * The EventLoggingDelegate writes the event metadata and calls the `apDelegate`
50 * with an TLV::TLVWriter reference so that the user code can emit
51 * the event data directly into the event log. This form of event
52 * logging minimizes memory consumption, as event data is serialized
53 * directly into the target buffer. The event data MUST contain
54 * context tags to be interpreted within the schema identified by
55 * `ClusterID` and `EventId`.
56 *
yunhanw-google783c3e02024-01-29 23:24:48 -080057 * The consumer has to either lock the Matter stack lock or queue the event to
58 * the Matter event queue when using LogEvent. This function is not safe to call
59 * outside of the main Matter processing context.
60 *
yunhanw-googlee4508322022-01-26 18:27:51 -080061 * LogEvent has 2 variant, one for fabric-scoped events and one for non-fabric-scoped events.
62 * @param[in] aEventData The event cluster object
yunhanw-google86823aa2021-12-08 06:35:52 -080063 * @param[in] aEndpoint The current cluster's Endpoint Id
yunhanw-google6f89b9b2021-12-07 14:26:21 -080064 * @param[out] aEventNumber The event Number if the event was written to the
65 * log, 0 otherwise. The Event number is expected to monotonically increase.
66 *
67 * @return CHIP_ERROR CHIP Error Code
68 */
Boris Zbarsky359fd432022-01-30 09:21:12 -050069template <typename T, std::enable_if_t<DataModel::IsFabricScoped<T>::value, bool> = true>
yunhanw-googlecd44f9b2022-03-09 10:36:31 -080070CHIP_ERROR LogEvent(const T & aEventData, EndpointId aEndpoint, EventNumber & aEventNumber)
yunhanw-googlee4508322022-01-26 18:27:51 -080071{
72 EventLogger<T> eventData(aEventData);
73 ConcreteEventPath path(aEndpoint, aEventData.GetClusterId(), aEventData.GetEventId());
74 EventManagement & logMgmt = chip::app::EventManagement::GetInstance();
75 EventOptions eventOptions;
yunhanw-googlee4508322022-01-26 18:27:51 -080076 eventOptions.mPath = path;
77 eventOptions.mPriority = aEventData.GetPriorityLevel();
78 eventOptions.mFabricIndex = aEventData.GetFabricIndex();
yunhanw-googlec037fc22022-08-17 16:02:52 -070079 // this skips logging the event if it's fabric-scoped but no fabric association exists yet.
yunhanw-google977aba02022-08-22 06:53:08 -070080 VerifyOrReturnError(eventOptions.mFabricIndex != kUndefinedFabricIndex, CHIP_ERROR_INVALID_FABRIC_INDEX);
Jerry Johns11a5b142022-02-17 15:21:39 -080081
82 //
83 // Unlike attributes which have a different 'EncodeForRead' for fabric-scoped structs,
84 // fabric-sensitive events don't require that since the actual omission of the event in its entirety
85 // happens within the event management framework itself at the time of access.
86 //
87 // The 'mFabricIndex' field in the event options above is encoded out-of-band alongside the event payload
88 // and used to match against the accessing fabric.
89 //
yunhanw-googlee4508322022-01-26 18:27:51 -080090 return logMgmt.LogEvent(&eventData, eventOptions, aEventNumber);
91}
92
93template <typename T, std::enable_if_t<!DataModel::IsFabricScoped<T>::value, bool> = true>
yunhanw-googlecd44f9b2022-03-09 10:36:31 -080094CHIP_ERROR LogEvent(const T & aEventData, EndpointId aEndpoint, EventNumber & aEventNumber)
yunhanw-google6f89b9b2021-12-07 14:26:21 -080095{
96 EventLogger<T> eventData(aEventData);
97 ConcreteEventPath path(aEndpoint, aEventData.GetClusterId(), aEventData.GetEventId());
98 EventManagement & logMgmt = chip::app::EventManagement::GetInstance();
yunhanw-google86823aa2021-12-08 06:35:52 -080099 EventOptions eventOptions;
yunhanw-google86823aa2021-12-08 06:35:52 -0800100 eventOptions.mPath = path;
101 eventOptions.mPriority = aEventData.GetPriorityLevel();
102 return logMgmt.LogEvent(&eventData, eventOptions, aEventNumber);
yunhanw-google6f89b9b2021-12-07 14:26:21 -0800103}
104
105} // namespace app
106} // namespace chip