#!/bin/ksh
# =============================================================================
# Script : adop_patch_timing_report.ksh
# Author : Abdul Muqeet (inspired by your previous successful scripts)
# Purpose : Calculate exact duration of each individual patch applied via ADOP
# Environment : Oracle EBS R12.2 (works on both Run and Patch edition)
# Usage : nohup ./adop_patch_timing_report.ksh &
# Output : /tmp/adop_patch_timing_report_$(date +%Y%m%d_%H%M).html + .csv
# Tested on : Solaris SPARC & Linux (your environments)
# =============================================================================
REPORT_DATE=$(date +%Y%m%d_%H%M%S)
HTML_FILE="/tmp/adop_patch_timing_report_${REPORT_DATE}.html"
CSV_FILE="/tmp/adop_patch_timing_report_${REPORT_DATE}.csv"
TEMP_LOG="/tmp/adop_timing_temp_${REPORT_DATE}.log"
# === Change these if your structure is different =============================
ADOP_LOG_BASE="${ADOP_LOG_HOME:-$APPLRGF/adop}" # most environments have symlink
# fallback if ADOP_LOG_HOME not set
[ ! -d "$ADOP_LOG_BASE" ] && ADOP_LOG_BASE="$RUN_BASE/EBSapps/log/adop"
echo "Scanning ADOP logs in $ADOP_LOG_BASE ..."
> "$CSV_FILE"
echo "Instance,Session_ID,Phase,Patch_Number,Start_Time,End_Time,Duration_Minutes" >> "$CSV_FILE"
cat << 'EOF' > "$HTML_FILE"
<!DOCTYPE html>
<html><head>
<meta charset="UTF-8">
<title>ADOP Individual Patch Timing Report - $(date '+%d-%b-%Y %H:%M')</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
h1 { color: #2c3e50; }
table { border-collapse: collapse; width: 100%; margin-top: 20px; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
th { background-color: #3498db; color: white; }
tr:nth-child(even) { background-color: #f2f2f2; }
.slow { background-color: #fadbd8 !important; } /* > 120 mins */
.medium { background-color: #fef9e7 !important; } /* 60-120 mins */
</style>
</head><body>
<h1>Oracle EBS R12.2 – Individual Patch Application Duration Report</h1>
<p>Generated on: $(date '+%d-%b-%Y %H:%M:%S') | Instance: $TWO_TASK | Host: $(hostname)</p>
<table>
<tr><th>Instance</th><th>Session ID</th><th>Phase</th><th>Patch</th><th>Start</th><th>End</th><th>Duration (min)</th></tr>
EOF
find "$ADOP_LOG_BASE" -type d -name "[0-9]*_[0-9]*" | sort | while read SESSION_DIR; do
SESSION_ID=$(basename "$SESSION_DIR")
INSTANCE="${TWO_TASK:-$(echo $SESSION_DIR | awk -F'/' '{print $(NF-3)}')}"
# Look for apply logs in both run and patch edition
for PHASE in apply finalize cutover cleanup; do
PHASE_DIR="$SESSION_DIR/${PHASE}"
[ ! -d "$PHASE_DIR" ] && continue
# Most accurate timestamps come from the driver log
DRIVER_LOG=$(find "$PHASE_DIR" -name "*_apply_*.log" | head -1)
[ -z "$DRIVER_LOG" ] && continue
echo "Processing $SESSION_ID - $PHASE ..." >> "$TEMP_LOG"
awk -v inst="$INSTANCE" -v sid="$SESSION_ID" -v phase="$PHASE" '
BEGIN {
in_patch = 0
start_time = ""
}
/Applying patch/ || /Start time:/ {
if ($0 ~ /Applying.*patch [0-9]+/) {
if (in_patch && start_time != "") {
end_time = $1 " " $2
split(start_time, s, /[:.]/)
split(end_time, e, /[:.]/)
duration = (e[1]*3600 + e[2]*60 + e[3]) - (s[1]*3600 + s[2]*60 + s[3])
mins = int(duration/60)
printf "%s,%s,%s,%s,%s,%s,%.1f\n", inst, sid, prev_phase, prev_patch, start_time, prev_end_time, mins >> "'"$CSV_FILE"'"
}
# New patch starts
match($0, /patch [0-9]+/, a)
prev_patch = a[0]
gsub(/patch /,"",prev_patch)
start_time = $1 " " $2
prev_phase = phase
prev_end_time = ""
in_patch = 1
}
}
/End time:/ {
if (in_patch) {
prev_end_time = $3 " " $4
}
}
END {
if (in_patch && start_time != "" && prev_end_time != "") {
split(start_time, s, /[:.]/)
split(prev_end_time, e, /[:.]/)
duration = (e[1]*3600 + e[2]*60 + e[3]) - (s[1]*3600 + s[2]*60 + s[3])
mins = int(duration/60)
printf "%s,%s,%s,%s,%s,%s,%.1f\n", inst, sid, phase, prev_patch, start_time, prev_end_time, mins >> "'"$CSV_FILE"'"
}
}
' "$DRIVER_LOG"
done
done
# Generate HTML rows from CSV
tail -n +2 "$CSV_FILE" | sort -t',' -k7nr | awk -F',' '
{
duration = $7
rowclass = ""
if (duration > 120) ? rowclass="slow" :
(duration > 60) ? rowclass="medium" : rowclass=""
print "<tr class=\"" rowclass "\">",
"<td>" $1 "</td><td>" $2 "</td><td>" $3 "</td>",
"<td>" $4 "</td><td>" $5 "</td><td>" $6 "</td>",
"<td><b>" $7 " min</b></td></tr>"
}' >> "$HTML_FILE"
cat << 'EOF' >> "$HTML_FILE"
</table>
<br>
<p><b>Color legend:</b> <span style="background:#fadbd8;padding:3px">> 120 min</span>
<span style="background:#fef9e7;padding:3px">60–120 min</span></p>
<p>Report & CSV also saved in /tmp with timestamp <b>adop_patch_timing_report_'$REPORT_DATE'</b></p>
</body></html>
EOF
# === Send email (your usual format) ===
SUBJECT="ADOP Patch Timing Report – $(date '+%d-%b-%Y')"
RECIPIENTS="your.team@company.com" # change as needed
(
echo "Subject: $SUBJECT"
echo "MIME-Version: 1.0"
echo "Content-Type: text/html"
echo
cat "$HTML_FILE"
) | /usr/sbin/sendmail "$RECIPIENTS"
echo "Report completed → $HTML_FILE and $CSV_FILE"
echo "Email sent to $RECIPIENTS"
# Optional: auto-clean reports older than 30 days
find /tmp -name "adop_patch_timing_report_*" -mtime +30 -exec rm {} \;
exit 0
No comments:
Post a Comment