flaskを使ってみる その7


こちらでモニタリングツールをWEBで表示する方法を紹介しました。
また、こちらでグラフをWEBで表示する方法を紹介しました。
そこで、モニタリングツールとグラフ表示を合体してみます。
但し、時々エラーとなりますので、参考程度に見てください。

最初はこちらの表示とほぼ同じです。


データが10件以上になるとヘッダーにアンカーを表示します。


アンカーをクリックするとその値をグラフで表示します。
最初は前回のグラフがなぜか表示されます。原因不明です。






<pythonコード>
#!/usr/bin/env python
#-*- encoding: utf-8 -*-
import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import commands
import os.path
import datetime
import time
import platform
from flask import Flask, render_template, request
app = Flask(__name__)


ITEMC = 0
ITEMS = {
  0 : {'time' : '', 'cpu' : 0, 'item1' : 0 , 'item2' : 0,  'item3' : 0, 'item4' : 0, 'item5' : 0, 'item6' : 0, 'item7' : 0, 'temp1' : 0, 'temp2' : 0},
  1 : {'time' : '', 'cpu' : 0, 'item1' : 0 , 'item2' : 0,  'item3' : 0, 'item4' : 0, 'item5' : 0, 'item6' : 0, 'item7' : 0, 'temp1' : 0, 'temp2' : 0},
  2 : {'time' : '', 'cpu' : 0, 'item1' : 0 , 'item2' : 0,  'item3' : 0, 'item4' : 0, 'item5' : 0, 'item6' : 0, 'item7' : 0, 'temp1' : 0, 'temp2' : 0},
  3 : {'time' : '', 'cpu' : 0, 'item1' : 0 , 'item2' : 0,  'item3' : 0, 'item4' : 0, 'item5' : 0, 'item6' : 0, 'item7' : 0, 'temp1' : 0, 'temp2' : 0},
  4 : {'time' : '', 'cpu' : 0, 'item1' : 0 , 'item2' : 0,  'item3' : 0, 'item4' : 0, 'item5' : 0, 'item6' : 0, 'item7' : 0, 'temp1' : 0, 'temp2' : 0},
  5 : {'time' : '', 'cpu' : 0, 'item1' : 0 , 'item2' : 0,  'item3' : 0, 'item4' : 0, 'item5' : 0, 'item6' : 0, 'item7' : 0, 'temp1' : 0, 'temp2' : 0},
  6 : {'time' : '', 'cpu' : 0, 'item1' : 0 , 'item2' : 0,  'item3' : 0, 'item4' : 0, 'item5' : 0, 'item6' : 0, 'item7' : 0, 'temp1' : 0, 'temp2' : 0},
  7 : {'time' : '', 'cpu' : 0, 'item1' : 0 , 'item2' : 0,  'item3' : 0, 'item4' : 0, 'item5' : 0, 'item6' : 0, 'item7' : 0, 'temp1' : 0, 'temp2' : 0},
  8 : {'time' : '', 'cpu' : 0, 'item1' : 0 , 'item2' : 0,  'item3' : 0, 'item4' : 0, 'item5' : 0, 'item6' : 0, 'item7' : 0, 'temp1' : 0, 'temp2' : 0},
  9 : {'time' : '', 'cpu' : 0, 'item1' : 0 , 'item2' : 0,  'item3' : 0, 'item4' : 0, 'item5' : 0, 'item6' : 0, 'item7' : 0, 'temp1' : 0, 'temp2' : 0}
   }

def addItem(time,cpu,item1,item2,item3,item4,item5,item6,item7,temp1,temp2):
  global ITEMC
