[PYTHON] L'histoire de la fabrication de soracom_exporter (j'ai essayé de surveiller SORACOM Air avec Prometheus)

TL; DR

introduction

Bien sûr, si vous utilisez quelque chose d'IoT avec la carte SIM de SORACOM Air, vous devez également le surveiller. Ensuite, en fonction de l'implémentation, les informations sur la santé seront envoyées à partir du système d'exploitation ou de l'application à l'intérieur de quelque chose qui est IoT. Cependant, si le NW n'est pas communiqué, de telles informations ne peuvent pas être envoyées, et il est nécessaire de surveiller du point de vue si le NW est vivant ou peut communiquer.

Donc, quand il y a un problème, il serait bon de savoir quelle est la cause de la session Air sim en tant que superposition. Très heureux. Par exemple, si la communication d'application dans l'IoT n'est pas possible mais que l'état de la session est En ligne, il semble y avoir un problème au sein du système d'exploitation ou de l'application à l'intérieur de quelque chose qui est l'IoT. Si vous utilisez Hors ligne, il y a une forte possibilité qu'il y ait un problème à l'extérieur, comme si l'appareil est à court d'électricité, l'état des ondes radio ou l'antenne n'est pas cassée.

C'est pourquoi, lorsque j'utilise Prometheus comme environnement de surveillance, je souhaite récupérer les informations Air de l'API SORACOM, les mettre dans Prometheus, les ignorer pour les relâcher ou les visualiser avec grafana.

la mise en oeuvre

--soracom_exporter.py (créé avec python, décrit plus tard)

Ainsi, par exemple, la structure de fichiers suivante.


/hoge
|-- prometheus
|   |-- prometheus(Corps binaire)
|   |-- prometheus.yml
|   |-- (divers)
|-- node_exporter(Corps binaire)
|   |-- node_exporter
|   |-- text_collector
|       |-- soracom_exporter_session_status.prom(Mis à jour à chaque fois)
|-- soracom_exporter
|   |-- soracom_exporter.py

soracom_exporter.py

soracom_exporter.py


import json
import logging
import time
import requests
logging.basicConfig(level=logging.DEBUG, format="%(asctime)-15s %(message)s")
requests_log = logging.getLogger("requests.packages.urllib3")
requests_log.setLevel(logging.DEBUG)
requests_log.propagate = True

#Pour en faire un processus résident et exécuter une minuterie
# pip install schedule
# cf. https://schedule.readthedocs.io/en/stable/
import schedule

# Prometheus Python Client
# cf. https://github.com/prometheus/client_python
from prometheus_client import CollectorRegistry, Gauge, write_to_textfile # pip install prometheus_client


