Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

172 Zeilen
5.6KB

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