def list_reports(config): """ TODO """ result = {} if not 'reports_directory' in config: msg = "Internal Error." raise UserError(msg) target = config['reports_directory'] or PGBADGER_REPORTS_DIRECTORY try: all_files_in_reports_dir = os.listdir(target) except: msg = "Error while reading the reports directory." raise UserError(msg) for f in all_files_in_reports_dir: if f.endswith(".json"): # filename format is supposed to be like that: # 1525794324_pgbadger_report_05may2018.json timestamp = int(f.split('_')[0]) metadata = {} metadata['timestamp'] = timestamp metadata['created_at'] = datetime.fromtimestamp(timestamp) metadata['url_json'] = '/pgbadger/v0/reports/%d/json' % timestamp metadata['url_html'] = '/pgbadger/v0/reports/%d/html' % timestamp result[timestamp] = metadata return result
def fetch_report_html(config, timestamp): """ TODO """ html_file = html_report_filepath(config, timestamp) # if the report does not exist let's build it from the JSON data if not os.path.isfile(html_file): # Generate the HTML report from the JSON version output_args = ['-f', 'json', json_report_filepath(config, timestamp)] input_args = ['-o', html_file] command = ['perl', pgbadger_bin(config)] + output_args + input_args # This operation should be very quick (return_code, stdout, stderr) = exec_command(command) if return_code != 0: msg = "pgBadger failed." logger.error("%s during command %s with error %s" % (msg, command, stderr)) raise UserError(msg) try: f = open(html_file, 'r') html_content = f.read() except: msg = "Internal Error." logger.error("Can't open file : %s" % html_file) raise UserError(msg) return html_content
def create_report(config): """ TODO """ now = datetime.now() metadata = {} metadata['created_at'] = now metadata['timestamp'] = int(time.mktime(now.timetuple())) # output file output_args = [ '--outfile', json_report_filepath(config, metadata['timestamp']) ] # input file try: input_dir = config['log_directory'] or POSTGRESQL_LOG_DIRECTORY except: msg = 'Internal Error.' raise UserError(msg) input_filename = 'postgresql.log' input_args = [os.path.join(input_dir, input_filename)] # Launch command = ['perl', pgbadger_bin(config)] + output_args + input_args (return_code, stdout, stderr) = exec_command(command) if return_code != 0: msg = "pgBadger failed" logger.error("%s during command %s with error %s" % (msg, command, stderr)) raise UserError(msg) return metadata
def check_table_exists(conn, schema, table): # Check that the specified table exists in schema rows = conn.query( "SELECT 1 FROM pg_tables WHERE tablename = '{table}' AND " "schemaname = '{schema}'".format(table=table, schema=schema)) if not list(rows): raise UserError("Table %s.%s not found" % (schema, table))
def check_index_exists(conn, schema, index): # Check that the specified table exists in schema rows = conn.query( "SELECT 1 FROM pg_indexes WHERE indexname = '{index}' AND " "schemaname = '{schema}'".format(index=index, schema=schema)) if not list(rows): raise UserError("Index %s.%s not found" % (schema, index))
def vacuum(conn, dbname, mode, schema=None, table=None): # Run vacuum statement if table: check_table_exists(conn, schema, table) # Build the SQL query q = "VACUUM" q += " (%s) " % mode.upper() if mode else "" if schema and table: q += " {schema}.{table}".format(schema=schema, table=table) try: # Try to execute the statement logger.info("Running SQL on DB %s: %s" % (dbname, q)) conn.execute(q) logger.info("VACCUM done.") except error as e: logger.exception(str(e)) logger.error("Unable to execute SQL: %s" % q) message = "Unable to run vacuum %s" % mode if schema and table: message += " on %s.%s" % ( schema, table, ) raise UserError(message)
def analyze(conn, dbname, schema=None, table=None): # Run analyze statement if table: check_table_exists(conn, schema, table) # Build the SQL query q = "ANALYZE" if schema and table: q += " {schema}.{table}".format(schema=schema, table=table) try: # Try to execute the statement logger.info("Running SQL on DB %s: %s" % (dbname, q)) conn.execute(q) logger.info("ANALYZE done.") except error as e: logger.exception(str(e)) logger.error("Unable to execute SQL: %s" % q) message = "Unable to run analyze" if schema and table: message += " on %s.%s" % ( schema, table, ) raise UserError(message)
def reindex(conn, dbname, schema, table, index): if index: check_index_exists(conn, schema, index) if table: check_table_exists(conn, schema, table) # Build the SQL query q = "REINDEX" if table: element = '{schema}.{table}'.format(schema=schema, table=table) q += " TABLE {element}".format(element=element) elif index: element = '{schema}.{index}'.format(schema=schema, index=index) q += " INDEX {element}".format(element=element) else: element = '{dbname}'.format(dbname=dbname) q += " DATABASE {element}".format(element=element) try: # Try to execute the statement logger.info("Running SQL on DB %s: %s" % (dbname, q)) conn.execute(q) logger.info("reindex done.") except error as e: logger.exception(str(e)) logger.error("Unable to execute SQL: %s" % q) raise UserError("Unable to run reindex on %s" % (element))
def info(app): cmd = base_cmd(app.config) + ['version'] logger.debug(' '.join(cmd)) (rc, out, err) = exec_command(cmd) if rc != 0: raise UserError("Could not get version of pgBackRest") v = out.strip().split()[1] return {"tool": "pgBackRest", "version": v, "supported": True}
def load(self): pg_version = self.app.postgres.fetch_version() if pg_version < self.PG_MIN_VERSION: msg = "%s is incompatible with Postgres below 9.4" % ( self.__class__.__name__) raise UserError(msg) self.app.router.add(routes)
def load(self): pg_version = self.app.postgres.fetch_version() if pg_version < self.pg_min_version: raise UserError("hellong is incompatible with Postgres below 9.4") self.app.router.add(routes) self.app.worker_pool.add(workers) self.app.scheduler.add(workers)
def purge(config): cmd = base_cmd(config) + ['purge'] logger.debug(' '.join(cmd)) (rc, out, err) = exec_command(cmd) result = {'rc': rc, 'stdout': out.split('\n'), 'stderr': err.split('\n')} logger.debug(out) logger.debug(err) if rc != 0: raise UserError(json.dumps(result)) return json.dumps(result)
def load(self): pg_version = self.app.postgres.fetch_version() if pg_version < self.PG_MIN_VERSION: msg = "%s is incompatible with Postgres below 9.4" % ( self.__class__.__name__) raise UserError(msg) add_route('GET', '/activity')(get_activity) add_route('GET', '/activity/waiting')(get_activity_waiting) add_route('GET', '/activity/blocking')(get_activity_blocking)
def fetch_report(config, timestamp): """ TODO """ reports = list_reports(config) if not timestamp in reports.keys(): msg = "Can't find report for timestamp %d" % timestamp logger.error(msg) raise UserError(msg) return append_json_report(config, reports[timestamp])
def delete_report(config, timestamp): """ Remove a report, identified by its timestamp """ report_file = json_report_filepath(config, timestamp) try: os.remove(report_file) except: msg = "Internal Error." logger.error("Can't remove report %s" % report_file) raise UserError(msg) return {'result': 'Report Removed Succesfully'}
def load(self): pg_version = self.app.postgres.fetch_version() if pg_version < self.PG_MIN_VERSION: msg = "%s is incompatible with Postgres below 9.4" % ( self.__class__.__name__) raise UserError(msg) self.app.router.add(routes) self.app.worker_pool.add(workers) workers.schedule( id='dashboard_collector', redo_interval=self.app.config.dashboard.scheduler_interval)( dashboard_collector_worker) self.app.scheduler.add(workers)
def append_json_report(config, report): """ Add the JSON content of the report in the current report object """ json_file = json_report_filepath(config, report['timestamp']) try: f = open(json_file, 'r') report['json'] = f.read() except: msg = "Internal Error." logger.error("Can't open file : %s" % json_file) raise UserError(msg) return report
def check_version(config): """ check if the pgBadger version is correct, throws an error is pgBadger is not present or too old :param path: directory containing the pgBadger binary (optional) :return: the version in different formats """ command = ['perl', pgbadger_bin(config), '--version'] (return_code, stdout, stderr) = exec_command(command) if return_code != 0: msg = "Seems like pgBadger is not installed : %s" % stderr raise UserError(msg) version = parse_version(stdout) if version['int_version'] < PGBADGER_MIN_VERSION: msg = "This version of pgBadger is too old : %s" % version[ 'full_version'] raise UserError(msg) return version
def load(self): global APP APP = self.app pg_version = self.app.postgres.fetch_version() if pg_version < self.pg_min_version: raise UserError("hellong is incompatible with Postgres below 9.4") # URI **MUST** be bytes. add_route('GET', b'/hello')(get_hello) add_route('GET', b'/hello/time')(get_hello_time) add_route('GET', b'/hello/' + T_SOMETHING)(get_hello_something) add_route('GET', b'/hello2/say')(get_hello_something2) add_route('POST', b'/hello3/say')(get_hello_something3) add_route('GET', b'/hello4/' + T_SOMETHING)(get_hello_something4) add_route('GET', b'/hello/from_config')(get_hello_from_config) add_route( 'GET', b'/hello/from_background_worker')(get_hello_from_background_worker) taskmanager.worker(pool_size=1)(say_hello_worker) taskmanager.bootstrap()(hello_task_manager_bootstrap)
def pgbadger_bin(config): try: return os.path.join(config['pgbadger_path'] or '', 'pgbadger') except: msg = 'Internal Error.' raise UserError(msg)
def reports_directory(config): try: return config['reports_directory'] or PGBADGER_REPORTS_DIRECTORY except: msg = 'Internal Error.' raise UserError(msg)
def main(argv, environ): raise UserError('POUET', retcode=0xd0d0)