class SORACOMExporter():
    def __init__(self):
        # config for api
        self.SORACOM_API_KEY_ID = "keyId-xxx"       #Changer pour le vôtre
        self.SORACOM_API_KEY_SECRET = "secret-xxx"  #Changer pour le vôtre
        self.SORACOM_URL_AUTH = "https://api.soracom.io/v1/auth"
        self.SORACOM_URL_SUBSCRIBERS = "https://api.soracom.io/v1/subscribers?limit=1000"

    def export_session_status_metrics(self):
        # api key id/Générer un jeton à partir du secret(Vous devriez vraiment l'utiliser correctement...)
        self._get_soracom_api_token()

        #Obtenez la liste des simulateurs aériens de l'API et analysez
        # cf. https://dev.soracom.io/jp/docs/api/#!/Subscriber/listSubscribers
        self.subscribers = self._get_subscribers()

        #Traitez-le en données de type métrique Prometheus et écrivez-le dans un fichier
        registry = CollectorRegistry()
        self._build_soracom_session_status_metrics(registry, self.subscribers)
        self._write_metrics(registry)

    def _build_soracom_session_status_metrics(self, registry, subscribers):
        #Ici le nom et l'étiquette des métriques/Définir une structure telle que la valeur
        soracom_session_status_gauge = Gauge(
            "soracom_session_status",  # metrics name
            "SORACOM session status",  # metrics description
            ["imsi", "name"],  # labels
            registry=registry
        )

        #Mettez les données extraites de l'API
        for subscriber in subscribers:
            metrics_value = 1.0 if subscriber["session_status"] else 0.0 #En ligne 1.0, 0 pour hors ligne.0
            soracom_session_status_gauge.labels(
                subscriber["imsi"],
                subscriber["name"]
            ).set(metrics_value)

    def _write_metrics(self, registry):
        #Ici et là, j'utilise juste ce qui est préparé comme décrit dans le README du client python de Prometheus.
        # cf. https://github.com/prometheus/client_python
        text_collector_output_path = "/hoge/node_exporter/text_collector/soracom_exporter_session_status.prom"
        write_to_textfile(text_collector_output_path, registry)
        logging.info("text metrics was written!:%s" % text_collector_output_path)

    def _get_subscribers(self):
        subscribers_json = self._get_soracom_api_json(self.SORACOM_URL_SUBSCRIBERS)

        # parse subscribers json to extract every subscribers's imsi/tag.Name/sessionStatus
        subscribers = []
        for subscriber_json in subscribers_json:
            subscribers.append({
                "imsi": subscriber_json["imsi"],
                "name": subscriber_json["tags"]["name"] if "name" in subscriber_json["tags"] else "",
                "session_status": subscriber_json["sessionStatus"]["online"] if subscriber_json[
                    "sessionStatus"] else False
            })

        return subscribers

    def _get_api_headers(self):
        api_headers = {
            "X-Soracom-API-Key": self.auth_api_key,
            "X-Soracom-Token": self.auth_token,
            "Accept": "application/json",
        }
        return api_headers

    def _get_soracom_api_token(self):
        try:
            auth_headers = {"Content-Type": "application/json"}
            auth_payload = {"authKeyId": self.SORACOM_API_KEY_ID, "authKey": self.SORACOM_API_KEY_SECRET}
            auth_response = requests.post(
                self.SORACOM_URL_AUTH,
                headers=auth_headers,
                data=json.dumps(auth_payload),
                verify=True,
                timeout=60
            )
            auth_response.raise_for_status()
        except requests.exceptions.RequestException as err:
            logging.warning(err)
        self.auth_token = auth_response.json()["token"]
        self.auth_api_key = auth_response.json()["apiKey"]

    def _get_soracom_api_json(self, soracom_api_url):
        try:
            soracom_response = requests.get(
                soracom_api_url,
                headers=self._get_api_headers(),
                verify=True,
                timeout=60
            )
            soracom_response.raise_for_status()
        except requests.exceptions.RequestException as err:
            logging.warning(err)
        return soracom_response.json()


if __name__ == "__main__":
    se = SORACOMExporter()
    schedule.every(1).minutes.do(se.export_session_status_metrics) #Courir chaque minute
    #Exportez si vous souhaitez prendre d'autres métriques_hoge_Définir des métriques et exécuter avec l'intervalle approprié
    while True:
        schedule.run_pending()
        time.sleep(1)

Le fichier de sortie ressemble à ceci

$ cat soracom_exporter_session_status.prom
# HELP soracom_session_status SORACOM session status
# TYPE soracom_session_status gauge
soracom_session_status{imsi="00000000000",name="Pour la vérification de l'entreprise"} 1.0
soracom_session_status{imsi="11111111111",name="Pour la vérification à domicile"} 0.0
...

Options de démarrage de node_exporter

node_exporter -web.listen-address ":9100" -collector.textfile.directory /hoge/node_exporter/text_collector/
#Attention à la syntaxe car la version peut être ancienne

Impressions

À partir de maintenant

―― Que pouvez-vous faire à partir de maintenant? --Notification de relâcher --Visualisation avec grafana ―― Quels autres points de terminaison pouvez-vous surveiller?

la mise en oeuvre

fin

Recommended Posts

