Let’s start this off with a bang

If, like most of us, part of your day to day role is support – one of the key advantages of using ODI in your overnight process is to have the full gambit of ODI error handling available to you. Errors are nicely caught, with email warnings for failures in batch processes basically a default state.

However, what happens if ODI isn’t part of your implementation? What happens if the back end is basically a bunch of batch/maxl scripts hanging together (no matter how elegant it is). If it is the latter, at best you’re unlikely to have an easy method to trap errors and send notifications to the support team and at worst, you may not have any automated notification at all!

So your options are:

  1. Hope against hope that you never ever have any errors in your overnight processes
  2. Write your own error handling piece and include it in the processing

Rolling Your Own

So you’ve decided to steal cable write your own. While this process would be possible in batch – certainly you’re likely to be better off selecting a more advanced language with slightly better handling of strings (See also: Java/Perl/Powershell/Cygwin/VBA).

I’ve gone with Powershell: slightly because I’m generally on Windows environments, somewhat because it’s fairly decent at string manipulation and mostly because it’s one of the few languages I know.

Code Overview

So – to start with, basic documentation and variable structure. I’ve written this to poll through a folder containing log files (rules file errors, maxl return errors and an archive copy of all of the Essbase Log files from the previous day). These have been moved to this folder by earlier maxl/batch steps, mostly by using STDERR outputs.

PowerShell_ErrorHandle_1

Loop-de-Loop

For each of the files in the log folder it scans for any lines containing errors and pushes the entire line to a central log file.

I’ve added suppression to deal with a majority of ‘false positive’ errors – primarily related to errors in the Essbase log for Smartview user-side errors like ‘you’ve-got-suppression-on-by-default-and-your-top-level-retrieve-is-blank’ (man, if I had a nickel for that one…).

PowerShell_ErrorHandle_2

Letting you Know

Finally it checks if the log file isn’t blank and emails it through to the email addresses listed. The primary reason I’ve got the error suppression above is to make sure you’re only receiving automated emails when something has gone wrong. I find too many false positives in your inbox mean that the actual errors occasionally get lost in the underflow.
PowerShell_ErrorHandle_3

Code
Finally – the full code in all it’s glory. 20 Lines of working code all up!

# Name: Hyperion Mail Error script
# Purpose: Sends an email to the support team if there are any errors in the overnight
# Author: Peter Nitschke - M-Power Solutions

# Change Control
# When Who What
# 19/07/2014 PN Created

# INSTRUCTIONS
# Script is built as a powershell command to be called at the end of the overnight
# Script will poll through the available files in the log locations folder searching for errors
# Some errors are suppressed (var SUPPRESSEDERROR), additional error codes to be suppressed can be added to this variable
# If any errors are found, it will automatically send an email through to the support team

Set-Variable ERRORFOLDER “..\Errors\OvernightErrors”
Set-Variable ERRORLOG “..\Logs\OvernightErrors.log”

#ERRORS TO BE SUPPRESSED
#1020010 No data was generated: Suppress Missing = [%s], Zeros = [%s]. Sheet not overwritten.
#1020011 Maximum number of rows [%s] exceeded [%s].
#1020012 Maximum number of columns [%s] exceeded [%s].
Set-Variable SUPPRESSEDERROR “1020007”,”1020011″,”1020012″

# Create or clear the status file
new-item $ERRORLOG -type file -force

#For all of the error log files
(Get-ChildItem $ERRORFOLDER |

#Create array of objects
Foreach-object{
#Define the name and content
$name = $_.name
$content = Get-Content $_.FullName
#look for errors in the file
switch(($content | Select-string “Error” | Select-string $SUPPRESSEDERROR -NotMatch | measure | select -exp count) -gt 0) {
#if errors found, print the filename and the error
True {Echo $name >> $ERRORLOG
$content | Select-string “Error” | Select-string $SUPPRESSEDERROR -NotMatch >> $ERRORLOG
Echo “” >> $ERRORLOG}
}
}
)
#Once the loop is finished, check if the status file has any content and email if true
If ((Get-Content $ERRORLOG) -eq $Null) {
}
Else{
#Calling send email function
$smtp = “mail.gmail”
$emailto = “[email protected]
$emailfrom = “[email protected]
$subject = “Hyperion Overnight – Errors” + (get-date -f “dd/MM/yyyy”)
$body =(get-content $ERRORLOG | Out-string)

send-mailmessage -to $emailto -from $emailfrom -smtp $smtp -subject $subject -body $body
}

As an aside, I’m aiming to provide full code snippets as often as possible. Most of my learning over the years has been picking up code from everywhere and jerry-rigging it all together. (Subnote: greatest wikipedia ‘Not to be confused with’ ever!). Please feel free to use, send to colleagues, share with friends, or claim as your own to help you pick up ladies.

However, standard rules of never putting something into your environment that you haven’t first tested and understood apply. I’m not to blame if it takes these lemons and burns your house down.

Conclusions

Hopefully this has given you some ideas as to adding basic error handling to your own environments, allowing you to both rest easier at night and feel like you’re always one step ahead of any problems as they occur!

Cheers
Pete


Warning: Undefined array key "share_counts" in /var/www/wp-content/plugins/simple-social-buttons/simple-social-buttons.php on line 477

Fatal error: Uncaught TypeError: Cannot access offset of type string on string in /var/www/wp-content/plugins/simple-social-buttons/simple-social-buttons.php:477 Stack trace: #0 /var/www/wp-includes/class-wp-hook.php(324): SimpleSocialButtonsPR->ssb_footer_functions('') #1 /var/www/wp-includes/class-wp-hook.php(348): WP_Hook->apply_filters(NULL, Array) #2 /var/www/wp-includes/plugin.php(517): WP_Hook->do_action(Array) #3 /var/www/wp-includes/general-template.php(3066): do_action('wp_footer') #4 /var/www/wp-content/themes/wordstar/footer.php(59): wp_footer() #5 /var/www/wp-includes/template.php(810): require_once('/var/www/wp-con...') #6 /var/www/wp-includes/template.php(745): load_template('/var/www/wp-con...', true, Array) #7 /var/www/wp-includes/general-template.php(92): locate_template(Array, true, true, Array) #8 /var/www/wp-content/themes/wordstar/single.php(86): get_footer() #9 /var/www/wp-includes/template-loader.php(106): include('/var/www/wp-con...') #10 /var/www/wp-blog-header.php(19): require_once('/var/www/wp-inc...') #11 /var/www/index.php(17): require('/var/www/wp-blo...') #12 {main} thrown in /var/www/wp-content/plugins/simple-social-buttons/simple-social-buttons.php on line 477