#  print "ITEMC:" + str(ITEMC)
  if ITEMC == len(ITEMS):
    shiftItem()
    ITEMC = ITEMC-1
  ITEMS[ITEMC]['time'] = time
  ITEMS[ITEMC]['cpu'] = cpu
  ITEMS[ITEMC]['item1'] = item1
  ITEMS[ITEMC]['item2'] = item2
  ITEMS[ITEMC]['item3'] = item3
  ITEMS[ITEMC]['item4'] = item4
  ITEMS[ITEMC]['item5'] = item5
  ITEMS[ITEMC]['item6'] = item6
  ITEMS[ITEMC]['item7'] = item7
  ITEMS[ITEMC]['temp1'] = temp1
  ITEMS[ITEMC]['temp2'] = temp2
  ITEMC = ITEMC + 1

  for i in ITEMS:
#    print "i=" + str(i),
    print ITEMS[i]['time'],
    print ITEMS[i]['cpu'],
    print ITEMS[i]['item1'],
    print ITEMS[i]['item2'],
    print ITEMS[i]['item3'],
    print ITEMS[i]['item4'],
    print ITEMS[i]['item5'],
    print ITEMS[i]['item6'],
    print ITEMS[i]['item7'],
    print ITEMS[i]['temp1'],
    print ITEMS[i]['temp2'],
    print


def shiftItem():
  for i in range(len(ITEMS)-1):
    ITEMS[i]['time'] = ITEMS[i+1]['time']
    ITEMS[i]['cpu'] = ITEMS[i+1]['cpu']
    ITEMS[i]['item1'] = ITEMS[i+1]['item1']
    ITEMS[i]['item2'] = ITEMS[i+1]['item2']
    ITEMS[i]['item3'] = ITEMS[i+1]['item3']
    ITEMS[i]['item4'] = ITEMS[i+1]['item4']
    ITEMS[i]['item5'] = ITEMS[i+1]['item5']
    ITEMS[i]['item6'] = ITEMS[i+1]['item6']
    ITEMS[i]['item7'] = ITEMS[i+1]['item7']
    ITEMS[i]['temp1'] = ITEMS[i+1]['temp1']
    ITEMS[i]['temp2'] = ITEMS[i+1]['temp2']

def ProcessStats():
  global LoadAvg
  global CpuFreq
  global SocTemp
  global PMICTemp
  global CPULoad
  global SystemLoad
  global UserLoad
  global NiceLoad
  global IOWaitLoad
  global IrqCombinedLoad

  LoadAvg = commands.getoutput("cut -f1 -d ' ' </proc/loadavg")
  CpuFreq = commands.getoutput("awk '{printf (\"%0.0f\",$1/1000); }' </sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq")

  Sensors="/etc/armbianmonitor/datasources/"
  SocTemp = 0
  path=Sensors + "soctemp"
  if os.path.isfile(path):
    SocTemp = commands.getoutput("cat " + path)
  PMICTemp = 0
  path=Sensors + "pmictemp"
  if os.path.isfile(path):
    PMICTemp = commands.getoutput("awk '{printf (\"%0.1f\",$1/1000); }' <" + path)

  CpuStat= commands.getoutput ("awk -F\" \" '{print$1\"\t\"$2\"\t\"$3\"\t\"$4\"\t\"$5\"\t\"$6}' </tmp/cpustat")
  list = CpuStat.split()
  CPULoad=list[0]
  SystemLoad=list[1]
  UserLoad=list[2]
  NiceLoad=list[3]
  IOWaitLoad=list[4]
  IrqCombinedLoad=list[5]    

def display():
  ProcessStats()
  d = datetime.datetime.today()
  time = '{0:02d}:{1:02d}:{2:02d}'.format(d.hour, d.minute, d.second)

#  print time,
  cpu = int(CpuFreq)
#  print cpu + 'MHz',
  item1 = float(LoadAvg)
#  print item1,
  item2 = int(CPULoad)
#  print item2,
  item3 = int(SystemLoad)
#  print item3,
  item4 =  int(UserLoad)
#  print item4,
  item5 =  int(NiceLoad)
#  print item5,
  item6 =  int(IOWaitLoad)
#  print item6,
  item7 =  int(IrqCombinedLoad)
