Underground-Digital/Workflow-Engine
0
1from datetime import datetime2from decimal import Decimal3 4import pytz5from flask import jsonify6from flask_login import current_user7from flask_restful import Resource, reqparse8 9from controllers.console import api10from controllers.console.app.wraps import get_app_model11from controllers.console.wraps import account_initialization_required, setup_required12from extensions.ext_database import db13from libs.helper import DatetimeString14from libs.login import login_required15from models.enums import WorkflowRunTriggeredFrom16from models.model import AppMode17 18 19class WorkflowDailyRunsStatistic(Resource):20 @setup_required21 @login_required22 @account_initialization_required23 @get_app_model24 def get(self, app_model):25 account = current_user26 27 parser = reqparse.RequestParser()28 parser.add_argument("start", type=DatetimeString("%Y-%m-%d %H:%M"), location="args")29 parser.add_argument("end", type=DatetimeString("%Y-%m-%d %H:%M"), location="args")30 args = parser.parse_args()31 32 sql_query = """SELECT33 DATE(DATE_TRUNC('day', created_at AT TIME ZONE 'UTC' AT TIME ZONE :tz )) AS date,34 COUNT(id) AS runs35FROM36 workflow_runs37WHERE38 app_id = :app_id39 AND triggered_from = :triggered_from"""40 arg_dict = {41 "tz": account.timezone,42 "app_id": app_model.id,43 "triggered_from": WorkflowRunTriggeredFrom.APP_RUN.value,44 }45 46 timezone = pytz.timezone(account.timezone)47 utc_timezone = pytz.utc48 49 if args["start"]:50 start_datetime = datetime.strptime(args["start"], "%Y-%m-%d %H:%M")51 start_datetime = start_datetime.replace(second=0)52 53 start_datetime_timezone = timezone.localize(start_datetime)54 start_datetime_utc = start_datetime_timezone.astimezone(utc_timezone)55 56 sql_query += " AND created_at >= :start"57 arg_dict["start"] = start_datetime_utc58 59 if args["end"]:60 end_datetime = datetime.strptime(args["end"], "%Y-%m-%d %H:%M")61 end_datetime = end_datetime.replace(second=0)62 63 end_datetime_timezone = timezone.localize(end_datetime)64 end_datetime_utc = end_datetime_timezone.astimezone(utc_timezone)65 66 sql_query += " AND created_at < :end"67 arg_dict["end"] = end_datetime_utc68 69 sql_query += " GROUP BY date ORDER BY date"70 71 response_data = []72 73 with db.engine.begin() as conn:74 rs = conn.execute(db.text(sql_query), arg_dict)75 for i in rs:76 response_data.append({"date": str(i.date), "runs": i.runs})77 78 return jsonify({"data": response_data})79 80 81class WorkflowDailyTerminalsStatistic(Resource):82 @setup_required83 @login_required84 @account_initialization_required85 @get_app_model86 def get(self, app_model):87 account = current_user88 89 parser = reqparse.RequestParser()90 parser.add_argument("start", type=DatetimeString("%Y-%m-%d %H:%M"), location="args")91 parser.add_argument("end", type=DatetimeString("%Y-%m-%d %H:%M"), location="args")92 args = parser.parse_args()93 94 sql_query = """SELECT95 DATE(DATE_TRUNC('day', created_at AT TIME ZONE 'UTC' AT TIME ZONE :tz )) AS date,96 COUNT(DISTINCT workflow_runs.created_by) AS terminal_count97FROM98 workflow_runs99WHERE100 app_id = :app_id101 AND triggered_from = :triggered_from"""102 arg_dict = {103 "tz": account.timezone,104 "app_id": app_model.id,105 "triggered_from": WorkflowRunTriggeredFrom.APP_RUN.value,106 }107 108 timezone = pytz.timezone(account.timezone)109 utc_timezone = pytz.utc110 111 if args["start"]:112 start_datetime = datetime.strptime(args["start"], "%Y-%m-%d %H:%M")113 start_datetime = start_datetime.replace(second=0)114 115 start_datetime_timezone = timezone.localize(start_datetime)116 start_datetime_utc = start_datetime_timezone.astimezone(utc_timezone)117 118 sql_query += " AND created_at >= :start"119 arg_dict["start"] = start_datetime_utc120 121 if args["end"]:122 end_datetime = datetime.strptime(args["end"], "%Y-%m-%d %H:%M")123 end_datetime = end_datetime.replace(second=0)124 125 end_datetime_timezone = timezone.localize(end_datetime)126 end_datetime_utc = end_datetime_timezone.astimezone(utc_timezone)127 128 sql_query += " AND created_at < :end"129 arg_dict["end"] = end_datetime_utc130 131 sql_query += " GROUP BY date ORDER BY date"132 133 response_data = []134 135 with db.engine.begin() as conn:136 rs = conn.execute(db.text(sql_query), arg_dict)137 for i in rs:138 response_data.append({"date": str(i.date), "terminal_count": i.terminal_count})139 140 return jsonify({"data": response_data})141 142 143class WorkflowDailyTokenCostStatistic(Resource):144 @setup_required145 @login_required146 @account_initialization_required147 @get_app_model148 def get(self, app_model):149 account = current_user150 151 parser = reqparse.RequestParser()152 parser.add_argument("start", type=DatetimeString("%Y-%m-%d %H:%M"), location="args")153 parser.add_argument("end", type=DatetimeString("%Y-%m-%d %H:%M"), location="args")154 args = parser.parse_args()155 156 sql_query = """SELECT157 DATE(DATE_TRUNC('day', created_at AT TIME ZONE 'UTC' AT TIME ZONE :tz )) AS date,158 SUM(workflow_runs.total_tokens) AS token_count159FROM160 workflow_runs161WHERE162 app_id = :app_id163 AND triggered_from = :triggered_from"""164 arg_dict = {165 "tz": account.timezone,166 "app_id": app_model.id,167 "triggered_from": WorkflowRunTriggeredFrom.APP_RUN.value,168 }169 170 timezone = pytz.timezone(account.timezone)171 utc_timezone = pytz.utc172 173 if args["start"]:174 start_datetime = datetime.strptime(args["start"], "%Y-%m-%d %H:%M")175 start_datetime = start_datetime.replace(second=0)176 177 start_datetime_timezone = timezone.localize(start_datetime)178 start_datetime_utc = start_datetime_timezone.astimezone(utc_timezone)179 180 sql_query += " AND created_at >= :start"181 arg_dict["start"] = start_datetime_utc182 183 if args["end"]:184 end_datetime = datetime.strptime(args["end"], "%Y-%m-%d %H:%M")185 end_datetime = end_datetime.replace(second=0)186 187 end_datetime_timezone = timezone.localize(end_datetime)188 end_datetime_utc = end_datetime_timezone.astimezone(utc_timezone)189 190 sql_query += " AND created_at < :end"191 arg_dict["end"] = end_datetime_utc192 193 sql_query += " GROUP BY date ORDER BY date"194 195 response_data = []196 197 with db.engine.begin() as conn:198 rs = conn.execute(db.text(sql_query), arg_dict)199 for i in rs:200 response_data.append(201 {202 "date": str(i.date),203 "token_count": i.token_count,204 }205 )206 207 return jsonify({"data": response_data})208 209 210class WorkflowAverageAppInteractionStatistic(Resource):211 @setup_required212 @login_required213 @account_initialization_required214 @get_app_model(mode=[AppMode.WORKFLOW])215 def get(self, app_model):216 account = current_user217 218 parser = reqparse.RequestParser()219 parser.add_argument("start", type=DatetimeString("%Y-%m-%d %H:%M"), location="args")220 parser.add_argument("end", type=DatetimeString("%Y-%m-%d %H:%M"), location="args")221 args = parser.parse_args()222 223 sql_query = """SELECT224 AVG(sub.interactions) AS interactions,225 sub.date226FROM227 (228 SELECT229 DATE(DATE_TRUNC('day', c.created_at AT TIME ZONE 'UTC' AT TIME ZONE :tz )) AS date,230 c.created_by,231 COUNT(c.id) AS interactions232 FROM233 workflow_runs c234 WHERE235 c.app_id = :app_id236 AND c.triggered_from = :triggered_from237 {{start}}238 {{end}}239 GROUP BY240 date, c.created_by241 ) sub242GROUP BY243 sub.date"""244 arg_dict = {245 "tz": account.timezone,246 "app_id": app_model.id,247 "triggered_from": WorkflowRunTriggeredFrom.APP_RUN.value,248 }249 250 timezone = pytz.timezone(account.timezone)251 utc_timezone = pytz.utc252 253 if args["start"]:254 start_datetime = datetime.strptime(args["start"], "%Y-%m-%d %H:%M")255 start_datetime = start_datetime.replace(second=0)256 257 start_datetime_timezone = timezone.localize(start_datetime)258 start_datetime_utc = start_datetime_timezone.astimezone(utc_timezone)259 260 sql_query = sql_query.replace("{{start}}", " AND c.created_at >= :start")261 arg_dict["start"] = start_datetime_utc262 else:263 sql_query = sql_query.replace("{{start}}", "")264 265 if args["end"]:266 end_datetime = datetime.strptime(args["end"], "%Y-%m-%d %H:%M")267 end_datetime = end_datetime.replace(second=0)268 269 end_datetime_timezone = timezone.localize(end_datetime)270 end_datetime_utc = end_datetime_timezone.astimezone(utc_timezone)271 272 sql_query = sql_query.replace("{{end}}", " AND c.created_at < :end")273 arg_dict["end"] = end_datetime_utc274 else:275 sql_query = sql_query.replace("{{end}}", "")276 277 response_data = []278 279 with db.engine.begin() as conn:280 rs = conn.execute(db.text(sql_query), arg_dict)281 for i in rs:282 response_data.append(283 {"date": str(i.date), "interactions": float(i.interactions.quantize(Decimal("0.01")))}284 )285 286 return jsonify({"data": response_data})287 288 289api.add_resource(WorkflowDailyRunsStatistic, "/apps/<uuid:app_id>/workflow/statistics/daily-conversations")290api.add_resource(WorkflowDailyTerminalsStatistic, "/apps/<uuid:app_id>/workflow/statistics/daily-terminals")291api.add_resource(WorkflowDailyTokenCostStatistic, "/apps/<uuid:app_id>/workflow/statistics/token-costs")292api.add_resource(293 WorkflowAverageAppInteractionStatistic, "/apps/<uuid:app_id>/workflow/statistics/average-app-interactions"294)295 