Como obter status das Functions que pertencem às Function Apps do Azure e enviar os status para o Zabbix
Published: 2023-08-14 23:05:44

Para funcionamento é necessário estar logado no Azure autorizando o dispositivo onde estão os arquivos de monitoramento com um usuário que tenha permissões para verificar status das functions no Azure.

```
az login --use-device-code
```
Abaixo instruções de realização do login pelo Azure CLI.
[](https://learn.microsoft.com/en-us/cli/azure/authenticate-azure-cli)

```
Pré-requisitos

Az cli

Python 3.6 ou superior

Zabbix Sender (necessário para envio das informações ao zabbix usando agendamento de execução pelo sistema operacional)

```

1 - Criar no diretório home do seu usuário o diretório statusfuncapp e dentro dele o diretório logstatus:

`mkdir -p statusfuncapp/{logstatus}`

O diretório logstatus apenas irá gravar um arquivo texto de log do status atual de cada function verificada.



2 - Criar no diretório statusfuncapp o arquivo listfunctionapp.json que conterá as informações sobre as functions app e function a serem monitoradas. Digite no terminal conforme abaixo:

`nano listfunctionapp.json`

**Observações:**
Abaixo uma explicação sobre cada um dos campos do arquivo json a seguir:
**subscriptionId** — Id da Subscription no azure que a function app pertence

**resourcegroup** — Nome do Resource Group no azure que a function app pertence

**functionapp** — Nome da Function App

**function** — Nome da Function

**zabbixkey** — Nome único para cada function a ser criado como chave no zabbix (zabbix key)

Abaixo o conteúdo do arquivo:

```
{
    "azurefunction": [
        {
            "subscriptionId": "xxxxxxx-yyyy-zzzz-wwww-kkkkkkkkkkkk",
            "resourcegroup": "RGTesteFunc",
            "functionapp": "namefunctionapp1",
            "function": "namefunction1",
            "zabbixkey": "key.nomefunctionapp1.function"
        },
        {
            "subscriptionId": "xxxxxxx-yyyy-zzzz-wwww-kkkkkkkkkkkk",
            "resourcegroup": "RGTesteFunc",
            "functionapp": "namefunctionapp2",
            "function": "namefunction2",
            "zabbixkey": "key.nomefunctionapp2.function"
        }
    ]
}
```
Podem ser adicionadas várias functions a serem monitoradas, apenas seguir esse estrutura acima do json.



3 - Criar no diretório statusfuncapp o arquivo vfuncapp.py que conterá o script python com a instruções de obter as informações das functions conforme existentes no arquivo listfunctionapp.json.

```
import json
import os
import io
import sys
import csv
import socket
from datetime import datetime
 
### Funcao de limpeza do log
def limpaLog():
    pathLog = r"/home/user/statusfuncapp/logfunctionapp.log"
     
    ### cria/escreve arquivo de log MongoDB
    with io.open(pathLog, 'w', encoding='utf-8') as f:
      f.write(str(''))
 
 
### Funcao de gravacao do log
def gravaLog(msglog):
    pathLog = r"/home/user/statusfuncapp/logfunctionapp.log"
    datahora = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
     
    ### cria/escreve arquivo de log MongoDB
    with io.open(pathLog, 'a', encoding='utf-8') as f:
      f.write(str('\n=====================================\n'))
      f.write(str(datahora + '\n' + msglog))
 
 
### Funcao de leitura do arquivo json com as informacoes das functions
def readJson():
     
    ### variaveis
    msg = ''  
    pathJsonFunction = r'/home/user/statusfuncapp/listfunctionapp.json'
    i = 0
     
    ### chamada da funcao de limpeza do log file
    limpaLog()
     
    ### codigo de leitura do json com as functions
    ### nesse trecho ocorre o processamento dos dados
    with open(pathJsonFunction) as file:
         data = json.load(file)
 
         for functions in data["azurefunction"]:
            v_subscription = str(data["azurefunction"][i]["subscriptionId"])
            v_resourcegroup = str(data["azurefunction"][i]["resourcegroup"])
            v_functionappname = str(data["azurefunction"][i]["functionapp"])
            v_functionname = str(data["azurefunction"][i]["function"])
            v_keyzabbix = str(data["azurefunction"][i]["zabbixkey"])
            #print(f"{v_functionappname} - {v_functionname}")
             
             
            try:
              ## Monta o comando de execucao via az cli
              cmd = 'az functionapp function show --subscription ' + v_subscription + ' -g ' + v_resourcegroup + ' -n ' + v_functionappname + ' --function-name ' + v_functionname
 
              ## Executa e pega o retorno em formato json
              retorno = os.popen(cmd).read()
              #print(retorno)
 
              ## Monta dicionario do json e exibe somente o valor requerido
              data_dict = json.loads(retorno)
              statusFunction = str(data_dict["isDisabled"])
              #print(data_dict["isDisabled"])
 
              ### Verifica os status da function
              ### conforme o retorno do campo isDisabled
              if(statusFunction == 'True'):
                statusAux = 'Disable'
              elif (statusFunction == 'False'):
                statusAux = 'Enabled'
              else:
                statusAux = 'Desconhecido'
 
            except:
              msg = msg + f'Erro functionApp: {v_functionappname} - function name: {v_functionname}\n'
              statusAux = 'Error'
 
            #msg = f'FunctionApp : {v_functionApp}, FunctionName : {v_functionName} ,Status : {statusAux}'
            strcsvAux = f'{v_functionappname},{v_functionname},{statusAux},{v_keyzabbix}'
            #print(strcsvAux)
             
            msg = msg + strcsvAux + '\n'
             
            ### chamada das funcoes de gravacao status e envio ao zabbix server
            gravaStatusFunction(v_functionappname, statusAux)
            zabbixSenderStatus(v_keyzabbix, statusAux)
 
            i = i + 1
     
    gravaLog(msg)
    #print(msg)
 
 
### Funcao de gravacao do status das functions
def gravaStatusFunction(functionApp, fstatus):
     
    ### variaveis do local de gravacao dos status
    strResult = r"/home/user/statusfuncapp/logstatus"
    strResult = os.path.join(strResult, functionApp + '.txt')
    pathCsvResult = strResult
 
    with open(pathCsvResult, 'w', encoding='utf-8') as csvf:
        csvf.write(fstatus)
 
 
### Funcao de envio das informacoes de status das functions via zabbix_sender
def zabbixSenderStatus(zbxChave, zbxStatus):
 
    ### variaveis server e host monitorado   
    server = 'ip_server_zabbix'
    myhost = socket.gethostname() #nome da maquina local
     
    zbxsendercmd = f'zabbix_sender -z {server} -s {myhost} -k {zbxChave} -o {zbxStatus}'   
    retornozbx = os.popen(zbxsendercmd).read()
     
    gravaLog(zbxsendercmd + '\n' + retornozbx)
    print(zbxsendercmd)
    print(retornozbx)
     
 
### INICIO DA APLICACAO
if __name__ == "__main__":
   readJson()

```

Após a criação dos arquivos na estrutura acima é necessário criar um agendamento para execução do mesmo via cron no Linux.

Como é um script que não necessita de execução via root pode ser criado o agendamento no cron do usuário logado no Linux mesmo, abaixo um exemplo:

```
## verifica status da function na functionapp azure roda a cada 6 minutos
*/6 * * * * /usr/bin/python3 /home/user/statusfuncapp/vfuncapp.py
```

Após o procedimento é necessário criar no zabbix os itens para cada uma das functions a serem monitoradas.

Exemplo item para a function app “namefunctionapp1” e function “namefunction1” .

Nome do item no zabbix: “key.namefunctionapp1.function”