É possível transformar os dados do CloudEvents escrevendo expressões de transformação usando a CEL. Para mais informações, consulte Transformar eventos recebidos.
Confira a seguir alguns casos de uso e exemplos comuns que mostram como escrever expressões CEL para transformar os dados de eventos.
Casos de uso padrão
Confira a seguir alguns casos de uso padrão ao transformar dados de eventos.
Normalização de dados
É necessário nivelar uma estrutura de dados aninhada na mensagem de evento para facilitar o processamento por um serviço downstream.
- Cenário:
Considerando os seguintes dados do CloudEvents:
{ "data": { "orderId": "12345", "customer": { "firstName": "Alex", "lastName": "Taylor", "address": { "street": "1800 Amphibious Blvd.", "city": "Mountain View" } } } }
Você quer escrever uma expressão CEL que resulte na seguinte saída:
{ "data": { "orderId": "12345", "customerFirstName": "Alex", "customerLastName": "Taylor", "customerStreet": "1800 Amphibious Blvd.", "customerCity": "Mountain View" } }
- Solução 1:
Formate os dados de saída manualmente. Isso permite listar os nomes dos campos e escolher apenas os elementos necessários na saída. Essa é uma abordagem razoável quando a entrada é previsível e o número de campos é baixo. A função
setField
adiciona ou substitui um campo do evento por uma determinada chave. Exemplo: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, })
- Solução 2:
Use uma função na sua expressão. A função
setField
adiciona ou substitui um campo do evento por uma determinada chave. A funçãodenormalize
aplana estruturas profundas para uma lista de pares de chave-valor. Os nomes de campo são delimitados usando um período (.
) para segmentar a hierarquia da estrutura. Exemplo:message.setField("data", message.data.denormalize())
Isso resulta na saída abaixo, que difere um pouco do payload esperado. No entanto, as vantagens incluem uma expressão CEL mais curta, que opera em qualquer entrada e inclui automaticamente qualquer número de campos recebidos.
{ "data": { "orderId": "12345", "customer.firstName": "Alex", "customer.lastName": "Taylor", "customer.address.street": "1800 Amphibious Blvd.", "customer.address.city": "Mountain View" } }
Mascaramento de dados
É necessário mascarar dados sensíveis em um payload de evento antes que ele seja enviado para um ambiente menos seguro.
- Cenário:
Considerando os seguintes dados do CloudEvents:
{ "data": { "userId": "user123", "email": "alex@example.com", "creditCardNumber": "1234-5678-9012-3456" } }
Você quer escrever uma expressão CEL que resulte na seguinte saída:
{ "data": { "userId": "user123", "email": "a***@example.com", "creditCardNumber": "xxxx-xxxx-xxxx-3456" } }
- Solução:
Use uma expressão para mascarar informações sensíveis, como o endereço de e-mail e o número do cartão de crédito. A função
setField
adiciona ou substitui um campo do evento por uma determinada chave. A função de expressão regularextract
segue a sintaxe RE2. Exemplo: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"))
Descarte de dados sensíveis
Você precisa remover campos específicos de um payload de evento com base em determinadas condições.
- Cenário:
Considerando os seguintes dados do CloudEvents:
{ "data": { "orderId": "12345", "customerType": "gold", "discountCode": "VIP" } }
Você quer escrever uma expressão CEL que resulte na seguinte saída:
{ { "orderId": "12345", "customerType": "gold" } }
- Solução:
Use uma expressão que oculte o campo
discountCode
se ocustomerType
for "gold". A funçãoremoveFields
remove campos específicos de um evento. Exemplo:message.data.customerType == "gold" ? message.removeFields(["data.discountCode"]) : message
Conversão de dados
Você precisa converter dados de um formato ou tipo para outro.
- Cenário:
Considerando os seguintes dados do CloudEvents:
{ "data": { "orderDate": "2024-10-31T12:00:00Z", "totalAmount": "1500" } }
Você quer escrever uma expressão CEL que resulte na seguinte saída:
{ "data": { "orderDate": 1704086400, "totalAmount": 1500.00 } }
- Solução:
Use uma expressão que converta
orderDate
em um carimbo de data/hora do UNIX e o tipototalAmount
de umstring
em umdouble
(número de ponto flutuante). A funçãosetField
adiciona ou substitui um campo do evento por uma determinada chave. Use funções de manipulação de string para converter os resultados de string. Exemplo:message .setField("data.orderDate", int(timestamp(message.data.orderDate))) .setField("data.totalAmount", double(message.data.totalAmount))
Roteamento condicional
Você precisa rotear eventos para diferentes destinos com base nos dados do evento.
- Cenário:
Considerando os seguintes dados do CloudEvents:
{ "data": { "eventType": "order.created", "orderValue": 200 } }
Você quer escrever uma expressão CEL que resulte na seguinte saída:
{ "data": { "eventType": "order.created", "orderValue": 200, "routingKey": "highValue" } }
- Solução:
Use uma expressão que adicione um campo
routingKey
com um "highValue" se oorderValue
for maior que 100. Caso contrário, use"normal"
. O camporoutingKey
pode ser usado para determinar o caminho de roteamento. A funçãosetField
adiciona ou substitui um campo do evento por uma determinada chave. Exemplo:message.data.orderValue > 100 ? message.setField("data.routingKey", "highValue") : message.setField("data.routingKey", "normal")
Processamento de valores padrão
É necessário garantir que determinados campos no payload do evento tenham valores padrão se eles não estiverem presentes.
- Cenário:
Considerando os seguintes dados do CloudEvents:
{ "data": { "itemName": "Product A" } }
Você quer escrever uma expressão CEL que resulte na seguinte saída:
{ "data": { "itemName": "Product A", "quantity": 1 } }
- Solução:
Use uma expressão que adicione um campo
quantity
com um valor padrão de1
, se o campo ainda não existir. A macrohas
testa se um campo está disponível. A funçãosetField
adiciona ou substitui um campo do evento por uma determinada chave. Exemplo:has(message.data.quantity) ? message : message.setField("data.quantity", 1)
Manipulação de strings
Você precisa extrair ou modificar partes de um campo de string nos dados do evento.
- Cenário:
Considerando os seguintes dados do CloudEvents:
{ "data": { "customerEmail": "alex@example.com" } }
Você quer escrever uma expressão CEL que resulte na seguinte saída:
{ "data": { "customerEmail": "alex@example.com", "emailDomain": "example.com" } }
- Solução:
Use uma expressão que extrai o nome de domínio ("example.com") do campo
customerEmail
e o armazena em um novo campoemailDomain
. A funçãosetField
adiciona ou substitui um campo do evento por uma determinada chave. A função de expressão regularextract
segue a sintaxe RE2. Exemplo:message .setField("data.emailDomain", re.extract(message.data.customerEmail, "(^.*@)(.*)", "\\2"))
Listar e mapear operações
Você precisa trabalhar com listas ou mapas nos dados de eventos.
- Cenário:
Considerando os seguintes dados do CloudEvents:
{ "data": { "productIds": [ "product123", "product456" ] } }
Você quer escrever uma expressão CEL que resulte na seguinte saída:
{ "data": { "productIds": [ "product123", "product456" ], "productFound": true } }
- Solução:
Use uma expressão que verifique se "product456" existe na lista
productIds
e armazene o resultado (true
oufalse
) em um novo campoproductFound
. A funçãosetField
adiciona ou substitui um campo do evento por uma determinada chave. A macroexists
testa se um predicado é válido para todos os elementos de uma lista e combina os resultados com o operador "or". Exemplo:message.setField("data.productFound", message.data.productIds.exists(id, id == "product123"))
Tratamento de erros
É necessário processar com cuidado possíveis erros ou dados inesperados no payload do evento.
- Cenário:
Considerando os seguintes dados do CloudEvents:
{ "data": { "quantity": "abc" } }
Você quer escrever uma expressão CEL que resulte na seguinte saída:
{ "data": { "quantity": 0, "error": "Invalid quantity" } }
- Solução:
Use uma expressão que tente converter o campo
quantity
em um número inteiro. Se a conversão falhar, defina o campoquantity
como0
e adicione um novo campoerror
com o valor "Quantidade inválida".- A macro
has
testa se um campo está disponível. - A função
type
retorna o tipo de um valor. - A função de expressão regular
matches
segue a sintaxe RE2. - A função
setField
adiciona ou substitui um campo do evento por uma determinada chave.
Exemplo:
// 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")
- A macro
Casos de uso complexos
Confira a seguir alguns casos de uso complexos ao transformar dados de eventos.
Transformação de dados
Você precisa realizar várias transformações em dados de eventos aninhados.
- Cenário:
Considerando os seguintes dados do 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 } ] } }
Você quer escrever uma expressão CEL que resulte na seguinte saída:
{ "data": { "orderId": "12345", "customer.firstName": "Alex", "customer.lastName": "Taylor", "customer.email": "a***@example.com", "customer.address.city": "Mountain View", "customer.address.state": "CA" } }
- Solução:
Use uma expressão que extraia a cidade e o estado do endereço e que oculte o endereço de e-mail.
- A função
setField
adiciona ou substitui um campo do evento por uma determinada chave. - A função
toMap
converte uma lista de mapas CEL em um único mapa CEL. - A função de expressão regular
extract
segue a sintaxe RE2. - A função
removeFields
remove campos específicos de um evento. - A função
denormalize
aplana estruturas profundas para uma lista de pares de chave-valor. Os nomes de campo são delimitados usando um período (.
) para segmentar a hierarquia da estrutura.
Exemplo:
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() )
- A função
Formatação e roteamento de dados
Você precisa formatar os dados do evento, adicionar informações do produto e encaminhar a mensagem do evento.
- Cenário:
Considerando os seguintes dados do CloudEvents:
{ "data": { "productId": "p123", "productName": "Example Product", "category": "electronics" } }
Você quer escrever uma expressão CEL que resulte na seguinte saída:
{ "data": { "productId": "electronics-p123", "productName": "EXAMPLE PRODUCT", "category": "electronics", "routingKey": "electronics" } }
- Solução:
Use uma expressão que formata o nome do produto em maiúsculas, adiciona um prefixo ao ID do produto com base na categoria e inclui uma chave de roteamento para processamento posterior. A função
setField
adiciona ou substitui um campo do evento por uma determinada chave. A funçãoupperAscii
retorna uma string com todos os caracteres ASCII convertidos em caracteres maiúsculos correspondentes. Exemplo:message .setField("data.productId", message.data.category + "-" + message.data.productId) .setField("data.productName", message.data.productName.upperAscii()) .setField("data.routingKey", message.data.category)