Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

176 linhas
6.0KB

  1. import datetime
  2. import os
  3. import time
  4. import requests
  5. import logging
  6. from flask import request, send_from_directory, json
  7. from flask_classy import FlaskView, route
  8. from modules import cbpi
  9. class LogView(FlaskView):
  10. def __init__(self):
  11. self.logger = logging.getLogger(__name__)
  12. @route('/', methods=['GET'])
  13. def get_all_logfiles(self):
  14. result = []
  15. for filename in os.listdir("./logs"):
  16. if filename.endswith(".log"):
  17. result.append(filename)
  18. return json.dumps(result)
  19. @route('/actions')
  20. def actions(self):
  21. filename = "./logs/action.log"
  22. if not os.path.isfile(filename):
  23. self.logger.warn("File does not exist [%s]", filename)
  24. return json.dumps([])
  25. import csv
  26. array = []
  27. with open(filename, 'rb') as f:
  28. reader = csv.reader(f)
  29. for row in reader:
  30. try:
  31. time.mktime(time.strptime(row[0], "%Y-%m-%d %H:%M:%S"))
  32. array.append([int(time.mktime(time.strptime(row[0], "%Y-%m-%d %H:%M:%S")) * 1000), row[1]])
  33. except:
  34. pass
  35. json_dumps = json.dumps(array)
  36. self.logger.debug("Loaded action.log [%s]", json_dumps)
  37. return json_dumps
  38. @route('/<file>', methods=["DELETE"])
  39. def clearlog(self, file):
  40. """
  41. Overload delete method to shutdown sensor before delete
  42. :param id: sensor id
  43. :return: HTTP 204
  44. """
  45. if not self.check_filename(file):
  46. return ('File Not Found', 404)
  47. filename = "./logs/%s" % file
  48. if os.path.isfile(filename) == True:
  49. os.remove(filename)
  50. cbpi.notify("log deleted succesfully", "")
  51. else:
  52. cbpi.notify("Failed to delete log", "", type="danger")
  53. return ('', 204)
  54. def query_tsdb(self, type, id):
  55. kairosdb_server = "http://127.0.0.1:" + cbpi.cache["config"]["kairos_db_port"].__dict__["value"]
  56. data = dict(metrics=[
  57. {
  58. "tags": {},
  59. "name": "cbpi.%s_%s" % (type, id),
  60. "aggregators": [
  61. {
  62. "name": "avg",
  63. "align_sampling": True,
  64. "sampling": {
  65. "value": "5",
  66. "unit": "seconds"
  67. },
  68. "align_start_time": True
  69. }
  70. ]
  71. }
  72. ],
  73. cache_time=0,
  74. start_relative={
  75. "value": "1",
  76. "unit": "days"
  77. })
  78. if cbpi.cache["active_brew"] != "none":
  79. data["metrics"][0]["tags"] = {"brew": [cbpi.cache["active_brew"]]}
  80. self.logger.debug("query: %s", json.dumps(data))
  81. response = requests.post(kairosdb_server + "/api/v1/datapoints/query", json.dumps(data))
  82. if response.ok:
  83. self.logger.debug("Fetching time series for [%s_%s] took [%s]", type, id, response.elapsed)
  84. self.logger.debug("Time series for [%s_%s] is [%s]", type, id, response.json())
  85. return response.json()["queries"][0]["results"][0]["values"]
  86. else:
  87. self.logger.warning("Failed to fetch time series for [%s_%s]. Response [%s]", type, id, response)
  88. def querry_log(self, type, id):
  89. filename = "./logs/%s_%s.log" % (type, id)
  90. if os.path.isfile(filename) == False:
  91. return
  92. import csv
  93. array = []
  94. with open(filename, 'rb') as f:
  95. reader = csv.reader(f)
  96. for row in reader:
  97. try:
  98. array.append([int((datetime.datetime.strptime(row[0], "%Y-%m-%d %H:%M:%S") - datetime.datetime(1970,
  99. 1,
  100. 1)).total_seconds()) * 1000,
  101. float(row[1])])
  102. except:
  103. pass
  104. return array
  105. def read_log_as_json(self, type, id):
  106. use_kairosdb = (cbpi.cache["config"]["kairos_db"].__dict__["value"] == "YES")
  107. if use_kairosdb:
  108. return self.querry_tsdb(type, id)
  109. return self.query_tsdb(type, id)
  110. else:
  111. return self.querry_log(type, id)
  112. def convert_chart_data_to_json(self, chart_data):
  113. return {"name": chart_data["name"],
  114. "data": self.read_log_as_json(chart_data["data_type"], chart_data["data_id"])}
  115. @route('/<t>/<int:id>', methods=["POST"])
  116. def get_logs_as_json(self, t, id):
  117. data = request.json
  118. result = []
  119. if t == "s":
  120. name = cbpi.cache.get("sensors").get(id).name
  121. result.append({"name": name, "data": self.read_log_as_json("sensor", id)})
  122. if t == "k":
  123. kettle = cbpi.cache.get("kettle").get(id)
  124. result = map(self.convert_chart_data_to_json, cbpi.get_controller(kettle.logic).get("class").chart(kettle))
  125. if t == "f":
  126. fermenter = cbpi.cache.get("fermenter").get(id)
  127. result = map(self.convert_chart_data_to_json,
  128. cbpi.get_fermentation_controller(fermenter.logic).get("class").chart(fermenter))
  129. return json.dumps(result)
  130. @route('/download/<file>')
  131. @cbpi.nocache
  132. def download(self, file):
  133. if not self.check_filename(file):
  134. return ('File Not Found', 404)
  135. return send_from_directory('../logs', file, as_attachment=True, attachment_filename=file)
  136. def check_filename(self, name):
  137. import re
  138. pattern = re.compile('^([A-Za-z0-9-_])+.log$')
  139. return True if pattern.match(name) else False
  140. @cbpi.initalizer()
  141. def init(app):
  142. """
  143. Initializer for the message module
  144. :param app: the flask app
  145. :return: None
  146. """
  147. LogView.register(cbpi.app, route_base='/api/logs')