0

OK so I'm doing a project on finding the Health details of a remote server using python and I'm hosting the main server using flask. But the idk how to send the Health report which I have created using python, to the flask app. The Health report is in the form of a dictionary and I need to pass the values of the dictionary into columns which are the keys of the dictionary in my database.can someone please help me in sending the Health report to the Flask app? This health report is on another system and I need to send that to my main server.

import psutil
import time
import json
import requests

'''
This program will be loaded on to the target server.
A flask app will transmit health data to the main flask app.
''' 

SERVER_NAME="test_local_server"

def getHealth():  # function for generating health report. Returns a json object.
    print('generating health report')
    report={}
    report['sever_name']=SERVER_NAME
    report['cpupercent']=psutil.cpu_percent(interval=2.0)
    report['ctime']=psutil.cpu_times()
    report['cpu_total']=report['ctime'].user+report['ctime'].system    
    report['disk_usages']=psutil.disk_usage("/")
    report['net']=psutil.net_io_counters()
    report['bytes_sent']=report['net'].bytes_sent
    report['bytes_received']=report['net'].bytes_recv
    report['packets_sent']=report['net'].packets_sent
    report['packets_received']=report['net'].packets_recv
    report['mem']=psutil.virtual_memory()
    report['memory_Free']=report['mem'].free
    json_report=json.dumps(report)
    return(json_report)

if __name__=='__main__':
    print(f'starting health report stream for server :\t{SERVER_NAME}')
    while True:
        getHealth()

This is the code for generating the Health details.How to send this back to my flask app in the form of a dictionary?

Nazim Kerimbekov
  • 4,712
  • 8
  • 34
  • 58
Mathew Pius
  • 65
  • 1
  • 7

1 Answers1

0

Client

I would start by simpifying that code somewhat:

import psutil

STATS_URL = 'http://localhost:5000/'
SERVER_NAME="test_local_server"

def get_health(): 

    print('generating health report')

    cpu_percent = psutil.cpu_percent(interval=2.0)
    cpu_times = psutil.cpu_times()
    disk_usage = psutil.disk_usage("/")
    net_io_counters = psutil.net_io_counters()
    virtual_memory = psutil.virtual_memory()    

    # The keys in this dict should match the db cols
    report = dict (
        sever_name = SERVER_NAME
        ctime = cpu_times.__str__(),
        disk_usages = disk_usage.__str__(),
        net = net_io_counters.__str__(),
        mem = virtual_memory.__str__(),

        cpupercent = cpu_percent,
        cpu_total = cpu_times.user + cpu_times.system,
        bytes_sent = net_io_counters.bytes_sent,
        bytes_received = net_io_counters.bytes_recv,
        packets_sent = net_io_counters.packets_sent,
        packets_received = net_io_counters.packets_recv,

        memory_Free = virtual_memory.free,
        )

    return report

This get_health function builds and returns a report dictionary. Notice that for some of the return values from the psutil functions, I've used the built in __str__ method. This ensures a friendly type to be inserted into the database.

If you want to check the types yourself, you can do something like:

for item in report:
    print (item, type(report[item]), report[item])

Next have this function run in a loop, with a desired time delay between requests:

if __name__=='__main__':

    import time
    import requests

    print(f'starting health report stream for server :\t{SERVER_NAME}')

    while True:
        report = get_health()
        r = requests.post(STATS_URL, json=report)
        print (r, r.json())
        time.sleep(1)

Notice this uses the json argument to request.post which automatically sets the correct Content-Type which Flask's request.get_json function expects.

Server

This is pretty easy to recieve:

from flask import Flask, request
app = Flask(__name__)

@app.route('/', methods=['POST'])
def index():
    incoming_report = request.get_json()

    add_to_db(incoming_report) # We'll build this in a sec.

    return {'message': 'success'}

You can now work with incoming_report which is a dictionary.

This also sends a success message back to the client, so on the client you'll see the ouptut:

starting health report stream for server :  test_local_server
generating health report
<Response [200]> {'message': 'success'}
# Repeats until killed

Database

and I need to pass the values of the dictionary into columns which are the keys of the dictionary in my database

Now that you have a dictionary incoming_report it should be easy to add this to your database if you're using an ORM.

Something along the lines of this answer should allow you to simply unpack that dictionary. So assuming your model is called Report you could simply do something like:

def add_to_db(d):
    report  = Report(**d)
    db.session.add(report)
    db.session.commit()

Note this could probably use some validation, and authentication if your deployment requires this.

v25
  • 7,096
  • 2
  • 20
  • 36
  • Thank you so much this helped me a lot.But also, is there another way to add the values in the dictionary into the database because i havnt used sqlalchemy. I'm using sqlite3 and merely a python connector to add values and create tables so is there another way to unpack the dictionary? – Mathew Pius Apr 05 '20 at 15:32