Docs Menu
Docs Home
/ /
Sincronizar datos

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.

Al usar la Biblioteca de eventos, puedes especificar los eventos que quieres registrar. Esto implica abrir dos dominios:

  • El ámbito del usuario, donde el usuario lee y escribe en la aplicación cliente.

  • El ámbito de eventos, donde la biblioteca de eventos registra eventos con alcance y personalizados

Los datos de ambos dominios se sincronizan con la aplicación de App Services. El usuario cliente nunca interactúa directamente con el dominio de eventos ni con sus datos; y el usuario que sincroniza el dominio de eventos puede incluso ser diferente del dominio del usuario.

Debido a que la biblioteca de eventos genera una gran cantidad de datos:

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

  • Se espera que el uso de sincronización de dispositivos para el ámbito de eventos sea mayor que la lectura y escritura en el ámbito de usuario.

  • El clúster Atlas de respaldo de la aplicación debe tener suficiente capacidad de almacenamiento para manejar los datos generados por la biblioteca 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.

Puede inicializar EventConfiguration de dos maneras:

  • Utilice la configuración inicializada predeterminada cuando no necesite especificar detalles

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

Si no necesita especificar parámetros particulares, puede utilizar el valor predeterminado inicializado EventConfiguration:

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

Puede pasar parámetros opcionales para personalizar EventConfiguration:

  • metadata:Diccionario de cadenas de campos de metadatos 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: Prefijo de cadena para agregar al valor de la partición del evento

  • loggerRegistrador personalizado para eventos. Si es nulo, se usa el registrador del dominio del usuario de forma predeterminada.

  • 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-")

Puedes actualizar los metadatos incluso después de haber iniciado la grabación de eventos. Usa la función updateMetadata() para reemplazar los metadatos proporcionados en la configuración del evento con los nuevos valores.

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, puede invocar la función de grabación de eventos con la nueva propiedad "eventos" en un dominio. Esto devuelve una Event instancia asociada a ese dominio.

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

Cambiado en la 10.36.0 versión: endScope() está obsoleto para commit() y cancel(), nuevo objeto Scope

La Biblioteca de Eventos registra eventos de lectura y escritura dentro del contexto de un ámbito. El ámbito es el periodo durante el cual la Biblioteca de Eventos supervisa y registra las actividades del dominio. Puede configurar diferentes ámbitos para registrar distintos tipos de eventos. Por ejemplo, puede tener ámbitos para flujos de usuario específicos, como "inicio de sesión", distintos ámbitos para distintas pantallas o distintos ámbitos para actividades específicas relacionadas con el cumplimiento normativo.

Use beginScope(activity: "some activity") para comenzar a registrar un nuevo evento con el nombre de actividad especificado. Esto devuelve un objeto Scope, que puede usar para confirmar o cancelar el alcance posteriormente. Al iniciar un alcance, se registran las actividades que ocurren dentro de él como eventos de lectura o escritura.

  • Eventos de lectura: ejecutan consultas e instancian objetos. Al finalizar el ámbito, el dominio de eventos registra estas actividades como eventos de lectura.

  • Escribir eventos: modificar objetos. Al finalizar el ámbito, el dominio de eventos registra el estado inicial del objeto, así como los nuevos valores de cualquier propiedad que cambie durante el ámbito del evento.

Usar beginScope para registrar un evento abre el dominio de eventos si aún no está abierto. El SDK abre dominios de eventos en el subproceso en segundo plano e informa de los errores a la devolución de llamada de errores.

Nota

Ámbitos de eventos superpuestos

Si más de un ámbito de evento está activo simultáneamente, los eventos generados se registran en todos los ámbitos activos.

Al terminar de grabar eventos para un ámbito, use commit() para guardar los eventos ocurridos dentro de él. Al finalizar la grabación, la biblioteca de eventos guarda el evento en el disco localmente. Luego, si el dispositivo tiene conexión de red, el SDK envía los datos al servidor de forma asíncrona.

// 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()

Como alternativa, puede cancel() un ámbito de evento. Esto detiene el registro de eventos y no los conserva en el disco ni en el servidor.

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

Puede comprobar si un ámbito dado está en curso mediante el booleano isActive. Este valor devuelve true si ha iniciado un ámbito que aún no ha confirmado ni cancelado.

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()

Puedes pasar un bloque de finalización opcional a commit() al finalizar la grabación. El SDK llama a este bloque cuando los datos del evento se han almacenado correctamente, no cuando se completa la carga del dominio de eventos.

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: el nombre de la actividad. Esta es una cadena arbitraria, como "registro de usuario".

  • eventType: el tipo de evento. Esta es una cadena arbitraria, como "presionó el botón Enviar".

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

  • completion: un controlador de finalización opcional. La biblioteca de eventos llama a este bloque de finalización una vez que el evento se ha guardado en el dominio de eventos o si se produce un error. Un error nulo indica éxito.

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")

La biblioteca de eventos convierte cada objeto de evento en un objeto JSON. La mayoría de los tipos de dominio tienen una representación JSON similar. Por ejemplo, una propiedad de cadena de dominio se convierte en una cadena JSON.

Así es como la biblioteca de eventos representa los tipos que no tienen un análogo JSON directo:

fecha

Datos

Excluido totalmente del evento.

UUID

Codificado en una cadena4122compatible con RFC-.

ObjectID

Codificado en nuestra representación de cadena ObjectID.

Decimal128

Codificado como una cadena, no como un número. Los números JSON tienen oficialmente precisión infinita, pero rara vez se implementan como tal.

Lista

Codificado como una matriz.

Configura

Codificado como una matriz.

Dictionary

Codificado como un objeto.

Objetos incrustados

Codificado como un objeto.

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.

Cuando un objeto se ajusta a CustomEventRepresentable, la biblioteca de eventos serializa los objetos mediante:

  • Construyendo un objeto de acceso

  • Llamando a customEventRepresentation en ese objeto de acceso

  • Serializar el resultado en lugar del objeto original

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.

Para compensar esto, la Biblioteca de Eventos divide automáticamente los datos de eventos en varias particiones según sea necesario. Cuando una partición alcanza su tamaño máximo, la Biblioteca de Eventos cierra el dominio de eventos y comienza a escribir automáticamente en una nueva partición.

La Biblioteca de Eventos comprueba si el usuario tiene particiones sin sincronizar. Si las tiene, abre una, carga los datos y, a continuación, cierra el archivo y lo elimina. Esto se repite hasta que el usuario no tenga particiones sin sincronizar.

La colección AuditEvent donde se almacenan los eventos debe tener un esquema definido en el servidor para la aplicación que recibe eventos.

El esquema debe contener los siguientes campos:

ID

_id

ObjectId.

Tipo de evento

event

Cadena opcional. read o write para eventos con alcance, o una cadena arbitraria para eventos personalizados.

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.

Las cargas útiles para eventos personalizados pueden ser las que desee el desarrollador, incluso nulas.

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:

Carga útil del evento de lectura
{
"type":"Person",
"value": [{
"_id":"62b38b3c10846041166f5deb",
"_partition":"",
"employeeId":2,
"name":"Anthony",
"userId":null
}]
}
Carga útil del evento de escritura
{
"Person": {
"modifications": [{
"newValue": {
"name":"Tony"
},
"oldValue":{
"_id":"62b38b3c10846041166f5deb",
"_partition":"",
"employeeId":2,
"name":"Anthony",
"userId":null
}
}]
}
}

Volver

Establecer el nivel de registro del cliente