事件库
Overview
事件库使开发者能够跟踪用户在使用支持 Device Sync 的移动应用程序时看到和编辑的数据。 事件库可以记录三种类型的事件:
读取事件
写入事件
自定义事件
开发者可以指定要记录的读取和写入事务。 此外,您可以配置自定义事件来记录按钮按下等事件或用户在前端应用程序中看到的内容。
这种详细程度使审核员或其他相关方能够准确评估发生的情况和时间。
重要
需要基于分区的同步
事件库不支持使用 Flexible Sync 记录 AuditEvents
。 此功能需要基于分区的同步 App Services App 来记录AuditEvent
数据。
用例(Use Case)
事件库提供执行审核的功能,以满足医疗保健或金融服务等监管严格的行业的合规性要求。
例子
医疗机构的护士使用启用了事件库的应用。 该应用程序向护士提供实时生命体征、从医疗设备流入的信息以及患者的历史治疗信息。 该应用程序本质上强制执行合规性,因为它的代码会根据正在查看的数据阻止护士不应执行的操作。 事件库捕获护士在应用程序界面中看到的所有信息,以及护士在查看这些信息后采取的操作。
在某些时候,该护士为患者提供治疗,后来使该机构陷入医疗事故诉讼。 法律部门必须审查护士在治疗期间可获得的信息。
事件库捕获护士在治疗期间查看的数字数据以及他采取的行动。 通过查看这些数据,法律团队可以评估这种处理方式是否合理。 如果没有这些信息,法务部门就无法了解和证明护士的行为是否合理。
如何操作
事件库在用户设备上打开一个单独的“事件”Realm。 此 Realm 可以访问开发者选择使用事件库监控的任何用户 Realm。
当开发者实现事件库时,他们会指定要记录的事件类型,以及要附加到事件记录的任何自定义元数据。 当客户端应用程序运行时,它会将指定的用户交互记录为“事件”Realm,如读取事件、写入事件或自定义事件。
当客户端设备具有网络连接时, Atlas Device Sync会将此事件域数据同步到链接的Atlas数据源中的AuditEvent
集合。
访问事件库数据
事件库将事件数据记录在链接的 Atlas 数据库中名为AuditEvent
的集合中。 配置事件库时,使用开发模式自动创建此集合并从同步事件派生模式。 请记住在将应用程序投入生产之前关闭“开发模式”。
事件库模式
您的AuditEvent
集合必须具有包含以下字段的模式:
字段名称 | 类型 | 必需 |
---|---|---|
_id | ObjectId | 必需 |
activity | 字符串 | 必需 |
_partition | 字符串 | 必需 |
timestamp | Date | 必需 |
event | 字符串 | Optional |
data | 字符串 | Optional |
此外,模式必须包含您使用的每个元数据键的可选string字段。 例如:
{ "<Metadata Key>": { "bsonType": "string" } }
例子
如果您不使用任何自定义元数据,您的模式可能如下所示:
{ "title": "AuditEvent", "bsonType": "object", "required": [ "_id", "_partition", "timestamp", "activity" ], "properties": { "_id": { "bsonType": "objectId" }, "_partition": { "bsonType": "string" }, "timestamp": { "bsonType": "date" }, "activity": { "bsonType": "string" }, "event": { "bsonType": "string" }, "data": { "bsonType": "string" } } }
事件类型
事件库记录三种类型的事件:
读取事件
写入事件
自定义事件
读取事件
事件库会将作为查询结果返回的数据记录为读取事件。 读取事件还记录 Realm 对象实例化的任何时间,例如点击链接或通过主键查找对象时。
事件库将读取事件记录为具有两个字段的 JSON 对象:
type
:存储类名value
:存储序列化对象的数组
读取事件存储值,如下所示:
单个对象读取事件:该值是一个具有单个元素的数组
与查询匹配的对象:该值是与查询匹配的所有对象的数组,即使这些对象从未使用过
写事务期间发生的读取:该值是写事务开始之前对象拥有的数据;它不反映写入事件期间发生的任何更改。
写入事务开始时不存在的对象:在写入事务中创建的对象根本不产生读取事件。
重要
事件库无法判断客户端应用程序中是否仅显示查询的子集。 例如,假设客户端应用程序有一个列表视图。 事件库的读取事件不记录滚动信息;它将读取事件记录为完整查询结果。 开发者必须使用自定义事件来记录客户端应用程序仅显示查询结果子集的时间。
读取事件组合
每个读取事件的流都可能在不添加信息的同一对象上产生大量“重复”事件。 为了减少这些“重复”事件,事件库丢弃并合并了一些事件。
事件库丢弃:
不匹配任何对象的查询
仅匹配新创建对象的查询
对象读取与先前查询匹配的对象
事件库合并:
对同一个表的多个查询合并为一个合并查询。
读取事件格式
读取事件对象的格式如下:
{ "_id": "62b396f4ebe94d2b871889bb", "_partition":"events-62b396f4ebe94d2b871889ba", "activity":"read object", "data": "{ "type":"Person", "value": [{ "_id": "62b396f4ebe94d2b871889b9", "_partition":"", "employeeId":1, "name":"Anthony" }] }", "event":"read", "timestamp": 2022-06-23T14:54:37.756+00:00 }
嵌入式对象读取事件
事件库通过在父对象中创建到嵌入式对象主键的链接来表示嵌入式对象。 如果用户不点击链接,则主键是嵌入式对象的唯一表示形式。 当用户点击链接时,嵌入式对象将在父对象中解析。
这还会生成一个针对嵌入式对象读取的顶级对象。
例子
Person
对象有一个嵌入式对象Office
,其中包含有关人员工作位置的详细信息。 当我们不点击链接查看任何office
详细信息时,父Person
对象仅显示嵌入式对象的对象ID。
{ "type": "Person", "value": [{ "_id": "62b47624265ff7b58e9b204e", "_partition": "", "employeeId": 1, "name": "Michael Scott", "office": "62b47624265ff7b58e9b204f" }] }
当我们点击链接查看嵌入式Office
对象的详细信息时,这将解析父对象中的嵌入式对象。 它还会仅生成子对象(在本例中为Office
对象)的第二个顶层读取。
{ "type":"Person", "value": [{ "_id": "62b47975a33224558bdf8b4d", "_partition": "", "employeeId": 1, "name": "Michael Scott", "office": { "_id": "62b47975a33224558bdf8b4e", "_partition": "", "city": "Scranton", "locationNumber": 123, "name": "Dunder Mifflin" } }] } { "type": "Office", "value": [{ "_id": "62b47975a33224558bdf8b4e", "_partition": "", "city": "Scranton", "locationNumber": 123, "name": "Dunder Mifflin" }] }
注意
读取事件组合
读取事件组合可能会影响您在查询对象以及稍后使用嵌入式对象链接时看到的对象。
在上面的示例中,如果您之前查询了 Person
,则当在 Person 对象中未解析 Office 对象时,会产生一个读取事件;您在初始读取事件中只能看到ObjectId 。 然后,如果您稍后点击解析嵌入式对象的链接,您将看到嵌入式对象的单独顶级读取,但不会看到显示父对象中已解析嵌入式对象的父对象读取。
写入事件
事件库会在以下情况下记录写入事件:
创建了新对象
现有对象已修改
对象已删除
写入事件记录对象之前和之后的状态。 对于创建的新对象,之前的状态为null
。 对于删除,对象的删除后状态为null
。
对于客户端在事件记录范围内提交的每个写事务,事件库都会记录一个写事件。 此写入事件记录写入事务期间所做的所有更改。
有效负载是一个以类名称为键的对象。 创建、修改或删除对象的每个对象类型都有一个条目。
事件库将对象类型的更改记录为具有三个数组的对象:
inserts:包含插入的序列化对象,使用与读取相同的序列化方案
修改:报告每个属性的旧值和新值
deleteions:包含已删除的序列化对象,使用与读取相同的序列化方案
在修改中, newValue
对象仅包含与oldValue
对象不同的属性。 如果写事务(write transaction)分配给对象但实际上并未更改任何属性的值,
写入事件格式
写入事件对象的格式如下:
{ "Person": { "insertions": [{ "_id": "62b47ead6a178a314ae0eb52", "_partition": "", "employeeId": 1, "name": "Anthony" }] } }
{ "Person":{ "modifications": [{ "newValue": { "name": "Tony" }, "oldValue": { "_id": "62b47d83cdac49f904c5737b", "_partition": "", "employeeId": 1, "name": "Anthony" } }] } }
{ "Person":{ "deletions":[{ "_id":"62b47ead6a178a314ae0eb52", "_partition":"", "employeeId":1, "name":"Tony", "userId":"tony.stark@starkindustries.com" }] } }
自定义事件
自定义事件可以记录不读取或写入数据库的事件类型,例如:
当显示特定屏幕时
当用户单击按钮时
您可以使用自定义事件为读取和写入事件提供上下文,例如在客户端应用程序显示给定屏幕时记录自定义事件。 然后,您可以推断在记录应用屏幕加载的自定义事件之后,读取和写入事件都发生在该应用屏幕上。
自定义事件可以存储开发者想要的任何数据,也可以不存储任何数据。
{ "_id": "62b4804c15659310991e5e0a", "_partition": "events-62b4804b15659310991e5e09", "activity": "login", "event": "custom event", "timestamp": 2022-06-23T15:01:31.941+00:00 }