# -*- coding: utf-8 -*-
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
# MIT License. See license.txt

from __future__ import unicode_literals

from datetime import datetime, timezone
import json
import traceback
import frappe
import os


MONITOR_REDIS_KEY = "monitor-transactions"


def start(transaction_type="request", method=None, kwargs=None):
	if frappe.conf.monitor:
		frappe.local.monitor = Monitor(
			transaction_type=transaction_type, method=method, kwargs=kwargs
		)


def stop():
	if frappe.conf.monitor and hasattr(frappe.local, "monitor"):
		frappe.local.monitor.dump()


def log_file():
	return os.path.join(frappe.utils.get_bench_path(), "logs", "monitor.json.log")


class Monitor:
	def __init__(self, transaction_type=None, method=None, kwargs=None):
		try:
			self.site = frappe.local.site
			self.timestamp = datetime.now(timezone.utc)
			self.transaction_type = transaction_type

			if self.transaction_type == "request":
				self.data = frappe.form_dict
				self.headers = dict(frappe.request.headers)
				self.method = frappe.request.method
				self.path = frappe.request.path
			else:
				self.kwargs = kwargs
				self.method = method
		except Exception:
			traceback.print_exc()

	def dump(self):
		try:
			timediff = datetime.now(timezone.utc) - self.timestamp
			# Obtain duration in microseconds
			self.duration = int(timediff.total_seconds() * 1000000)
			data = {
				"duration": self.duration,
				"site": self.site,
				"timestamp": self.timestamp.isoformat(sep=" "),
				"transaction_type": self.transaction_type,
			}

			if self.transaction_type == "request":
				update = {
					"data": self.data,
					"headers": self.headers,
					"method": self.method,
					"path": self.path,
				}
			else:
				update = {
					"kwargs": self.kwargs,
					"method": self.method,
				}
			data.update(update)
			json_data = json.dumps(data, sort_keys=True, default=str)
			store(json_data)
		except Exception:
			traceback.print_exc()


def store(json_data):
	MAX_LOGS = 1000000
	if frappe.cache().llen(MONITOR_REDIS_KEY) > MAX_LOGS:
		frappe.cache().ltrim(MONITOR_REDIS_KEY, 1, -1)
	frappe.cache().rpush(MONITOR_REDIS_KEY, json_data)


def flush():
	try:
		# Fetch all the logs without removing from cache
		logs = frappe.cache().lrange(MONITOR_REDIS_KEY, 0, -1)
		logs = list(map(frappe.safe_decode, logs))
		with open(log_file(), "a", os.O_NONBLOCK) as f:
			f.write("\n".join(logs))

		# Remove fetched entries from cache
		frappe.cache().ltrim(MONITOR_REDIS_KEY, len(logs) - 1, -1)
	except Exception:
		traceback.print_exc()

@@ -252,16 +252,28 @@
 port os%0A
+import uuid%0A
 %0A%0AMONITO
@@ -927,16 +927,44 @@
 ion_type
+%0A%09%09%09self.uuid = uuid.uuid4()
 %0A%0A%09%09%09if 
@@ -1447,24 +1447,47 @@
 %09%09%09data = %7B%0A
+%09%09%09%09%22uuid%22: self.uuid,%0A
 %09%09%09%09%22duratio

Add UUID to every log