Serveral improvements, including sorting of output tags, ignore error if any tag fails, add apex mail queue, smtp settings, top redo generating sql and apex bots usage
This commit is contained in:
parent
f54a39aee8
commit
fe39829fa2
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
.vscode/
|
||||
playground/
|
||||
venv/
|
||||
venv/
|
||||
src/custom.json
|
||||
|
||||
75
src/app.py
75
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")
|
||||
|
||||
@ -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
|
||||
}
|
||||
]
|
||||
|
||||
87
src/scripts/apexBots.sh
Executable file
87
src/scripts/apexBots.sh
Executable file
@ -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 <<EOF >> \"$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"
|
||||
74
src/scripts/apex_mail_queue.sh
Executable file
74
src/scripts/apex_mail_queue.sh
Executable file
@ -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 <<EOF >> \"$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 <<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 APEX Mail Queue 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"
|
||||
81
src/scripts/apex_smtp_settings.sh
Executable file
81
src/scripts/apex_smtp_settings.sh
Executable file
@ -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 <<EOF >> \"$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 <<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 APEX SMTP Settings 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"
|
||||
82
src/scripts/topRedoSQL.sh
Executable file
82
src/scripts/topRedoSQL.sh
Executable file
@ -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 <<EOF >> \"$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 <<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 top redo size sessions 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
|
||||
Loading…
x
Reference in New Issue
Block a user