Esquemas de eventos¶
Desde Unomi 2, cada tipo de evento que entra por la API pública se valida contra un esquema JSON
(https://json-schema.org, borrador 2019-09). Sin esquema para su eventType, el evento se descarta. Un esquema
rechaza cualquier propiedad no declarada cuando usa additionalProperties: false / unevaluatedProperties: false.
Formato¶
Los tres esquemas validados en el banco de pruebas están en
unomi-eval/tests/schemas/.
Estructura mínima de un esquema propio:
{
"$id": "https://cdp.compulandia.com.py/schemas/json/events/productView/1-0-0",
"$schema": "https://json-schema.org/draft/2019-09/schema",
"self": {"vendor": "py.com.compulandia", "target": "events", "name": "productView", "format": "jsonschema", "version": "1-0-0"},
"title": "productView",
"type": "object",
"allOf": [{"$ref": "https://unomi.apache.org/schemas/json/event/1-0-0"}],
"properties": {
"source": {"$ref": "https://unomi.apache.org/schemas/json/item/1-0-0"},
"target": {"$ref": "https://unomi.apache.org/schemas/json/item/1-0-0"},
"properties": {
"type": "object",
"properties": {
"productId": {"type": "string"},
"categoria": {"type": "string"},
"precio": {"type": "number", "minimum": 0}
},
"required": ["productId", "categoria", "precio"],
"additionalProperties": false
}
},
"unevaluatedProperties": false
}
Reglas del formato:
$idúnico (una URL, no hace falta que resuelva).self.targetdebe sereventsyself.nameigual aleventType(solo letras, dígitos y guion bajo).allOfcon el esquema base de evento de Unomi aportaeventType,scope,sessionId,profileId.- Declarar
sourceytargetsi el productor los envía (Jitsu y el tracker de Unomi lo hacen); conunevaluatedProperties: falseun campo no declarado invalida todo el evento. - El
scopedel evento debe existir en Unomi (validateScopeen el esquema base). - Un esquema puede extender uno de fábrica (por ejemplo agregar propiedades a
view) medianteself.extendscon el$iddel esquema a extender. - Versionar: cambiar
versiony$idante un cambio incompatible, y mantener ambos hasta que Jitsu migre.
Registrar, consultar y borrar¶
| Operación | API (usuario karaf) |
Inoyu |
|---|---|---|
| Listar ids instalados | GET /cxs/jsonSchema |
JSON Schemas |
| Registrar o actualizar | POST /cxs/jsonSchema con el esquema como cuerpo (Content-Type: application/json); responde 200. Re-enviar el mismo $id lo reemplaza. |
JSON Schemas → nuevo |
| Ver uno | POST /cxs/jsonSchema/query con el $id como cuerpo (texto) |
JSON Schemas → abrir |
| Validar un evento de prueba | POST /cxs/jsonSchema/validateEvent con el evento como cuerpo; responde [] si es válido o la lista de errores |
— |
| Borrar | POST /cxs/jsonSchema/delete con el $id como cuerpo |
JSON Schemas → borrar |
Ejemplo:
U=https://cdp-api.compulandia.com.py; A="karaf:$UNOMI_ROOT_PASSWORD" # más cabeceras CF-Access-Client-Id/Secret
curl -s -u "$A" -H 'Content-Type: application/json' -X POST "$U/cxs/jsonSchema" --data-binary @productView.json
curl -s -u "$A" -H 'Content-Type: application/json' -X POST "$U/cxs/jsonSchema/validateEvent" \
-d '{"eventType":"productView","scope":"tienda-web","properties":{"productId":"sku-1","categoria":"hogar","precio":10}}'
Tras registrar un esquema, esperar 1 a 2 segundos antes de enviar eventos: Unomi lo persiste en Elasticsearch y recarga su caché cada segundo.
Errores típicos y cómo se ven¶
Todos aparecen en el log de Unomi como WARN SchemaServiceImpl ... Validation error: ... y en la respuesta de
validateEvent. El evento real recibe igualmente 200 {"updated":0}.
| Mensaje | Causa | Corrección |
|---|---|---|
$.properties.color: is not defined in the schema and the schema does not allow additional properties |
Propiedad no declarada | Declararla en el esquema o quitarla en Jitsu |
$.properties.cantidad: string found, integer expected |
Tipo incorrecto | Corregir el mapeo en Jitsu |
$.properties.items: is missing but it is required |
Falta una obligatoria | Enviarla o quitarla de required |
Schema not found for event type: refund |
Tipo sin esquema | Registrar el esquema |
There are unevaluated properties at the following paths $.source.itemId ... |
source/target no declarados |
Declararlos como en el ejemplo |
Unknown scope value at $.scope for value tienda-web |
Scope inexistente o creado hace menos de 2 s | Crear el scope (POST /cxs/scopes) y esperar |
Buenas prácticas¶
- Mantener un evento de ejemplo válido por tipo junto al esquema y validarlo con
validateEventen cada cambio. - Nombrar propiedades en camelCase y en un solo idioma; no repetir en
propertiesdatos que ya viajan entarget. - No enviar datos personales en
propertiesde eventos que no los necesitan: el perfil los recibe porlogin. - Los eventos de fábrica de Unomi (
view,login,updateProperties,form,search,click,video,modifyConsent) ya tienen esquema;loginyupdatePropertiesson abiertos porque están protegidos por clave.