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.

169 líneas
5.5KB

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