Saltar a contenido

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.target debe ser events y self.name igual al eventType (solo letras, dígitos y guion bajo).
  • allOf con el esquema base de evento de Unomi aporta eventType, scope, sessionId, profileId.
  • Declarar source y target si el productor los envía (Jitsu y el tracker de Unomi lo hacen); con unevaluatedProperties: false un campo no declarado invalida todo el evento.
  • El scope del evento debe existir en Unomi (validateScope en el esquema base).
  • Un esquema puede extender uno de fábrica (por ejemplo agregar propiedades a view) mediante self.extends con el $id del esquema a extender.
  • Versionar: cambiar version y $id ante 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 validateEvent en cada cambio.
  • Nombrar propiedades en camelCase y en un solo idioma; no repetir en properties datos que ya viajan en target.
  • No enviar datos personales en properties de eventos que no los necesitan: el perfil los recibe por login.
  • Los eventos de fábrica de Unomi (view, login, updateProperties, form, search, click, video, modifyConsent) ya tienen esquema; login y updateProperties son abiertos porque están protegidos por clave.