No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

176 líneas
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')