L'histoire de la fabrication de soracom_exporter (j'ai essayé de surveiller SORACOM Air avec Prometheus)
J'ai essayé de trouver l'entropie de l'image avec python
J'ai essayé de trouver la moyenne de plusieurs colonnes avec TensorFlow
J'ai essayé d'agrandir la taille du volume logique avec LVM
J'ai essayé d'améliorer l'efficacité du travail quotidien avec Python
zoom J'ai essayé de quantifier le degré d'excitation de l'histoire lors de la conférence
J'ai essayé d'obtenir le code d'authentification de l'API Qiita avec Python.
J'ai essayé d'extraire automatiquement les mouvements des joueurs Wiire avec un logiciel
J'ai essayé d'extraire et d'illustrer l'étape de l'histoire à l'aide de COTOHA
J'ai essayé de rationaliser le rôle standard des nouveaux employés avec Python
J'ai essayé de visualiser le texte du roman "Weather Child" avec Word Cloud
J'ai essayé d'obtenir les informations sur le film de l'API TMDb avec Python
J'ai essayé l'histoire courante de l'utilisation du Deep Learning pour prédire la moyenne Nikkei
J'ai essayé de prédire le comportement du nouveau virus corona avec le modèle SEIR.
J'ai essayé de sauvegarder les données avec discorde
J'ai essayé d'automatiser la fabrication des sushis avec python
J'ai essayé de vectoriser les paroles de Hinatazaka 46!
J'ai essayé de visualiser facilement les tweets de JAWS DAYS 2017 avec Python + ELK
J'ai essayé de créer un modèle avec l'exemple d'Amazon SageMaker Autopilot
J'ai essayé d'envoyer automatiquement la littérature du nouveau virus corona à LINE avec Python
J'ai essayé d'entraîner la fonction péché avec chainer
J'ai essayé d'extraire des fonctionnalités avec SIFT d'OpenCV
J'ai essayé de résumer la forme de base de GPLVM
J'ai essayé de toucher un fichier CSV avec Python
J'ai essayé de visualiser les informations spacha de VTuber
J'ai essayé d'effacer la partie négative de Meros
J'ai essayé de résoudre le problème avec Python Vol.1
J'ai essayé de classer les voix des acteurs de la voix
J'ai essayé de résumer les opérations de chaîne de Python
J'ai essayé de faire quelque chose comme un chatbot avec le modèle Seq2Seq de TensorFlow
J'ai essayé d'automatiser la mise à jour de l'article du blog Livedoor avec Python et sélénium.
J'ai essayé de visualiser les caractéristiques des nouvelles informations sur les personnes infectées par le virus corona avec wordcloud
J'ai essayé de visualiser les données de course du jeu de course (Assetto Corsa) avec Plotly
J'ai essayé de comparer la vitesse de traitement avec dplyr de R et pandas de Python
Le 15e temps réel hors ligne, j'ai essayé de résoudre le problème de l'écriture avec python
[Courses de chevaux] J'ai essayé de quantifier la force du cheval de course
J'ai essayé la "correction gamma" de l'image avec Python + OpenCV
J'ai essayé de simuler la propagation de l'infection avec Python
J'ai essayé d'obtenir les informations de localisation du bus Odakyu
J'ai essayé de notifier les informations de retard de train avec LINE Notify
[Apprentissage automatique] J'ai essayé de résumer la théorie d'Adaboost
J'ai essayé de combattre le minimum local de la fonction Goldstein-Price
L'histoire de la création d'un bot de boîte à questions avec discord.py
J'ai essayé d'afficher les données du groupe de points DB de la préfecture de Shizuoka avec Vue + Leaflet
J'ai essayé de publier automatiquement sur ChatWork au moment du déploiement avec Fabric et ChatWork Api
J'ai essayé de réécrire le serveur WEB de la 1ère édition de programmation Linux normale avec C ++ 14
J'ai essayé de résoudre le problème de F02 comment écrire en temps réel hors ligne avec Python
J'ai essayé de visualiser la consommation électrique de ma maison avec Nature Remo E lite
J'ai essayé d'analyser les données du tournoi de football de la Coupe du monde de football en Russie avec l'action de football
J'ai écrit un doctest dans "J'ai essayé de simuler la probabilité d'un jeu de bingo avec Python"
J'ai essayé de prédire les ventes de logiciels de jeux avec VARISTA en me référant à l'article du Codexa
J'ai essayé de déplacer le ballon
J'ai essayé d'estimer la section.
J'ai essayé de décrire le trafic en temps réel avec WebSocket
J'ai essayé de résoudre l'édition du débutant du livre des fourmis avec python
[Linux] J'ai essayé de résumer les commandes de confirmation des ressources