diff --git a/.gitignore b/.gitignore index 37a6672..a42a8ae 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .vscode/ playground/ -venv/ \ No newline at end of file +venv/ +src/custom.json diff --git a/src/app.py b/src/app.py index 58c4b9b..0386a6d 100644 --- a/src/app.py +++ b/src/app.py @@ -38,9 +38,9 @@ def read_log(log_file, lines): @app.route('/get_logs', methods=['GET']) def get_logs(): - tags = request.args.getlist("tags") + tags = request.args.getlist("tags") # Get tags in the order they appear in the query try: - # Load main config-tags.json + # Load main config.json with open('/opt/ticket-ai/src/config.json') as config_file: config = json.load(config_file) @@ -49,40 +49,51 @@ def get_logs(): if os.path.exists(custom_config_path): with open(custom_config_path) as custom_file: custom_config = json.load(custom_file) - for key, value in custom_config.items(): - if key in config: - config[key].extend(value) - else: - config[key] = value + for custom_tag in custom_config["tags"]: + # Remove matching tags in config if custom.json supersedes + config["tags"] = [tag for tag in config["tags"] if tag["tag"] != custom_tag["tag"]] + config["tags"].append(custom_tag) - response = {} - - # Process each tag in the list + response_list = [] # Use a list to store the responses in order + tags_found = False + + # Process each tag in the given order for tag in tags: - # Search for the tag in commands and logs - tag_data = next((item for item in config["tags"] if item["tag"] == tag), None) - if not tag_data: - response[tag] = "Tag not found" - continue - - # Determine if the tag is a command or a log - if tag_data["type"] == "command": - response[tag] = f"```\n{os.popen(tag_data['content']).read()}\n```" - elif tag_data["type"] == "log": - log_file = tag_data["content"] - # Replace any placeholders in the log file path - log_file = replace_placeholders(log_file) - if "*" in log_file: - # Handle wildcard in log file path - response[tag] = f"```\n{read_log_from_dir(*split_directory_and_file(log_file), tag_data['lines'])}\n```" - else: - # Regular log file - response[tag] = f"```\n{read_log(log_file, tag_data['lines'])}\n```" + try: + # Search for the tag in commands and logs + tag_data = next((item for item in config["tags"] if item["tag"] == tag), None) + if not tag_data: + response_list.append({tag: "Tag not found"}) + continue + + tags_found = True # At least one valid tag is found + + # Determine if the tag is a command or a log + if tag_data["type"] == "command": + response_list.append({tag: f"```\n{os.popen(tag_data['content']).read()}\n```"}) + elif tag_data["type"] == "log": + log_file = tag_data["content"] + # Replace any placeholders in the log file path + log_file = replace_placeholders(log_file) + if "*" in log_file: + # Handle wildcard in log file path + response_list.append({tag: f"```\n{read_log_from_dir(*split_directory_and_file(log_file), tag_data['lines'])}\n```"}) + else: + # Regular log file + response_list.append({tag: f"```\n{read_log(log_file, tag_data['lines'])}\n```"}) + except Exception as e: + # Log the error and proceed + response_list.append({tag: f"Error: {str(e)}"}) + + # If no tags were found, return HTTP 400 with an error message + if not tags_found: + return jsonify({"error": "None of the requested tags were found."}), 400 except Exception as e: - return jsonify({"error": str(e)}) - - return jsonify(response) + return jsonify({"error": str(e)}), 500 + + # Return the response as a list to guarantee order + return jsonify(response_list) if __name__ == '__main__': app.run(debug=True, host="0.0.0.0") diff --git a/src/config.json b/src/config.json index 0ba1458..db1326f 100644 --- a/src/config.json +++ b/src/config.json @@ -25,6 +25,26 @@ "type": "command", "content": "/opt/ticket-ai/src/scripts/apexUsage.sh;sleep 5;cat /tmp/apex_usage.tmp" }, + { + "tag": "apex_mail_queue", + "type": "command", + "content": "/opt/ticket-ai/src/scripts/apex_mail_queue.sh;sleep 5;cat /tmp/apex_mail_queue.tmp" + }, + { + "tag": "apex_smtp_settings", + "type": "command", + "content": "/opt/ticket-ai/src/scripts/apex_smtp_settings.sh;sleep 5;cat /tmp/apex_smtp_settings.tmp" + }, + { + "tag": "apex_bot_hits", + "type": "command", + "content": "/opt/ticket-ai/src/scripts/apexBots.sh;sleep 5;cat /tmp/apex_bots.tmp" + }, + { + "tag": "top_redo_sql", + "type": "command", + "content": "/opt/ticket-ai/src/scripts/topRedoSQL.sh;sleep 5;cat /tmp/top_redo_sql.tmp" + }, { "tag": "top", "type": "command", @@ -36,27 +56,22 @@ "content": "iostat -x 1 3" }, { - "tag": "df", - "type": "command", - "content": "df -h | head -n 1 && df -h | grep '^/dev/sd'" - }, - { - "tag": "processfinder", + "tag": "process_finder", "type": "command", "content": "/opt/ticket-ai/src/scripts/processfinder.sh;sleep 5;cat /tmp/findsql.tmp" }, { - "tag": "ordsconfig", + "tag": "ords_config", "type": "command", "content": "cat /opt/ords/config/databases/default/pool.xml" }, { - "tag": "datetime", + "tag": "date_time", "type": "command", "content": "echo Current Date and time on server: ; date" }, { - "tag": "apacheerrorlogs", + "tag": "apache_error_logs", "type": "command", "content": "find {virtualmin_error_log} -type f -name '*error_log*' -mmin -15 -exec sh -c 'echo \"===== {} =====\"; tail -n 50 {}' \\;" }, @@ -135,7 +150,7 @@ "lines": 150 }, { - "tag": "os-release", + "tag": "os_release", "type": "log", "content": "/etc/os-release", "lines": 150 @@ -155,7 +170,7 @@ { "tag": "var_log_mariadb", "type": "log", - "content": "/var/log/mariadb/mariadb.log", + "content": "/var/log/mariadb/mariadb.log1", "lines": 150 } ] diff --git a/src/scripts/apexBots.sh b/src/scripts/apexBots.sh new file mode 100755 index 0000000..6182eed --- /dev/null +++ b/src/scripts/apexBots.sh @@ -0,0 +1,87 @@ +#!/bin/bash + +# File paths for output +OUTPUT_FILE="/tmp/apex_bots.tmp" +PDB_LIST_FILE="/tmp/pdb_list.tmp" +> "$OUTPUT_FILE" # Clear the output file before starting +touch $OUTPUT_FILE +chown oracle $OUTPUT_FILE + +# Function to execute the Bot Hits query in a specific container +run_query() { + local container_name="$1" + su - oracle -s /bin/bash -c " + sqlplus -s / as sysdba <> \"$OUTPUT_FILE\" + whenever sqlerror exit sql.sqlcode; + set echo on + set heading on + SET UNDERLINE '=' + set feedback off + set linesize 150 + + -- Switch to the specified container + ALTER SESSION SET CONTAINER = $container_name; + + -- Print the container name for clarity + PROMPT Bot Hits on APEX for container: $container_name; + + SELECT + AGENT, + COUNT(*) AS HIT_COUNT + FROM + APEX_WORKSPACE_ACTIVITY_LOG + WHERE + VIEW_DATE BETWEEN SYSDATE - (1/24) AND SYSDATE + AND ( + UPPER(AGENT) LIKE '%BOT%' OR + UPPER(AGENT) LIKE '%YANDEX%' OR + UPPER(AGENT) LIKE '%MJ12BOT%' OR + UPPER(AGENT) LIKE '%INDEX%' OR + UPPER(AGENT) LIKE '%.RU%' OR + UPPER(AGENT) LIKE '%GOOGLE%' OR + UPPER(AGENT) LIKE '%FACEBOOK%' + ) + GROUP BY + AGENT + ORDER BY + HIT_COUNT DESC; + + + exit; +EOF + " +} + +# Run the query for the CDB (root container) +# echo "Gathering Bot Hits for CDB (root container)..." >> "$OUTPUT_FILE" +# run_query 'CDB\$ROOT' + +# Get a list of all PDBs, excluding PDB$SEED, and write to a temporary file +su - oracle -s /bin/bash -c " + sqlplus -s / as sysdba <<'EOF' + set heading off + set feedback off + set pagesize 0 + spool $PDB_LIST_FILE + SELECT NAME FROM v\$pdbs WHERE NAME NOT IN ('PDB\$SEED'); + spool off + exit; +EOF +" + +# Verify that the PDB_LIST_FILE was created and contains data +if [[ -f "$PDB_LIST_FILE" && -s "$PDB_LIST_FILE" ]]; then + # Read each valid PDB name from the temporary file + while IFS= read -r PDB; do + PDB=$(echo "$PDB" | xargs) # Trim any leading/trailing whitespace + if [[ -n "$PDB" ]]; then + echo "Gathering Bot Hits for PDB: $PDB..." >> "$OUTPUT_FILE" + run_query "$PDB" + fi + done < "$PDB_LIST_FILE" +else + echo "No PDBs found or could not access v\$pdbs view" >> "$OUTPUT_FILE" +fi + +# Clean up the temporary file +rm -f "$PDB_LIST_FILE" diff --git a/src/scripts/apex_mail_queue.sh b/src/scripts/apex_mail_queue.sh new file mode 100755 index 0000000..4f9ec24 --- /dev/null +++ b/src/scripts/apex_mail_queue.sh @@ -0,0 +1,74 @@ +#!/bin/bash + +# File paths for output +OUTPUT_FILE="/tmp/apex_mail_queue.tmp" +PDB_LIST_FILE="/tmp/pdb_list.tmp" +> "$OUTPUT_FILE" # Clear the output file before starting +touch $OUTPUT_FILE +chown oracle $OUTPUT_FILE + +# Function to execute the APEX Mail Queue query in a specific container +run_query() { + local container_name="$1" + su - oracle -s /bin/bash -c " + sqlplus -s / as sysdba <> \"$OUTPUT_FILE\" + whenever sqlerror exit sql.sqlcode; + set echo on + set heading on + SET UNDERLINE '=' + set feedback off + set linesize 150 + + -- Switch to the specified container + ALTER SESSION SET CONTAINER = $container_name; + + -- Print the container name for clarity + PROMPT APEX Mail Queue for container: $container_name; + + SELECT + WORKSPACE_NAME, + COUNT(*) AS TOTAL_EMAILS, + SUM(CASE WHEN MAIL_SEND_COUNT = 0 THEN 1 ELSE 0 END) AS UNSENT_EMAILS, + SUM(CASE WHEN MAIL_SEND_ERROR IS NOT NULL THEN 1 ELSE 0 END) AS EMAILS_WITH_ERRORS + FROM + APEX_MAIL_QUEUE + GROUP BY + WORKSPACE_NAME + ORDER BY + WORKSPACE_NAME; + + + exit; +EOF + " +} + +# Get a list of all PDBs, excluding PDB$SEED, and write to a temporary file +su - oracle -s /bin/bash -c " + sqlplus -s / as sysdba <> "$OUTPUT_FILE" + run_query "$PDB" + fi + done < "$PDB_LIST_FILE" +else + echo "No PDBs found or could not access v\$pdbs view" >> "$OUTPUT_FILE" +fi + +# Clean up the temporary file +rm -f "$PDB_LIST_FILE" diff --git a/src/scripts/apex_smtp_settings.sh b/src/scripts/apex_smtp_settings.sh new file mode 100755 index 0000000..38d2886 --- /dev/null +++ b/src/scripts/apex_smtp_settings.sh @@ -0,0 +1,81 @@ +#!/bin/bash + +# File paths for output +OUTPUT_FILE="/tmp/apex_smtp_settings.tmp" +PDB_LIST_FILE="/tmp/pdb_list.tmp" +> "$OUTPUT_FILE" # Clear the output file before starting +touch $OUTPUT_FILE +chown oracle $OUTPUT_FILE + +# Function to execute the SMTP Settings query in a specific container +run_query() { + local container_name="$1" + su - oracle -s /bin/bash -c " + sqlplus -s / as sysdba <> \"$OUTPUT_FILE\" + whenever sqlerror exit sql.sqlcode; + set echo on + set heading on + SET UNDERLINE '=' + set feedback off + set linesize 150 + + -- Switch to the specified container + ALTER SESSION SET CONTAINER = $container_name; + + -- Print the container name for clarity + PROMPT APEX SMTP Settings for container: $container_name; + + SELECT + 'SMTP_HOST_ADDRESS' AS PARAMETER_NAME, APEX_INSTANCE_ADMIN.GET_PARAMETER('SMTP_HOST_ADDRESS') AS PARAMETER_VALUE + FROM + DUAL + UNION ALL + SELECT + 'SMTP_PORT', APEX_INSTANCE_ADMIN.GET_PARAMETER('SMTP_PORT') + FROM + DUAL + UNION ALL + SELECT + 'SMTP_USERNAME', APEX_INSTANCE_ADMIN.GET_PARAMETER('SMTP_USERNAME') + FROM + DUAL + UNION ALL + SELECT + 'SMTP_AUTH_REQUIRED', APEX_INSTANCE_ADMIN.GET_PARAMETER('SMTP_AUTH_REQUIRED') + FROM + DUAL; + + exit; +EOF + " +} + +# Get a list of all PDBs, excluding PDB$SEED, and write to a temporary file +su - oracle -s /bin/bash -c " + sqlplus -s / as sysdba <> "$OUTPUT_FILE" + run_query "$PDB" + fi + done < "$PDB_LIST_FILE" +else + echo "No PDBs found or could not access v\$pdbs view" >> "$OUTPUT_FILE" +fi + +# Clean up the temporary file +rm -f "$PDB_LIST_FILE" diff --git a/src/scripts/topRedoSQL.sh b/src/scripts/topRedoSQL.sh new file mode 100755 index 0000000..4f99662 --- /dev/null +++ b/src/scripts/topRedoSQL.sh @@ -0,0 +1,82 @@ +#!/bin/bash + +# File paths for output +OUTPUT_FILE="/tmp/top_redo_sql.tmp" +PDB_LIST_FILE="/tmp/pdb_list.tmp" +> "$OUTPUT_FILE" # Clear the output file before starting +touch $OUTPUT_FILE +chown oracle $OUTPUT_FILE + +# Function to execute the Redo Size query in a specific container +run_query() { + local container_name="$1" + su - oracle -s /bin/bash -c " + sqlplus -s / as sysdba <> \"$OUTPUT_FILE\" + whenever sqlerror exit sql.sqlcode; + set echo on + set heading on + SET UNDERLINE '=' + set feedback off + set linesize 150 + + -- Switch to the specified container + ALTER SESSION SET CONTAINER = $container_name; + + -- Print the container name for clarity + PROMPT Top redo size sessions for container: $container_name; + + SELECT + S.SID, + S.SERIAL#, + Q.SQL_TEXT, + S.USERNAME, + ROUND(R.VALUE / (1024 * 1024), 2) AS REDO_SIZE_MB + FROM + V\\\$SESSION S + JOIN + V\\\$SQL Q ON S.SQL_ADDRESS = Q.ADDRESS + JOIN + V\\\$SESSTAT R ON S.SID = R.SID + JOIN + V\\\$STATNAME N ON R.STATISTIC# = N.STATISTIC# + WHERE + N.NAME = 'redo size' + AND S.LAST_CALL_ET < 7200 -- Filter sessions active within last 2 hours + ORDER BY + R.VALUE DESC + FETCH FIRST 10 ROWS ONLY; + + exit; +EOF + " +} + +# Get a list of all PDBs, excluding PDB$SEED, and write to a temporary file +su - oracle -s /bin/bash -c " + sqlplus -s / as sysdba <> "$OUTPUT_FILE" + run_query "$PDB" + fi + done < "$PDB_LIST_FILE" +else + echo "No PDBs found or could not access v\$pdbs view" >> "$OUTPUT_FILE" +fi + +# Clean up the temporary file +rm -f