capsul.org webapp

trying to fix logging

forest 26340f11 3bd9d24a

+2 -1
app.py
··· 1 - from capsulflask import app 1 + 2 + from capsulflask import app
+27 -2
capsulflask/__init__.py
··· 1 + import logging 2 + from logging.config import dictConfig as logging_dict_config 1 3 2 4 import os 3 5 ··· 13 15 load_dotenv(find_dotenv()) 14 16 15 17 app = Flask(__name__) 18 + 16 19 app.config.from_mapping( 17 20 BASE_URL=os.environ.get("BASE_URL", default="http://localhost:5000"), 18 21 SECRET_KEY=os.environ.get("SECRET_KEY", default="dev"), 22 + LOG_LEVEL=os.environ.get("LOG_LEVEL", default="INFO"), 23 + 19 24 DATABASE_URL=os.environ.get("DATABASE_URL", default="sql://postgres:dev@localhost:5432/postgres"), 20 25 DATABASE_SCHEMA=os.environ.get("DATABASE_SCHEMA", default="public"), 21 26 ··· 37 42 BTCPAY_URL=os.environ.get("BTCPAY_URL", default="https://btcpay.cyberia.club") 38 43 ) 39 44 45 + logging_dict_config({ 46 + 'version': 1, 47 + 'formatters': {'default': { 48 + 'format': '[%(asctime)s] %(levelname)s in %(module)s: %(message)s', 49 + }}, 50 + 'handlers': {'wsgi': { 51 + 'class': 'logging.StreamHandler', 52 + 'stream': 'ext://flask.logging.wsgi_errors_stream', 53 + 'formatter': 'default' 54 + }}, 55 + 'root': { 56 + 'level': app.config['LOG_LEVEL'], 57 + 'handlers': ['wsgi'] 58 + } 59 + }) 60 + 61 + # app.logger.critical("critical") 62 + # app.logger.error("error") 63 + # app.logger.warning("warning") 64 + # app.logger.info("info") 65 + # app.logger.debug("debug") 66 + 40 67 stripe.api_key = app.config['STRIPE_SECRET_KEY'] 41 68 stripe.api_version = app.config['STRIPE_API_VERSION'] 42 69 ··· 59 86 60 87 app.add_url_rule("/", endpoint="index") 61 88 62 - if __name__ == "__main__": 63 - app.run(host='127.0.0.1')
+10 -10
capsulflask/cli.py
··· 66 66 def cron_task(): 67 67 68 68 # make sure btcpay payments get completed (in case we miss a webhook), otherwise invalidate the payment 69 - print("cron_task: starting clean_up_unresolved_btcpay_invoices") 69 + current_app.logger.info("cron_task: starting clean_up_unresolved_btcpay_invoices") 70 70 clean_up_unresolved_btcpay_invoices() 71 - print("cron_task: finished clean_up_unresolved_btcpay_invoices") 71 + current_app.logger.info("cron_task: finished clean_up_unresolved_btcpay_invoices") 72 72 73 73 # notify when funds run out 74 - print("cron_task: starting notify_users_about_account_balance") 74 + current_app.logger.info("cron_task: starting notify_users_about_account_balance") 75 75 notify_users_about_account_balance() 76 - print("cron_task: finished notify_users_about_account_balance") 76 + current_app.logger.info("cron_task: finished notify_users_about_account_balance") 77 77 78 78 # make sure vm system and DB are synced 79 - print("cron_task: starting ensure_vms_and_db_are_synced") 79 + current_app.logger.info("cron_task: starting ensure_vms_and_db_are_synced") 80 80 ensure_vms_and_db_are_synced() 81 - print("cron_task: finished ensure_vms_and_db_are_synced") 81 + current_app.logger.info("cron_task: finished ensure_vms_and_db_are_synced") 82 82 83 83 84 84 ··· 90 90 days = float((datetime.now() - unresolved_invoice['created']).total_seconds())/float(60*60*24) 91 91 92 92 if btcpay_invoice['status'] == "complete": 93 - print( 93 + current_app.logger.info( 94 94 f"resolving btcpay invoice {invoice_id} " 95 95 f"({unresolved_invoice['email']}, ${unresolved_invoice['dollars']}) as completed " 96 96 ) 97 97 get_model().btcpay_invoice_resolved(invoice_id, True) 98 98 elif days >= 1: 99 - print( 99 + current_app.logger.info( 100 100 f"resolving btcpay invoice {invoice_id} " 101 101 f"({unresolved_invoice['email']}, ${unresolved_invoice['dollars']}) as invalidated, " 102 102 f"btcpay server invoice status: {btcpay_invoice['status']}" ··· 224 224 index_to_send = i 225 225 226 226 if index_to_send > -1: 227 - print(f"cron_task: sending {warnings[index_to_send]['id']} warning email to {account['email']}.") 227 + current_app.logger.info(f"cron_task: sending {warnings[index_to_send]['id']} warning email to {account['email']}.") 228 228 get_body = warnings[index_to_send]['get_body'] 229 229 get_subject = warnings[index_to_send]['get_subject'] 230 230 current_app.config["FLASK_MAIL_INSTANCE"].send( ··· 237 237 get_model().set_account_balance_warning(account['email'], warnings[index_to_send]['id']) 238 238 if index_to_send == len(warnings)-1: 239 239 for vm in vms: 240 - print(f"cron_task: deleting {vm['id']} ( {account['email']} ) due to negative account balance.") 240 + current_app.logger.warning(f"cron_task: deleting {vm['id']} ( {account['email']} ) due to negative account balance.") 241 241 current_app.config["VIRTUALIZATION_MODEL"].destroy(email=account["email"], id=vm['id']) 242 242 get_model().delete_vm(email=account["email"], id=vm['id']) 243 243
+4 -5
capsulflask/console.py
··· 30 30 ipv4 = result.ipv4 31 31 get_model().update_vm_ip(email=session["account"], id=id, ipv4=result.ipv4) 32 32 except: 33 - print(f""" 33 + current_app.logger.error(f""" 34 34 the virtualization model threw an error in double_check_capsul_address of {id}: 35 35 {my_exec_info_message(sys.exc_info())}""" 36 36 ) ··· 82 82 83 83 return render_template("capsul-detail.html", vm=vm, delete=True, deleted=False) 84 84 else: 85 - print(f"deleting {vm['id']} per user request ({session['account']})") 85 + current_app.logger.info(f"deleting {vm['id']} per user request ({session['account']})") 86 86 current_app.config["VIRTUALIZATION_MODEL"].destroy(email=session['account'], id=id) 87 87 get_model().delete_vm(email=session['account'], id=id) 88 88 ··· 182 182 flash(error) 183 183 184 184 if not capacity_avaliable: 185 - print(f"when capsul capacity is restored, send an email to {session['account']}") 185 + current_app.logger.warning(f"when capsul capacity is restored, send an email to {session['account']}") 186 186 187 187 return render_template( 188 188 "create-capsul.html", ··· 299 299 300 300 for vm in get_vms(): 301 301 end_datetime = vm["deleted"] if vm["deleted"] else datetime.utcnow() 302 - # print(end_datetime) 303 - # print(vm["created"]) 302 + 304 303 vm_months = (end_datetime - vm["created"]).days / average_number_of_days_in_a_month 305 304 vms_billed.append(dict( 306 305 id=vm["id"],
+10 -10
capsulflask/db.py
··· 25 25 26 26 schemaMigrations = {} 27 27 schemaMigrationsPath = join(app.root_path, 'schema_migrations') 28 - print("loading schema migration scripts from {}".format(schemaMigrationsPath)) 28 + app.logger.info("loading schema migration scripts from {}".format(schemaMigrationsPath)) 29 29 for filename in listdir(schemaMigrationsPath): 30 30 result = re.search(r"^\d+_(up|down)", filename) 31 31 if not result: 32 - print(f"schemaVersion {filename} must match ^\d+_(up|down). exiting.") 32 + app.logger.error(f"schemaVersion {filename} must match ^\\d+_(up|down). exiting.") 33 33 exit(1) 34 34 key = result.group() 35 35 with open(join(schemaMigrationsPath, filename), 'rb') as file: ··· 54 54 hasSchemaVersionTable = True 55 55 56 56 if hasSchemaVersionTable == False: 57 - print("no table named schemaversion found in the {} schema. running migration 01_up".format(app.config['DATABASE_SCHEMA'])) 57 + app.logger.info("no table named schemaversion found in the {} schema. running migration 01_up".format(app.config['DATABASE_SCHEMA'])) 58 58 try: 59 59 cursor.execute(schemaMigrations["01_up"]) 60 60 connection.commit() 61 61 except: 62 - print("unable to create the schemaversion table because: {}".format(my_exec_info_message(sys.exc_info()))) 62 + app.logger.error("unable to create the schemaversion table because: {}".format(my_exec_info_message(sys.exc_info()))) 63 63 exit(1) 64 64 actionWasTaken = True 65 65 ··· 67 67 schemaVersion = cursor.fetchall()[0][0] 68 68 69 69 if schemaVersion > desiredSchemaVersion: 70 - print("schemaVersion ({}) > desiredSchemaVersion ({}). schema downgrades are not supported yet. exiting.".format( 70 + app.logger.critical("schemaVersion ({}) > desiredSchemaVersion ({}). schema downgrades are not supported yet. exiting.".format( 71 71 schemaVersion, desiredSchemaVersion 72 72 )) 73 73 exit(1) 74 74 75 75 while schemaVersion < desiredSchemaVersion: 76 76 migrationKey = "%02d_up" % (schemaVersion+1) 77 - print("schemaVersion ({}) < desiredSchemaVersion ({}). running migration {}".format( 77 + app.logger.info("schemaVersion ({}) < desiredSchemaVersion ({}). running migration {}".format( 78 78 schemaVersion, desiredSchemaVersion, migrationKey 79 79 )) 80 80 try: 81 81 cursor.execute(schemaMigrations[migrationKey]) 82 82 connection.commit() 83 83 except KeyError: 84 - print("missing schema migration script: {}_xyz.sql".format(migrationKey)) 84 + app.logger.critical("missing schema migration script: {}_xyz.sql".format(migrationKey)) 85 85 exit(1) 86 86 except: 87 - print("unable to execute the schema migration {} because: {}".format(migrationKey, my_exec_info_message(sys.exc_info()))) 87 + app.logger.critical("unable to execute the schema migration {} because: {}".format(migrationKey, my_exec_info_message(sys.exc_info()))) 88 88 exit(1) 89 89 actionWasTaken = True 90 90 ··· 93 93 versionFromDatabase = cursor.fetchall()[0][0] 94 94 95 95 if schemaVersion != versionFromDatabase: 96 - print("incorrect schema version value \"{}\" after running migration {}, expected \"{}\". exiting.".format( 96 + app.logger.critical("incorrect schema version value \"{}\" after running migration {}, expected \"{}\". exiting.".format( 97 97 versionFromDatabase, 98 98 migrationKey, 99 99 schemaVersion ··· 104 104 105 105 app.config['PSYCOPG2_CONNECTION_POOL'].putconn(connection) 106 106 107 - print("{} current schemaVersion: \"{}\"".format( 107 + app.logger.info("{} current schemaVersion: \"{}\"".format( 108 108 ("schema migration completed." if actionWasTaken else "schema is already up to date. "), schemaVersion 109 109 )) 110 110
+2 -1
capsulflask/db_model.py
··· 1 1 2 2 from nanoid import generate 3 + from flask import current_app 3 4 4 5 5 6 class DBModel: ··· 168 169 row = self.cursor.fetchone() 169 170 if row: 170 171 if int(row[1]) != int(dollars): 171 - print(f""" 172 + current_app.logger.warning(f""" 172 173 {payment_type} gave us a completed payment session with a different dollar amount than what we had recorded!! 173 174 id: {id} 174 175 account: {row[0]}
+1
capsulflask/landing.py
··· 1 1 from flask import Blueprint 2 2 from flask import render_template 3 + from flask import current_app 3 4 4 5 bp = Blueprint("landing", __name__, url_prefix="/") 5 6
+6 -6
capsulflask/payment.py
··· 62 62 # print(invoice) 63 63 invoice_id = invoice["id"] 64 64 65 - print(f"created btcpay invoice_id={invoice_id} ( {session['account']}, ${dollars} )") 65 + current_app.logger.info(f"created btcpay invoice_id={invoice_id} ( {session['account']}, ${dollars} )") 66 66 67 67 get_model().create_payment_session("btcpay", invoice_id, session["account"], dollars) 68 68 ··· 94 94 success_account = get_model().consume_payment_session("btcpay", invoice_id, dollars) 95 95 96 96 if success_account: 97 - print(f"{success_account} paid ${dollars} successfully (btcpay_invoice_id={invoice_id})") 97 + current_app.logger.info(f"{success_account} paid ${dollars} successfully (btcpay_invoice_id={invoice_id})") 98 98 99 99 if invoice['status'] == "complete": 100 100 get_model().btcpay_invoice_resolved(invoice_id, True) ··· 119 119 120 120 if len(errors) == 0: 121 121 122 - print(f"creating stripe checkout session for {session['account']}, ${dollars}") 122 + current_app.logger.info(f"creating stripe checkout session for {session['account']}, ${dollars}") 123 123 124 124 checkout_session = stripe.checkout.Session.create( 125 125 success_url=current_app.config['BASE_URL'] + "/payment/stripe/success?session_id={CHECKOUT_SESSION_ID}", ··· 138 138 ) 139 139 stripe_checkout_session_id = checkout_session['id'] 140 140 141 - print(f"stripe_checkout_session_id={stripe_checkout_session_id} ( {session['account']}, ${dollars} )") 141 + current_app.logger.info(f"stripe_checkout_session_id={stripe_checkout_session_id} ( {session['account']}, ${dollars} )") 142 142 143 143 get_model().create_payment_session("stripe", stripe_checkout_session_id, session["account"], dollars) 144 144 ··· 191 191 def success(): 192 192 stripe_checkout_session_id = request.args.get('session_id') 193 193 if not stripe_checkout_session_id: 194 - print("/payment/stripe/success returned 400: missing required URL parameter session_id") 194 + current_app.logger.info("/payment/stripe/success returned 400: missing required URL parameter session_id") 195 195 abort(400, "missing required URL parameter session_id") 196 196 else: 197 197 for _ in range(0, 5): 198 198 paid = validate_stripe_checkout_session(stripe_checkout_session_id) 199 199 if paid: 200 - print(f"{paid['email']} paid ${paid['dollars']} successfully (stripe_checkout_session_id={stripe_checkout_session_id})") 200 + current_app.logger.info(f"{paid['email']} paid ${paid['dollars']} successfully (stripe_checkout_session_id={stripe_checkout_session_id})") 201 201 return redirect(url_for("console.account_balance")) 202 202 else: 203 203 sleep(1)
+4 -4
capsulflask/virt_model.py
··· 47 47 48 48 def create(self, email: str, id: str, template_image_file_name: str, vcpus: int, memory_mb: int, ssh_public_keys: list): 49 49 validate_capsul_id(id) 50 - print(f"mock create: {id} for {email}") 50 + current_app.logger.info(f"mock create: {id} for {email}") 51 51 sleep(1) 52 52 53 53 def destroy(self, email: str, id: str): 54 - print(f"mock destroy: {id} for {email}") 54 + current_app.logger.info(f"mock destroy: {id} for {email}") 55 55 56 56 57 57 class ShellScriptVirtualization(VirtualizationInterface): ··· 74 74 completedProcess = run(my_args, capture_output=True) 75 75 76 76 if completedProcess.returncode != 0: 77 - print(f""" 77 + current_app.logger.error(f""" 78 78 capacity-avaliable.sh exited {completedProcess.returncode} with 79 79 stdout: 80 80 {completedProcess.stdout} ··· 85 85 86 86 lines = completedProcess.stdout.splitlines() 87 87 if not lines[len(lines)-1] == "yes": 88 - print("capacity-avaliable.sh exited 0 but did not return \"yes\" ") 88 + current_app.logger.error("capacity-avaliable.sh exited 0 but did not return \"yes\" ") 89 89 return False 90 90 91 91 return True