Join us at MongoDB.local London on 7 May to unlock new possibilities for your data. Use WEB50 to save 50%.
Register now >
Docs Menu
Docs Home
/ /
Sync Data

Librería de eventos - Swift SDK

La Biblioteca de Eventos permite rastrear la actividad de un usuario mientras usa una aplicación móvil con sincronización habilitada. Puede registrar transacciones de lectura y escritura. Los desarrolladores también pueden configurar eventos personalizados para registrar las pulsaciones de botones, los datos mostrados en la interfaz de usuario u otros detalles importantes.

When you use the Event Library, you can specify the events you want to record. This means opening two realms:

  • The user realm, where the user does the reading and writing in the client application

  • The event realm, where the Event Library records scoped and custom events

The data from both realms syncs to your App Services App. The client user never interacts directly with the event realm or its data; and the event realm Sync user can even be different from the user realm.

Because the Event Library generates a large amount of data:

  • El dispositivo cliente debe tener suficiente capacidad para almacenar los datos

  • Expect Device Sync usage for the event realm to be higher than the reading and writing in the user realm

  • El clúster Atlas de respaldo de la aplicación debe tener suficiente capacidad de almacenamiento para gestionar los datos generados por la librería de eventos

La biblioteca de eventos almacena datos en un AuditEvent colección en su fuente de datos Atlas vinculada. Habilitar Modo de desarrollo en su aplicación App Services para permitir que Atlas cree la colección e infiera el esquema a partir de los eventos cargados

Importante

Se requiere sincronización basada en particiones

La biblioteca de eventos no admite la grabación de AuditEvents mediante la sincronización flexible. Esta función requiere una aplicación de servicios de sincronización basada en particiones para grabar datos de AuditEvent.

Para habilitar la grabación de eventos,configure la propiedad Event.Configuration en Realm.Configuration.

You can initialize the EventConfiguration in either of two ways:

  • Use the default-initialized configuration when you don't need to specify details

  • Pase parámetros adicionales para personalizar la configuración del evento

Si no necesitas especificar parámetros particulares, puedes usar el EventConfiguration inicializado por defecto:

var config = user.configuration(partitionValue: "Some partition value")
config.eventConfiguration = EventConfiguration()

Puede pasar parámetros opcionales para personalizar EventConfiguration:

  • metadata: Diccionario de metadatos de tipo String para agregar a cada evento

  • syncUser: El usuario que se usará para sincronizar los dominios de eventos. Si es nulo, se usa el usuario de Realm.Configuration de forma predeterminada.

  • partitionPrefix: String prefix to append to the event partition value

  • logger: Registrador personalizado para usar en eventos. Si es nil, se utiliza por defecto el registrador del usuario en el realm.

  • errorHandlerEl controlador de errores personalizado que se llama si se produce un error de sincronización al cargar datos de eventos. Si es nil, el SDK registra el evento y luego llama a abort(). Las aplicaciones de producción siempre deben definir un evento errorHandler, a menos que se desee cancelar la ejecución debido al error.

let eventSyncUser = try await app.login(credentials: Credentials.anonymous)
var config = user.configuration(partitionValue: "Some partition value")
config.eventConfiguration = EventConfiguration(metadata: ["username": "Jason Bourne"], syncUser: eventSyncUser, partitionPrefix: "event-")

You can update metadata even after you have started recording events. Use the updateMetadata() function to replace the metadata supplied in the event configuration with new values.

Si actualiza los metadatos mientras un ámbito de evento está activo, la biblioteca de eventos no utiliza los nuevos metadatos hasta que comience el siguiente ámbito de evento.

var config = user.configuration(partitionValue: "Some partition value")
config.eventConfiguration = EventConfiguration(metadata: ["username": "Jason Bourne"], syncUser: user, partitionPrefix: "event-")
let realm = try! Realm(configuration: config)
let events = realm.events!
let updateUsernameScope = events.beginScope(activity: "Update username")
// Call some function that updates the user's username
updateUsername()
updateUsernameScope.commit()
// Update the metadata you supplied with the initial EventConfiguration
events.updateMetadata(["username": "John Michael Kane"])

Después de definir la configuración de eventos, puedes invocar la funcionalidad de grabación de eventos con la nueva propiedad events en un realm. Esto devuelve una instancia Event ligada a ese realm.

