def enqueue_webhook(doc, webhook): webhook = dataent.get_doc("Webhook", webhook.get("name")) headers = {} data = {} if webhook.webhook_headers: for h in webhook.webhook_headers: if h.get("key") and h.get("value"): headers[h.get("key")] = h.get("value") if webhook.webhook_data: for w in webhook.webhook_data: for k, v in doc.as_dict().items(): if k == w.fieldname: data[w.key] = v for i in range(3): try: r = requests.post(webhook.request_url, data=json.dumps(data), headers=headers, timeout=5) r.raise_for_status() dataent.logger().debug({"webhook_success": r.text}) break except Exception as e: dataent.logger().debug({"webhook_error": e, "try": i + 1}) sleep(3 * i + 1) if i != 2: continue else: raise e
def enqueue_events_for_site(site, queued_jobs): def log_and_raise(): dataent.logger(__name__).error( 'Exception in Enqueue Events for Site {0}'.format(site) + '\n' + dataent.get_traceback()) raise # pylint: disable=misplaced-bare-raise try: dataent.init(site=site) if dataent.local.conf.maintenance_mode: return if dataent.local.conf.pause_scheduler: return dataent.connect() if is_scheduler_disabled(): return enqueue_events(site=site, queued_jobs=queued_jobs) dataent.logger(__name__).debug( 'Queued events for site {0}'.format(site)) except pymysql.OperationalError as e: if e.args[0] == ER.ACCESS_DENIED_ERROR: dataent.logger(__name__).debug( 'Access denied for site {0}'.format(site)) else: log_and_raise() except: log_and_raise() finally: dataent.destroy()
def create_mandate(data): data = dataent._dict(data) dataent.logger().debug(data) mandate = data.get('mandate') if dataent.db.exists("GoCardless Mandate", mandate): return else: reference_doc = dataent.db.get_value( data.get('reference_doctype'), data.get('reference_docname'), ["reference_doctype", "reference_name"], as_dict=1) epaas_customer = dataent.db.get_value(reference_doc.reference_doctype, reference_doc.reference_name, ["customer_name"], as_dict=1) try: dataent.get_doc({ "doctype": "GoCardless Mandate", "mandate": mandate, "customer": epaas_customer.customer_name, "gocardless_customer": data.get('customer') }).insert(ignore_permissions=True) except Exception: dataent.log_error(dataent.get_traceback())
def make_error_snapshot(exception): if dataent.conf.disable_error_snapshot: return logger = dataent.logger(__name__, with_more_info=False) try: error_id = '{timestamp:s}-{ip:s}-{hash:s}'.format( timestamp=cstr(datetime.datetime.now()), ip=dataent.local.request_ip or '127.0.0.1', hash=dataent.generate_hash(length=3)) snapshot_folder = get_error_snapshot_path() dataent.create_folder(snapshot_folder) snapshot_file_path = os.path.join(snapshot_folder, "{0}.json".format(error_id)) snapshot = get_snapshot(exception) with open(encode(snapshot_file_path), 'wb') as error_file: error_file.write(encode(dataent.as_json(snapshot))) logger.error('New Exception collected with id: {}'.format(error_id)) except Exception as e: logger.error('Could not take error snapshot: {0}'.format(e), exc_info=True)
def trigger(site, event, last=None, queued_jobs=(), now=False): """Trigger method in hooks.scheduler_events.""" queue = 'long' if event.endswith('_long') else 'short' timeout = queue_timeout[queue] if not queued_jobs and not now: queued_jobs = get_jobs(site=site, queue=queue) if dataent.flags.in_test: dataent.flags.ran_schedulers.append(event) events_from_hooks = get_scheduler_events(event) if not events_from_hooks: return events = events_from_hooks if not now: events = [] if event == "cron": for e in events_from_hooks: e = cron_map.get(e, e) if croniter.is_valid(e): if croniter(e, last).get_next( datetime) <= dataent.utils.now_datetime(): events.extend(events_from_hooks[e]) else: dataent.log_error("Cron string " + e + " is not valid", "Error triggering cron job") dataent.logger(__name__).error( 'Exception in Trigger Events for Site {0}, Cron String {1}' .format(site, e)) else: if croniter( cron_map[event], last).get_next(datetime) <= dataent.utils.now_datetime(): events.extend(events_from_hooks) for handler in events: if not now: if handler not in queued_jobs: enqueue(handler, queue, timeout, event) else: scheduler_task(site=site, event=event, handler=handler, now=True)
def scheduler_task(site, event, handler, now=False): '''This is a wrapper function that runs a hooks.scheduler_events method''' dataent.logger(__name__).info( 'running {handler} for {site} for event: {event}'.format( handler=handler, site=site, event=event)) try: if not now: dataent.connect(site=site) dataent.flags.in_scheduler = True dataent.get_attr(handler)() except Exception: dataent.db.rollback() traceback = log( handler, "Method: {event}, Handler: {handler}".format(event=event, handler=handler)) dataent.logger(__name__).error(traceback) raise else: dataent.db.commit() dataent.logger(__name__).info( 'ran {handler} for {site} for event: {event}'.format(handler=handler, site=site, event=event))
def handle_exception(e): response = None http_status_code = getattr(e, "http_status_code", 500) return_as_message = False if dataent.get_request_header('Accept') and ( dataent.local.is_ajax or 'application/json' in dataent.get_request_header('Accept')): # handle ajax responses first # if the request is ajax, send back the trace or error message response = dataent.utils.response.report_error(http_status_code) elif (http_status_code == 500 and isinstance(e, pymysql.InternalError) and e.args[0] in (ER.LOCK_WAIT_TIMEOUT, ER.LOCK_DEADLOCK)): http_status_code = 508 elif http_status_code == 401: dataent.respond_as_web_page( _("Session Expired"), _("Your session has expired, please login again to continue."), http_status_code=http_status_code, indicator_color='red') return_as_message = True elif http_status_code == 403: dataent.respond_as_web_page( _("Not Permitted"), _("You do not have enough permissions to complete the action"), http_status_code=http_status_code, indicator_color='red') return_as_message = True elif http_status_code == 404: dataent.respond_as_web_page( _("Not Found"), _("The resource you are looking for is not available"), http_status_code=http_status_code, indicator_color='red') return_as_message = True else: traceback = "<pre>" + dataent.get_traceback() + "</pre>" if dataent.local.flags.disable_traceback: traceback = "" dataent.respond_as_web_page("Server Error", traceback, http_status_code=http_status_code, indicator_color='red', width=640) return_as_message = True if e.__class__ == dataent.AuthenticationError: if hasattr(dataent.local, "login_manager"): dataent.local.login_manager.clear_cookies() if http_status_code >= 500: dataent.logger().error('Request Error', exc_info=True) make_error_snapshot(e) if return_as_message: response = dataent.website.render.render( "message", http_status_code=http_status_code) return response
def log_and_raise(): dataent.logger(__name__).error( 'Exception in Enqueue Events for Site {0}'.format(site) + '\n' + dataent.get_traceback()) raise # pylint: disable=misplaced-bare-raise
def log(event, details): dataent.logger().info(details)
def sendmail(communication_name, print_html=None, print_format=None, attachments=None, recipients=None, cc=None, bcc=None, lang=None, session=None, print_letterhead=None): try: if lang: dataent.local.lang = lang if session: # hack to enable access to private files in PDF session['data'] = dataent._dict(session['data']) dataent.local.session.update(session) if print_letterhead: dataent.flags.print_letterhead = print_letterhead # upto 3 retries for i in range(3): try: communication = dataent.get_doc("Communication", communication_name) communication._notify(print_html=print_html, print_format=print_format, attachments=attachments, recipients=recipients, cc=cc, bcc=bcc) except pymysql.InternalError as e: # deadlock, try again if e.args[0] == ER.LOCK_DEADLOCK: dataent.db.rollback() time.sleep(1) continue else: raise else: break except: traceback = log( "dataent.core.doctype.communication.email.sendmail", dataent.as_json({ "communication_name": communication_name, "print_html": print_html, "print_format": print_format, "attachments": attachments, "recipients": recipients, "cc": cc, "bcc": bcc, "lang": lang })) dataent.logger(__name__).error(traceback) raise