Puedes transformar tus datos de CloudEvents escribiendo expresiones de transformación con CEL. Para obtener más información, consulta Transforma los eventos recibidos.
A continuación, se incluyen algunos casos de uso y ejemplos comunes que muestran cómo escribir expresiones de CEL para transformar tus datos de eventos.
Casos de uso estándar
A continuación, se incluyen algunos casos de uso estándar cuando se transforman datos de eventos.
Normalización de datos
Necesitas aplanar una estructura de datos anidada en el mensaje del evento para que un servicio downstream pueda procesarla con mayor facilidad.
- Situación:
Dados los siguientes datos de CloudEvents:
{ "data": { "orderId": "12345", "customer": { "firstName": "Alex", "lastName": "Taylor", "address": { "street": "1800 Amphibious Blvd.", "city": "Mountain View" } } } }
Quieres escribir una expresión en CEL que genere el siguiente resultado:
{ "data": { "orderId": "12345", "customerFirstName": "Alex", "customerLastName": "Taylor", "customerStreet": "1800 Amphibious Blvd.", "customerCity": "Mountain View" } }
- Solución 1:
Dar formato a los datos de salida de forma manual Esto te permite enumerar los nombres de los campos y elegir solo los elementos necesarios en el resultado. Este es un enfoque razonable cuando la entrada es predecible y la cantidad de campos es baja. La función
setField
agrega o reemplaza un campo del evento con una clave determinada. Por ejemplo:message.setField("data", { "orderId": message.data.orderId, "customerFirstName": message.data.customer.firstName, "customerLastName": message.data.customer.lastName, "customerStreet": message.data.customer.address.street, "customerCity": message.data.customer.address.city, })
- Solución 2:
Usa una función en tu expresión. La función
setField
agrega o reemplaza un campo del evento con una clave determinada. La funcióndenormalize
aplana las estructuras profundas en una lista de pares clave-valor. Los nombres de los campos se delimitan con un punto (.
) para segmentar la jerarquía de la estructura. Por ejemplo:message.setField("data", message.data.denormalize())
Esto genera el siguiente resultado, que difiere ligeramente de la carga útil esperada. Sin embargo, las ventajas incluyen una expresión CEL más corta que funciona con cualquier entrada y que incluye automáticamente cualquier cantidad de campos entrantes.
{ "data": { "orderId": "12345", "customer.firstName": "Alex", "customer.lastName": "Taylor", "customer.address.street": "1800 Amphibious Blvd.", "customer.address.city": "Mountain View" } }
Enmascarar datos
Debes enmascarar los datos sensibles en la carga útil de un evento antes de que se envíe a un entorno menos seguro.
- Situación:
Dados los siguientes datos de CloudEvents:
{ "data": { "userId": "user123", "email": "alex@example.com", "creditCardNumber": "1234-5678-9012-3456" } }
Quieres escribir una expresión en CEL que genere el siguiente resultado:
{ "data": { "userId": "user123", "email": "a***@example.com", "creditCardNumber": "xxxx-xxxx-xxxx-3456" } }
- Solución:
Usa una expresión para enmascarar cualquier información sensible, como la dirección de correo electrónico y el número de tarjeta de crédito. La función
setField
agrega o reemplaza un campo del evento con una clave determinada. La función de expresión regularextract
sigue la sintaxis RE2. Por ejemplo:message .setField("data.email", re.extract(message.data.email, "(^.).*@(.*)", "\\1***@\\2")) .setField("data.creditCardNumber", re.extract(message.data.creditCardNumber, "(\\d{4})\\D*$", "xxxx-xxxx-xxxx-\\1"))
Ocultación de datos
Debes quitar campos específicos de la carga útil de un evento según ciertas condiciones.
- Situación:
Dados los siguientes datos de CloudEvents:
{ "data": { "orderId": "12345", "customerType": "gold", "discountCode": "VIP" } }
Quieres escribir una expresión en CEL que genere el siguiente resultado:
{ { "orderId": "12345", "customerType": "gold" } }
- Solución:
Usa una expresión que oculte el campo
discountCode
si elcustomerType
es "gold". La funciónremoveFields
quita campos específicos de un evento. Por ejemplo:message.data.customerType == "gold" ? message.removeFields(["data.discountCode"]) : message
Conversión de datos
Necesitas convertir datos de un formato o tipo a otro.
- Situación:
Dados los siguientes datos de CloudEvents:
{ "data": { "orderDate": "2024-10-31T12:00:00Z", "totalAmount": "1500" } }
Quieres escribir una expresión en CEL que genere el siguiente resultado:
{ "data": { "orderDate": 1704086400, "totalAmount": 1500.00 } }
- Solución:
Usa una expresión que convierta
orderDate
en una marca de tiempo de UNIX y el tipototalAmount
de unstring
a undouble
(número de punto flotante). La funciónsetField
agrega o reemplaza un campo del evento con una clave determinada. Puedes usar funciones de manipulación de cadenas para convertir los resultados de cadenas. Por ejemplo:message .setField("data.orderDate", int(timestamp(message.data.orderDate))) .setField("data.totalAmount", double(message.data.totalAmount))
Enrutamiento condicional
Necesitas enrutar eventos a diferentes destinos según los datos del evento.
- Situación:
Dados los siguientes datos de CloudEvents:
{ "data": { "eventType": "order.created", "orderValue": 200 } }
Quieres escribir una expresión en CEL que genere el siguiente resultado:
{ "data": { "eventType": "order.created", "orderValue": 200, "routingKey": "highValue" } }
- Solución:
Usa una expresión que agregue un campo
routingKey
con un valor "highValue" si el campoorderValue
es mayor que 100; de lo contrario,"normal"
. El camporoutingKey
se puede usar para determinar la ruta. La funciónsetField
agrega o reemplaza un campo del evento con una clave determinada. Por ejemplo:message.data.orderValue > 100 ? message.setField("data.routingKey", "highValue") : message.setField("data.routingKey", "normal")
Control de valores predeterminados
Debes asegurarte de que ciertos campos de la carga útil del evento tengan valores predeterminados si no están presentes.
- Situación:
Dados los siguientes datos de CloudEvents:
{ "data": { "itemName": "Product A" } }
Quieres escribir una expresión en CEL que genere el siguiente resultado:
{ "data": { "itemName": "Product A", "quantity": 1 } }
- Solución:
Usa una expresión que agregue un campo
quantity
con un valor predeterminado de1
si el campo aún no existe. La macro dehas
comprueba si un campo está disponible. La funciónsetField
agrega o reemplaza un campo del evento con una clave determinada. Por ejemplo:has(message.data.quantity) ? message : message.setField("data.quantity", 1)
Manipulación de cadenas
Necesitas extraer o modificar partes de un campo de cadena en los datos del evento.
- Situación:
Dados los siguientes datos de CloudEvents:
{ "data": { "customerEmail": "alex@example.com" } }
Quieres escribir una expresión en CEL que genere el siguiente resultado:
{ "data": { "customerEmail": "alex@example.com", "emailDomain": "example.com" } }
- Solución:
Usa una expresión que extraiga el nombre de dominio (“example.com”) del campo
customerEmail
y lo almacene en un campoemailDomain
nuevo. La funciónsetField
agrega o reemplaza un campo del evento con una clave determinada. La función de expresión regularextract
sigue la sintaxis RE2. Por ejemplo:message .setField("data.emailDomain", re.extract(message.data.customerEmail, "(^.*@)(.*)", "\\2"))
Operaciones de lista y mapa
Necesitas trabajar con listas o mapas en los datos del evento.
- Situación:
Dados los siguientes datos de CloudEvents:
{ "data": { "productIds": [ "product123", "product456" ] } }
Quieres escribir una expresión en CEL que genere el siguiente resultado:
{ "data": { "productIds": [ "product123", "product456" ], "productFound": true } }
- Solución:
Usa una expresión que verifique si "product456" existe en la lista
productIds
y almacene el resultado (true
ofalse
) en un nuevo campoproductFound
. La funciónsetField
agrega o reemplaza un campo del evento con una clave determinada. La macroexists
prueba si un predicado se cumple para todos los elementos de una lista y combina los resultados con el operador "o". Por ejemplo:message.setField("data.productFound", message.data.productIds.exists(id, id == "product123"))
Manejo de errores
Debes controlar con elegancia los posibles errores o los datos inesperados en la carga útil del evento.
- Situación:
Dados los siguientes datos de CloudEvents:
{ "data": { "quantity": "abc" } }
Quieres escribir una expresión en CEL que genere el siguiente resultado:
{ "data": { "quantity": 0, "error": "Invalid quantity" } }
- Solución:
Usa una expresión que intente convertir el campo
quantity
en un número entero. Si falla la conversión, establece el campoquantity
en0
y agrega un campoerror
nuevo con el valor "Cantidad no válida".- La macro
has
comprueba si un campo está disponible. - La función
type
devuelve el tipo de un valor. - La función de expresión regular
matches
sigue la sintaxis RE2. - La función
setField
agrega o reemplaza un campo del evento con una clave determinada.
Por ejemplo:
// Check if data.quantity exists has(message.data.quantity) && // Check if data.quantity is a string type(message.data.quantity) == string && // Check if string consists of digits message.data.quantity.matches(r'^-?[0-9]+$') ? // If data.quantity is valid, use message message : // If data.quantity is invalid, set to 0 and generate error message .setField("data.quantity", 0) .setField("data.error", "Invalid quantity")
- La macro
Casos de uso complejos
A continuación, se incluyen algunos casos de uso complejos cuando se transforman datos de eventos.
Transformación de datos
Necesitas realizar varias transformaciones en los datos de eventos anidados.
- Situación:
Dados los siguientes datos de CloudEvents:
{ "data": { "orderId": "12345", "customer": { "firstName": "Alex", "lastName": "Taylor", "email": "alex@example.com", "address": { "street": "1800 Amphibious Blvd.", "city": "Mountain View", "state": "CA" } }, "items": [ { "itemId": "item1", "price": 10.00, "quantity": 2 }, { "itemId": "item2", "price": 5.00, "quantity": 1 } ] } }
Quieres escribir una expresión en CEL que genere el siguiente resultado:
{ "data": { "orderId": "12345", "customer.firstName": "Alex", "customer.lastName": "Taylor", "customer.email": "a***@example.com", "customer.address.city": "Mountain View", "customer.address.state": "CA" } }
- Solución:
Usa una expresión que extraiga la ciudad y el estado de la dirección, y que enmascare la dirección de correo electrónico.
- La función
setField
agrega o reemplaza un campo del evento con una clave determinada. - La función
toMap
convierte una lista de CEL de mapas de CEL en un solo mapa de CEL. - La función de expresión regular
extract
sigue la sintaxis RE2. - La función
removeFields
quita campos específicos de un evento. - La función
denormalize
aplana las estructuras profundas en una lista de pares clave-valor. Los nombres de los campos se delimitan con un punto (.
) para segmentar la jerarquía de la estructura.
Por ejemplo:
message .setField("data", message.data.setField("customer.address", message.data.customer.address.map(key, key == "city" || key == "state", { key: message.data.customer.address[key] }).toMap()) .setField("customer.email", re.extract(message.data.customer.email, "(^..?).*@(.*)", "\\1***@\\2")) .removeFields(["items"]) .denormalize() )
- La función
Formato y enrutamiento de datos
Debes dar formato a los datos del evento, agregar información del producto y, luego, enrutar el mensaje del evento.
- Situación:
Dados los siguientes datos de CloudEvents:
{ "data": { "productId": "p123", "productName": "Example Product", "category": "electronics" } }
Quieres escribir una expresión en CEL que genere el siguiente resultado:
{ "data": { "productId": "electronics-p123", "productName": "EXAMPLE PRODUCT", "category": "electronics", "routingKey": "electronics" } }
- Solución:
Usa una expresión que dé formato al nombre del producto en mayúsculas, agregue un prefijo al ID del producto según su categoría y que incluya una clave de enrutamiento para el procesamiento posterior. La función
setField
agrega o reemplaza un campo del evento con una clave determinada. La funciónupperAscii
devuelve una cadena con todos los caracteres ASCII convertidos a sus caracteres en mayúsculas correspondientes. Por ejemplo:message .setField("data.productId", message.data.category + "-" + message.data.productId) .setField("data.productName", message.data.productName.upperAscii()) .setField("data.routingKey", message.data.category)