let realm = try! Realm(configuration: config)
let events = realm.events!

Changed in version 10.36.0: endScope() deprecated for commit() and cancel(), new Scope object

The Event Library records read and write events within the context of a scope. The scope is the period during which the Event Library watches for and records realm activities. You can set different scopes to record different types of events. For example, you might have scopes for specific user flows such as "login", different scopes for different screens, or different scopes for specific compliance-related activities.

Utiliza beginScope(activity: "some activity") para comenzar a registrar un nuevo evento con el nombre de actividad dado. Esto devuelve un objeto Scope, que puedes usar posteriormente para confirmar o cancelar el alcance. El comenzar un alcance registra las actividades que ocurren dentro de ese alcance como eventos de lectura o escritura.

  • Read events: run queries and instantiate objects. When the scope ends, the event realm records these activities as read events.

  • Write events: modify objects. When the scope ends, the event realm records the initial state of the object, as well as the new values of any properties that change durign the scope of the event.

Using beginScope to record an event opens the event realm if it is not already open. The SDK opens event realms on the background thread and reports errors to the error callback.

Nota

Overlapping Event Scopes

If more than one event scope is active simultaneously, generated events are recorded by all active scopes.

When you're done recording events for a scope, use commit() to save events that occurred within the scope. When you end the recording, the Event Library saves the event to disk locally. Then, if the device has a network connection, the SDK asynchronously sends the data to the server.

// Read event
let readEventScope = events.beginScope(activity: "read object")
let person = realm.objects(Person.self).first!
print("Found this person: \(person.name)")
readEventScope.commit()
let mutateEventScope = events.beginScope(activity: "mutate object")
// Write event
try! realm.write {
// Change name from "Anthony" to "Tony"
person.name = "Tony"
}
mutateEventScope.commit()

Alternately, you can cancel() an event scope. This stops recording events, and does not persist the events to disk or to the server.

let eventScope = events.beginScope(activity: "read object")
let person1 = realm.objects(Person.self).first!
print("Found this person: \(person1.name)")
eventScope.cancel()

You can check whether a given scope is currently in progress using the isActive bool. This returns true if you have begun a scope that you have not yet committed or canceled.

let readPersonScope = events.beginScope(activity: "read object")
let person2 = realm.objects(Person.self).first!
print("Found this person: \(person2.name)")
if readPersonScope.isActive {
print("The readPersonScope is active")
} else {
print("The readPersonScope is no longer active")
}
readPersonScope.cancel()

You can pass an optional completion block to commit() when you finish recording. The SDK calls this block when the event data has been successfully persisted - not when the event realm upload has completed.

let mutateScope = events.beginScope(activity: "mutate object with completion")
// Write event
try! realm.write {
// Add a userId
person.userId = "tony.stark@starkindustries.com"
}
mutateScope.commit(completion: { error in
if let error = error {
print("Error recording write event: \(error.localizedDescription)")
return
}
print("Successfully recorded a write event")
})

La librería de eventos te permite registrar clics de botón u otros eventos que no impliquen lecturas y guardados en la base de datos. Utiliza registroEvento para registrar un evento personalizado. Esta función toma los siguientes parámetros:

  • activity: the activity name. This is an arbitrary string, such as "user registration."

  • eventType: the type of event. This is an arbitrary string, such as "pressed Submit button."

  • data:una carga de datos opcional para el evento.

  • completion: an optional completion handler. The Event Library calls this completion block once the event has been saved to the event realm, or if an error occurs. A nil error indicates success.

Un evento personalizado no tiene un alcance como los eventos de lectura y escritura. Registrarlo es más similar a activar un disparador.

events.recordEvent(activity: "event", eventType: "custom event")

The Event Library converts each event object to a JSON object. Most Realm types have an analogous JSON representation. For example, a Realm String property becomes a JSON String.

This is how the Event Library represents the types that do not have a direct JSON analog:

fecha

Datos

Excluido completamente del evento.

UUID

Encoded to a RFC-4122-compliant string.

ObjectID

Codificado en nuestra representación de cadena ObjectID.

Decimal128

Encoded to a string, not a number. JSON numbers are officially infinite- precision, but are rarely actually implemented as such.

Lista

Encoded as an array.

Configura