#  print item7,
  temp1=0
  if SocTemp > 0:
    temp1 = int(SocTemp)
#    print temp1,
  temp2=0
  if PMICTemp > 0:
    temp2 = int(MPICTTemp)
#    print temp2,
#  print
 
  addItem(time,cpu,item1,item2,item3,item4,item5,item6,item7,temp1,temp2)

@app.route("/")
def main():
   display()

   templateData = {
      'items' : ITEMS
   }

#   print "ITEMC:" + str(ITEMC)
   if ITEMC == len(ITEMS):
     return render_template('monitor5B.html', **templateData)
   else:
     return render_template('monitor5A.html', **templateData)

@app.route("/cpu")
def cpu():
   print "action cpu"
   display()
   sns.set(font="serif")
   df = pd.DataFrame(ITEMS)
   print "df:"
   print df
   data = df.T
   print "data:"
   print data

   ax = sns.pointplot(
    x='time',       # x軸
    y='cpu',        # y軸
    data=data,      # DataFrameを指定
    markers=[''])   # dataをplotするマーカーを非表示に

   # x軸は時刻(hh:mm:ss)
   xlabels = [datetime
    for datetime in data.time]
   print xlabels

   # x軸ラベルを設定&ラベル表示を45度回転
   ax.set_xticklabels(xlabels, rotation=45)
   ax.set(ylabel='CPU Freq')

   plt.savefig("static/graph.png",dpi=70)
   plt.close()

   templateData = {
      'title' : 'CPU',
      'filename' : 'graph.png'
   }

   return render_template('graph.html', **templateData)

@app.route("/load")
def load():
   print "action load"
   display()
   sns.set(font="serif")
   df = pd.DataFrame(ITEMS)
   print "df:"
   print df
   data = df.T
   print "data:"
   print data

   ax = sns.pointplot(
    x='time',       # x軸
    y='item1',      # y軸
    data=data,      # DataFrameを指定
    markers=[''])   # dataをplotするマーカーを非表示に

   # x軸は時刻(hh:mm:ss)
   xlabels = [datetime
    for datetime in data.time]
   print xlabels

   # x軸ラベルを設定&ラベル表示を45度回転
   ax.set_xticklabels(xlabels, rotation=45)
   ax.set(ylabel='CPU Load')

   plt.savefig("static/graph.png",dpi=70)
   plt.close()

   templateData = {
      'title' : 'load',
      'filename' : 'graph.png'
   }

   return render_template('graph.html', **templateData)


@app.route("/cpu_temp")
def cpu_temp():
   print "action cpu_temp"
   display()
   sns.set(font="serif")
   df = pd.DataFrame(ITEMS)
   print "df:"
   print df
   data = df.T
   print "data:"
   print data

   ax = sns.pointplot(
    x='time',       # x軸
    y='temp1',      # y軸
    data=data,      # DataFrameを指定
    markers=[''])   # dataをplotするマーカーを非表示に

   # x軸は時刻(hh:mm:ss)
   xlabels = [datetime
    for datetime in data.time]
   print xlabels

   # x軸ラベルを設定&ラベル表示を45度回転
   ax.set_xticklabels(xlabels, rotation=45)
   ax.set(ylabel='CPU Temp')

   plt.savefig("static/graph.png",dpi=70)
   plt.close()

   templateData = {
      'title' : 'load',
      'filename' : 'graph.png'
   }

   return render_template('graph.html', **templateData)


if __name__ == "__main__":
   app.run(host='0.0.0.0', port=80, debug=True)

<テンプレートファイル monitor5A.html>
<!DOCTYPE html>
<head>
   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
   <meta http-equiv="refresh" content="5;url="/">
   <link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='style.css') }}"/>

   <title>Current Status</title>
