Obter Http Status Code de uma lista de Function Apps do Azure e enviar para o Zabbix
Tags: zabbix, azure, python, functionapp
Published: 2023-12-27 22:50:46

No artigo anterior postei um script que obtém o status da function que pertence a determinada function app onde exibe se a mesma está habilitada ou desabilitada [Acesse Aqui](https://dev.to/magnorsantos/como-obter-status-das-functions-que-pertencem-as-function-apps-do-azure-e-enviar-os-status-para-o-zabbix-l0c).

No artigo atual iremos obter os status http code das function apps do Azure, assim podemos saber de uma forma facilitada uma lista de functions apps e seus status.

Bom vamos lá!

```
Pré-requisitos

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 statusUrlfuncapp e dentro dele os diretórios logstatus e loghistorico:
`mkdir -p statusUrlfuncapp/{logstatus,loghistorico}`

O diretório logstatus apenas irá gravar um arquivo texto de log do status atual de cada function verificada.
O diretório loghistorico irá receber o log diário dos status obtidos e adicionar mais informações de log em execuções posteriores no mesmo dia.

2 - Criar no diretório statusUrlfuncapp o arquivo listfunctionapp.json que conterá as informações sobre as functions apps 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:

**functionapp** — Nome da Function App

**urlfunctionapp** - Url da Function App

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

Abaixo o conteúdo do arquivo:

```
{
    "azurefunction": [
        {
            "functionapp": "namefunctionapp1",
            "urlfunctionapp": "https://namefunctionapp1.azurewebsites.net",
            "zabbixkeyurl": "key.url.namefunctionapp1.function"
        },
        {
            "functionapp": "namefunctionapp2",
            "urlfunctionapp": "https://namefunctionapp2.azurewebsites.net",
            "zabbixkeyurl": "key.url.namefunctionapp2.function"
        }
    ]
}
```

Podem ser adicionadas várias functions apps a serem monitoradas, apenas seguir esse estrutura acima do json.

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

```
import json
import os
import io
#import sys
import socket
import requests
from datetime import datetime


def limpaLog():
    pathLog = r"/home/user/statusUrlfuncapp/logfunctionapp_urlstatus.log"
    
    ### cria/escreve arquivo de log
    with io.open(pathLog, 'w', encoding='utf-8') as f:
      f.write(str(''))

def gravaLog(msglog): 
    pathLog = r"/home/user/statusUrlfuncapp/logfunctionapp_urlstatus.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))


def gravaLogHistorico(msgloghist):
    dataloghist = datetime.now().strftime('%Y-%m-%d')
    pathLog = r"/home/user/statusUrlfuncapp/loghistorico/logfunctionapp_urlstatusHist_" + dataloghist + ".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' + msgloghist)) 


def removeLogHistorico():
    ### variaveis dos logs antigos a serem removidos
    pathLog = r"/home/user/statusUrlfuncapp/loghistorico"
    diasRemover = 4
    
    
    ### remove os logs acima de XX dias
    ## cmd = 'find ' + pathLog + ' -type f -mtime +' + str(diasRemover) + ' -exec rm -f -r {} +'
    cmd = 'find ' + pathLog + ' -name "*.log" -type f -mtime +' + str(diasRemover) + ' -delete'
    print(cmd)
    os.popen(cmd)

      
#somente app services worker
def verificaStatusUrlWorker(varUrl):
    p_Url = varUrl

    try: 
        x = requests.get(p_Url)
        #print(x.status_code)
        #print('\nUrl: '+ str(varUrl) + '\nStatus Code Http: ' + str(x.status_code))
        return x.status_code
    except:
        #print('\nUrl: '+ str(varUrl) + '\nOcorreu erro ao obter status da url')
        return 0


def readJson():
    
    ### variaveis
    msg = ''   
    pathJsonFunction = r'/home/user/statusUrlfuncapp/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_functionappname = str(data["azurefunction"][i]["functionapp"])
            v_urlfunctionapp = str(data["azurefunction"][i]["urlfunctionapp"])
            v_keyzabbix = str(data["azurefunction"][i]["zabbixkeyurl"])
            
            
            statusAux = str(verificaStatusUrlWorker(v_urlfunctionapp))

            #msg = f'FunctionApp : {v_functionApp}, UrlFunctionApp : {v_urlfunctionapp} , Http Status Code: {statusAux}'
            #print(f'FunctionApp: {v_functionappname}, UrlFunctionApp: {v_urlfunctionapp} , Http Status Code: {statusAux}')
            strcsvAux = f'{v_functionappname},{v_urlfunctionapp},{statusAux},{v_keyzabbix}'
            #print(strcsvAux)
            
            msg = msg + '\n' + strcsvAux + '\n'
            
            ### chamada das funcoes de gravacao status e envio ao zabbix server
            gravaStatusFunction(v_functionappname, statusAux)
            zabbixSenderStatus(v_keyzabbix, statusAux)

            #print(f"\n****{v_functionappname} - {v_urlfunctionapp} - {statusAux}\n")
            gravaLogHistorico(f"\n****{v_functionappname} - {v_urlfunctionapp} - {statusAux}\n")

            i = i + 1
    
    gravaLog(msg)



def gravaStatusFunction(functionApp, fstatus):
    
    ### variaveis do local de gravacao dos status
    strResult = r"/home/user/statusUrlfuncapp/logstatus"
    strResult = os.path.join(strResult, functionApp + '.txt')
    pathCsvResult = strResult

    with open(pathCsvResult, 'w', encoding='utf-8') as csvf: 
        csvf.write(fstatus)

def zabbixSenderStatus(zbxChave, zbxStatus):

    ### variaveis server e host monitorado    
    server = '10.10.9.2' #ip do zabbix server
    myhost = socket.gethostname()
    
    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()
   removeLogHistorico()
```

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/statusUrlfuncapp/vfuncapp_urlstatus.py
```
Após o procedimento é necessário criar no zabbix os itens para cada uma das functions apps a serem monitoradas.

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

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

Com isso no zabbix pode-se criar um Screen com o tipo de visualização de dados "Data Overview" que irá apresentar os dados em um formato de tabela e os retornos dos status url podem ser mapeados para os tipos http status code conforme esse link: [Acesse aqui](https://www.httpstatus.com.br).