Processar regras configuráveis baseadas em limiares no Azure Stream Analytics

Este artigo descreve como utilizar dados de referência para obter uma solução de alerta que utiliza regras configuráveis baseadas em limiares no Azure Stream Analytics.

Cenário: Alertas com base em limiares de regras ajustáveis

Poderá ter de produzir um alerta como saída quando os eventos transmitidos em fluxo de entrada atingirem um determinado valor ou quando um valor agregado com base nos eventos transmitidos em fluxo de entrada exceder um determinado limiar. É simples configurar uma consulta do Stream Analytics que comparou o valor a um limiar estático que é fixo e pré-determinado. Um limiar fixo pode ser codificado na sintaxe da consulta de transmissão em fluxo através de comparações numéricas simples (maiores do que, menos do que e igualdade).

Em alguns casos, os valores de limiar têm de ser mais facilmente configuráveis sem editar a sintaxe da consulta sempre que um valor de limiar for alterado. Noutros casos, poderá precisar de vários dispositivos ou utilizadores processados pela mesma consulta, com cada um deles a ter valores de limiar diferentes em cada tipo de dispositivo.

Este padrão pode ser utilizado para configurar dinamicamente limiares, escolher seletivamente o tipo de dispositivo que o limiar se aplica ao filtrar os dados de entrada e escolher seletivamente os campos a incluir na saída.

Utilize uma entrada de dados de referência para uma tarefa do Stream Analytics como uma pesquisa dos limiares de alerta:

  • Armazene os valores de limiar nos dados de referência, um valor por chave.
  • Associe os eventos de entrada de dados de transmissão em fluxo aos dados de referência na coluna de chave.
  • Utilize o valor com chave dos dados de referência como o valor de limiar.

Dados de exemplo e consulta

No exemplo, os alertas são gerados quando a agregação da transmissão em fluxo de dados a partir de dispositivos numa janela com um minuto de duração corresponde aos valores estipulados na regra fornecida como dados de referência.

Na consulta, para cada deviceId e cada metricName no deviceId, pode configurar de 0 a 5 dimensões para GROUP BY. Apenas os eventos com os valores de filtro correspondentes são agrupados. Uma vez agrupadas, as agregações em janelas de Min, Max, Avg, são calculadas numa janela em cascata de 60 segundos. Os filtros nos valores agregados são calculados de acordo com o limiar configurado na referência, para gerar o evento de saída do alerta.

Por exemplo, suponha que existe uma tarefa do Stream Analytics que tem uma entrada de dados de referência com o nome regras e entrada de dados de transmissão em fluxo com o nome métricas.

Dados de referência

Estes dados de referência de exemplo mostram como uma regra baseada em limiares pode ser representada. Um ficheiro JSON contém os dados de referência e é guardado no armazenamento de blobs do Azure e esse contentor de armazenamento de blobs é utilizado como uma entrada de dados de referência denominada regras. Pode substituir este ficheiro JSON e substituir a configuração da regra à medida que o tempo passa, sem parar ou iniciar a tarefa de transmissão em fluxo.

  • A regra de exemplo é utilizada para representar um alerta ajustável quando a CPU excede (a média é maior ou igual a) a percentagem do valor 90 . O value campo é configurável conforme necessário.
  • Repare que a regra tem um campo de operador , que é interpretado dinamicamente na sintaxe da consulta mais tarde em AVGGREATEROREQUAL.
  • A regra filtra os dados numa determinada chave 2 de dimensão com o valor C1. Outros campos são de cadeia vazia, indicando não filtrar o fluxo de entrada por esses campos de eventos. Pode configurar regras de CPU adicionais para filtrar outros campos correspondentes, conforme necessário.
  • Nem todas as colunas devem ser incluídas no evento de alerta de saída. Neste caso, includedDim o número 2 de chave é ativado TRUE para representar esse número de campo 2 dos dados de eventos no fluxo serão incluídos nos eventos de saída elegíveis. Os outros campos não estão incluídos na saída do alerta, mas a lista de campos pode ser ajustada.
{
    "ruleId": 1234, 
    "deviceId" : "978648", 
    "metricName": "CPU", 
    "alertName": "hot node AVG CPU over 90",
    "operator" : "AVGGREATEROREQUAL",
    "value": 90, 
    "includeDim": {
        "0": "FALSE", 
        "1": "FALSE", 
        "2": "TRUE", 
        "3": "FALSE", 
        "4": "FALSE"
    },
    "filter": {
        "0": "", 
        "1": "",
        "2": "C1", 
        "3": "", 
        "4": ""
    }    
}