</head>

 <body>
   <h1>CPU Frequency and Status</h1>

   <table border="1" cellpadding="2" cellspacing="2">
   <tbody>
   <tr>
   <th valign="top">Time</th>
   <th valign="top">CPU</th>
   <th valign="top">load</th>
   <th valign="top">%cpu</th>
   <th valign="top">%sys</th>
   <th valign="top">%usr</th>
   <th valign="top">%nice</th>
   <th valign="top">%io</th>
   <th valign="top">%irq</th>
   <th valign="top">CPU</th>
   <th valign="top">PMIC</th>
   </tr>


{% for i in items %}
   <tr>
   <td>{{ items[i].time }}</td>
{% if items[i].cpu == 0 %}
   <td><br></td>
   <td><br></td>
   <td><br></td>
   <td><br></td>
   <td><br></td>
   <td><br></td>
   <td><br></td>
   <td><br></td>
{% else %}
   <td>{{ items[i].cpu }}MHz</td>
   <td>{{ items[i].item1 }}</td>
   <td>{{ items[i].item2 }}%</td>
   <td>{{ items[i].item3 }}%</td>
   <td>{{ items[i].item4 }}%</td>
   <td>{{ items[i].item5 }}%</td>
   <td>{{ items[i].item6 }}%</td>
   <td>{{ items[i].item7 }}%</td>
{% endif %}
{% if items[i].temp1 == 0 %}
   <td><br></td>
{% else %}
   <td>{{ items[i].temp1 }}℃</td>
{% endif %}


{% if items[i].temp2 == 0 %}
   <td><br></td>
{% else %}
   <td>{{ items[i].temp2 }}℃</td>
{% endif %}

{% endfor %}
   </tbody>
   </table>

</body>
</html>

<テンプレートファイル monitor5B.html>
<!DOCTYPE html>
<head>
   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
   <meta http-equiv="refresh" content="5;url="/">
   <title>Current Status</title>
</head>

<body>
   <h1>CPU Frequency and Status</h1>

   <table border="1" cellpadding="2" cellspacing="2">
   <tbody>
   <tr>
   <th valign="top">Time</th>
   <th valign="top"><a href="/cpu">CPU</a></th>
   <th valign="top"><a href="/load">load</a></th>
   <th valign="top">%cpu</th>
   <th valign="top">%sys</th>
   <th valign="top">%usr</th>
   <th valign="top">%nice</th>
   <th valign="top">%io</th>
   <th valign="top">%irq</th>
   <th valign="top"><a href="/cpu_temp">CPU</a></th>
   <th valign="top">PMIC</th>
   </tr>


{% for i in items %}
   <tr>
   <td>{{ items[i].time }}</td>
   <td>{{ items[i].cpu }}MHz</td>
   <td>{{ items[i].item1 }}</td>
   <td>{{ items[i].item2 }}%</td>
   <td>{{ items[i].item3 }}%</td>
   <td>{{ items[i].item4 }}%</td>
   <td>{{ items[i].item5 }}%</td>
   <td>{{ items[i].item6 }}%</td>
   <td>{{ items[i].item7 }}%</td>
{% if items[i].temp1 == 0 %}
   <td><br></td>
{% else %}
   <td>{{ items[i].temp1 }}℃</td>
{% endif %}


{% if items[i].temp2 == 0 %}
   <td><br></td>
{% else %}
   <td>{{ items[i].temp2 }}℃</td>
{% endif %}

{% endfor %}
   </tbody>
   </table>

</body>
</html>

<テンプレートファイル graph.html>
<!DOCTYPE html>
<head>
   <meta http-equiv="Pragma" content="no-cache">
   <meta http-equiv="Cache-Control" content="no-cache">
   <meta http-equiv="refresh" content="5;url="/">
   <title>{{ title }}</title>
   <link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='style.css') }}"/>
</head>

<body>
   <img src="{{url_for('static', filename='graph.png')}}" alt="box-in-icon.png"/>
</body>
</html>

次回はflaskとよく似たフレームワークのbottleを紹介します。