Encoded as an array.

Dictionary

Encoded as an object.

Objetos incrustados

Encoded as an object.

Los enlaces de objetos no incrustados se codifican como la clave principal del destino. En eventos de lectura, si se sigue el enlace, este se expande al objeto completo. Si no se sigue el enlace, este permanece como clave principal.

Puede personalizar la serialización JSON de los objetos de evento. Para personalizar la carga útil del evento, utilice el protocolo CustomEventRepresentable.

When an object conforms to CustomEventRepresentable, the Event Library serializes objects by:

  • Constructing an accessor object

  • Calling customEventRepresentation on that accessor object

  • Serializing the result instead of the original object

Para cumplir con CustomEventRepresentable, tu objeto debe implementar una función customEventRepresentation que defina tu serialización personalizada.

// To customize event serialization, your object must
// conform to the `CustomEventRepresentable` protocol.
class Person: Object, CustomEventRepresentable {
@Persisted(primaryKey: true) var _id: ObjectId
@Persisted var name: String
@Persisted var employeeId: Int
@Persisted var userId: String?
convenience init(name: String, employeeId: Int) {
self.init()
self.name = name
self.employeeId = employeeId
}
// To conform to `CustomEventRepresentable`, your object
// must implement a `customEventRepresentation` func that
// defines your customized event serialization
func customEventRepresentation() -> String {
if employeeId == 0 {
return "invalid json"
}
return "{\"int\": \(employeeId)}"
}
}

El ámbito de eventos puede crecer bastante si el dispositivo está fuera de línea durante un tiempo prolongado.

To compensate for this, the Event Library automatically splits event data into multiple partitions as needed. When a partition reaches its maximum size, the Event Library closes the event realm and automatically begins writing to a new partition.

The Event Library checks whether the user has any unsynced partitions. If they do, the Event Library opens one, uploads the data, and then closes the file and deletes it. This repeats until the user has no unsynced partitions.

The AuditEvent collection where events are stored must have a schema defined on the server for the App receiving events.

The schema must contain the following fields:

ID

_id

ObjectId.

Type of Event

event

Optional string. read or write for scoped events, or an arbitrary string for custom events.

Alcance del evento

activity

Cadena opcional. El nombre del ámbito pasado a beginScope() para iniciar la grabación del evento, o una cadena arbitraria para eventos personalizados.

Marca de tiempo

timestamp

Hora local del dispositivo cuando finaliza el ámbito del evento y se confirman los datos, o la hora en la que el evento llega al servidor.

Datos

data

La carga útil del evento. Se trata de un blob JSON para eventos con ámbito específico o de una cadena arbitraria para eventos personalizados.

Metadata

metadata key (cadena)

Un diccionario de metadatos opcional. Cuando este diccionario contiene claves y valores, la clave se convierte en un nombre de campo en el objeto de evento, y el valor se almacena en ese campo para cada evento.

Cada evento contiene una carga útil en la propiedad data que captura el estado actual de los objetos que se están leyendo o escribiendo.

Payloads for custom events can be whatever the developer desires, including nil.

Importante

Debido a que la carga útil captura el estado actual de los objetos que se están leyendo o escribiendo, esto produce una gran cantidad de datos. Sin embargo, esto debe realizarse en el cliente y no en el servidor, ya que es posible que los datos exactos que ve el usuario nunca existan del lado del servidor. En la práctica, esto significa que el dispositivo debe tener la capacidad de almacenar una gran cantidad de datos si queda sin conexión. Además, el uso de Device Sync para el realm de evento puede ser mucho mayor que para la lectura y escritura que el usuario realiza en el realm de usuario.

Ejemplo

En nuestros ejemplos de eventos de registro anteriores, estas son las data cargas útiles para los eventos de lectura y escritura:

Read Event Payload
{
"type":"Person",
"value": [{
"_id":"62b38b3c10846041166f5deb",
"_partition":"",
"employeeId":2,
"name":"Anthony",
"userId":null
}]
}
Write Event Payload
{
"Person": {
"modifications": [{
"newValue": {
"name":"Tony"
},
"oldValue":{
"_id":"62b38b3c10846041166f5deb",
"_partition":"",
"employeeId":2,
"name":"Anthony",
"userId":null
}
}]
}
}

Volver

Set the Client Log Level