Exemplo de consulta de transmissão em fluxo

Este exemplo de consulta do Stream Analytics associa os dados de referência de regras do exemplo acima a um fluxo de entrada de dados com o nome métricas.

WITH transformedInput AS
(
    SELECT
        dim0 = CASE rules.includeDim.[0] WHEN 'TRUE' THEN metrics.custom.dimensions.[0].value ELSE NULL END,
        dim1 = CASE rules.includeDim.[1] WHEN 'TRUE' THEN metrics.custom.dimensions.[1].value ELSE NULL END,
        dim2 = CASE rules.includeDim.[2] WHEN 'TRUE' THEN metrics.custom.dimensions.[2].value ELSE NULL END,
        dim3 = CASE rules.includeDim.[3] WHEN 'TRUE' THEN metrics.custom.dimensions.[3].value ELSE NULL END,
        dim4 = CASE rules.includeDim.[4] WHEN 'TRUE' THEN metrics.custom.dimensions.[4].value ELSE NULL END,
        metric = metrics.metric.value,
        metricName = metrics.metric.name,
        deviceId = rules.deviceId, 
        ruleId = rules.ruleId, 
        alertName = rules.alertName,
        ruleOperator = rules.operator, 
        ruleValue = rules.value
    FROM 
        metrics
        timestamp by eventTime
    JOIN 
        rules
        ON metrics.deviceId = rules.deviceId AND metrics.metric.name = rules.metricName
    WHERE
        (rules.filter.[0] = '' OR metrics.custom.filters.[0].value = rules.filter.[0]) AND 
        (rules.filter.[1] = '' OR metrics.custom.filters.[1].value = rules.filter.[1]) AND
        (rules.filter.[2] = '' OR metrics.custom.filters.[2].value = rules.filter.[2]) AND
        (rules.filter.[3] = '' OR metrics.custom.filters.[3].value = rules.filter.[3]) AND
        (rules.filter.[4] = '' OR metrics.custom.filters.[4].value = rules.filter.[4])
)

SELECT
    System.Timestamp as time, 
    transformedInput.deviceId as deviceId,
    transformedInput.ruleId as ruleId,
    transformedInput.metricName as metric,
    transformedInput.alertName as alert,
    AVG(metric) as avg,
    MIN(metric) as min, 
    MAX(metric) as max, 
    dim0, dim1, dim2, dim3, dim4
FROM
    transformedInput
GROUP BY
    transformedInput.deviceId,
    transformedInput.ruleId,
    transformedInput.metricName,
    transformedInput.alertName,
    dim0, dim1, dim2, dim3, dim4,
    ruleOperator, 
    ruleValue, 
    TumblingWindow(second, 60)
HAVING
    (
        (ruleOperator = 'AVGGREATEROREQUAL' AND avg(metric) >= ruleValue) OR
        (ruleOperator = 'AVGEQUALORLESS' AND avg(metric) <= ruleValue) 
    )

Dados de eventos de entrada de transmissão em fluxo de exemplo

Estes dados JSON de exemplo representam os dados de entrada de métricas que são utilizados na consulta de transmissão em fluxo acima.

  • Três eventos de exemplo são listados no intervalo de tempo de 1 minuto, valor T14:50.
  • Os três têm o mesmo deviceId valor 978648.
  • Os valores das métricas da CPU variam em cada evento, 98, 95, 80 respetivamente. Apenas os dois primeiros eventos de exemplo excedem a regra de alerta da CPU estabelecida na regra.
  • O campo includeDim na regra de alerta era a chave número 2. O campo chave 2 correspondente nos eventos de exemplo tem o nome NodeName. Os três eventos de exemplo têm valores N024, N024e N014 respetivamente. No resultado, verá apenas o nó N024 , uma vez que são os únicos dados que correspondem aos critérios de alerta da CPU elevada. N014 não cumpre o limiar de CPU elevado.
  • A regra de alerta é configurada com apenas um filter número de chave 2, que corresponde ao cluster campo nos eventos de exemplo. Todos os três eventos de exemplo têm valor C1 e correspondem aos critérios de filtro.
{
    "eventTime": "2018-04-30T14:50:23.1324132Z",
    "deviceId": "978648",
    "custom": {
        "dimensions": {
            "0": {
                "name": "NodeType",
                "value": "N1"
            },
            "1": {
                "name": "Cluster",
                "value": "C1"
            },
            "2": {
                "name": "NodeName",
                "value": "N024"
            }
        },
        "filters": {
            "0": {
                "name": "application",
                "value": "A1"
            },
            "1": {
                "name": "deviceType",
                "value": "T1"
            },
            "2": {
                "name": "cluster",
                "value": "C1"
            },
            "3": {
                "name": "nodeType",
                "value": "N1"
            }
        }
    },
    "metric": {
        "name": "CPU",
        "value": 98,
        "count": 1.0,
        "min": 98,
        "max": 98,
        "stdDev": 0.0
    }
}
{
    "eventTime": "2018-04-30T14:50:24.1324138Z",
    "deviceId": "978648",
    "custom": {
        "dimensions": {
            "0": {
                "name": "NodeType",
                "value": "N2"
            },
            "1": {
                "name": "Cluster",
                "value": "C1"
            },
            "2": {
                "name": "NodeName",
                "value": "N024"
            }
        },
        "filters": {
            "0": {
                "name": "application",
                "value": "A1"
            },
            "1": {
                "name": "deviceType",
                "value": "T1"
            },
            "2": {
                "name": "cluster",
                "value": "C1"
            },
            "3": {
                "name": "nodeType",
                "value": "N2"
            }
        }
    },
    "metric": {
        "name": "CPU",
        "value": 95,
        "count": 1,
        "min": 95,
        "max": 95,
        "stdDev": 0
    }
}
{
    "eventTime": "2018-04-30T14:50:37.1324130Z",
    "deviceId": "978648",
    "custom": {
        "dimensions": {
            "0": {
                "name": "NodeType",
                "value": "N3"
            },
            "1": {
                "name": "Cluster",
                "value": "C1 "
            },
            "2": {
                "name": "NodeName",
                "value": "N014"
            }
        },
        "filters": {
            "0": {
                "name": "application",
                "value": "A1"
            },
            "1": {
                "name": "deviceType",
                "value": "T1"
            },
            "2": {
                "name": "cluster",
                "value": "C1"
            },
            "3": {
                "name": "nodeType",
                "value": "N3"
            }
        }
    },
    "metric": {
        "name": "CPU",
        "value": 80,
        "count": 1,
        "min": 80,
        "max": 80,
        "stdDev": 0
    }
}

Saída de exemplo

Estes dados JSON de saída de exemplo mostram que um único evento de alerta foi produzido com base na regra de limiar da CPU definida nos dados de referência. O evento de saída contém o nome do alerta, bem como a agregação (média, mínimo, máx. dos campos considerados. Os dados do evento de saída incluem o valor N024 número 2 NodeName da chave de campo devido à configuração da regra. (O JSON foi alterado para mostrar quebras de linha para legibilidade.)

{"time":"2018-05-01T02:03:00.0000000Z","deviceid":"978648","ruleid":1234,"metric":"CPU",
"alert":"hot node AVG CPU over 90","avg":96.5,"min":95.0,"max":98.0,
"dim0":null,"dim1":null,"dim2":"N024","dim3":null,"dim4":null}