Wednesday, August 30, 2017

WFA Command - advanced logging

I created a powershell module once (somewhere in this blog) that allows you to do some powerfull logging.  I always planned on showing you how it's done as a WFA command.

For my NetApp Insight sessions, I had to create such a command, and I'm already posting it here.

Logging on 3 levels :
- Database
- Logfile
- Eventviewer


How to use :

- Type : debug, info, warn, error or fatal
- Message : the actual logging message
- Cr : A Change Request, I thought it might come in handy, you could leave it out if you want
- LogToFile : boolean, if you want a logfile too
- LogToEventViewer : boolean, if you want to log to the eventviewer
- EventId : in case of eventviewer, you can set the eventid
- Category : in case of eventviewer, you can set the category (leave default, unless you know about this)

Testing

- $interactive : set to true if you want to test this in powershell first (run as admin !!)

don't forget to set you shell in WFA debug mode.
http://www.wfaguy.com/2017/08/debug-wfa-in-your-powershell-editor.html

Scheme

now set to "log", so I assumed you have created the scheme "log" and dictionary "log".

$MySqlDatabase : use this to set change the scheme

The dictionary

- log
     - timestamp (datetime)
     - cr (string)
     - message (string 8000)
     - type (enum : debug,info,warn,error,fatal)
     - workflowname
     - jobid (integer)
     - user (string)

The code :


param (

    [parameter(Mandatory=$true, HelpMessage="Type")]
    [validateset('debug','info','warn','error','fatal')]
    [string]$Type,

    [parameter(Mandatory=$true, HelpMessage="Message")]
    [string]$Message,

    [parameter(Mandatory=$true, HelpMessage="Change Request")]
    [string]$Cr,

    [parameter(Mandatory=$false, HelpMessage="Log to local logfile ?")]
    [boolean]$LogToFile=$false,

    [parameter(Mandatory=$false, HelpMessage="Log to event viewer ?")]
    [boolean]$LogToEventViewer=$false,
 
    [parameter(Mandatory=$false, HelpMessage="Event viewer - Event id")]
    [int]$EventId=1,
  
    [parameter(Mandatory=$false, HelpMessage="Event view - Category")]
    [int]$Category=0 
)

# Default credentials for playground database
$MySQLAdminUserName = 'wfa'
$MySQLAdminPassword = 'Wfa123'
$MySQLDatabase = 'log'
$MySQLHost = "localhost"

# fix single quotes
$SqlMessage = $Message -replace "'","''"

# log message format
$Message = "[$User][$Cr][$WorkflowName][$JobId] - $Message" 

[string]$mySqlDateTime = get-date -Format "yyyy-MM-dd HH:mm:ss"

$interactive = $false     # set this if your are running locally in the shell

# ================================================================
# ==   Get Environment variables (script location, host & port)
# ==   Note : set the datasource port to 1, to trigger debug mode
# ================================================================
 
if(!$interactive){
    Set-Variable -Name SCRIPT_PATH -Value (Split-Path (Resolve-Path $myInvocation.MyCommand.Path)) -Scope local
    $User = $(Get-WfaRestParameter "userName")
    $Workflowname = $(Get-WfaRestParameter "workflowName")
    $Jobid = $(Get-WfaRestParameter "jobId")
}else{
    # auto load wfa profile
    $profilecheck = Get-Item function: | ?{$_.Name -eq "Connect-WfaCluster"}
    if(-not $profilecheck){
        Write-Host "Loading WFA profile..." -ForegroundColor Yellow
        cd 'C:\Program Files\NetApp\WFA\PoSH\'
        . '.\profile.ps1'
    }
    Set-Variable -Name SCRIPT_PATH -Value 'C:\Program Files\NetApp\WFA\jboss\standalone\tmp\wfa' -Scope local
    cd "$SRIPT_PATH"
    $User = "dummy_user"
    $Workflowname = "dummy_workflow_name"
    $Jobid = "123"
}

# store to db
Get-WFALogger -Info -message $("Preparing Command")
$cmd1 = "INSERT INTO $MySQLDatabase.log SET " + 
    "User='$User',"+
    "Workflowname='$Workflowname',"+
    "Jobid=$Jobid,"+
    "Type='$Type',"+
    "Message='$SqlMessage'," +
    "Timestamp='$mySqlDateTime'," +
    "Cr='$Cr'"
Get-WFALogger -Info -message $("Executing SQL: " + $cmd1)
Invoke-MySqlQuery -query $cmd1

# Event Viewer Function
function SetLog4NetEventLogEventId{
    Param
    (
        [Parameter(Mandatory=$true)]
        [int] $EventId,
        [Parameter(Mandatory=$true)]
        [int] $Category
    )
    [log4net.ThreadContext]::Properties.Item("EventID") = $EventId
    [log4net.ThreadContext]::Properties.Item("Category") = $Category
}


if($LogToFile -or $LogToEventViewer){
 $LoggerName = $MySQLDatabase
 $dllLocation = $SCRIPT_PATH + "\..\..\..\..\Posh\Modules\DataOntap\log4net.dll"
 $logfile = $SCRIPT_PATH + "\..\..\log.war\jboss\" + $LoggerName + ".logger.log"

 # Initialize log4net
 [Reflection.Assembly]::LoadFrom($dllLocation) | Out-Null

 #Reset the log4net configuration
 [log4net.LogManager]::ResetConfiguration()

 #Define new logger for this module only
 try{
  [log4net.LogManager]::CreateRepository("$($LoggerName)Logger")
 }catch{
  Get-WfaLogger -warn -message "[LOG] Repository already created"
 }
 [log4net.Repository.Hierarchy.Hierarchy]$repository = [log4net.LogManager]::GetRepository("$($LoggerName)Logger")

 # create new appenders
 $repository.Root.RemoveAllAppenders();

 if($LogToFile){
  # create rolling file logging
  Get-WfaLogger -info -message "[LOG] LogFile path is : '$logFile'"
        try{
      New-Item -Path $logFile -type file -EA Stop
        }catch{
            if($_.Exception -match "denied"){
                Get-WfaLogger -warn -message "[LOG] No access to write log file"
            }else{
                Get-WfaLogger -warn -message "[LOG] $($_.Exception)"
            }
        }
  $logPattern="%d %w %-5p %c : %m%n"
  $rollingLogAppender = new-object log4net.Appender.RollingFileAppender
  $rollingLogAppender.MaximumFileSize = "50MB"
  $rollingLogAppender.Name = "file"
  $rollingLogAppender.File = $logFile
  $rollingLogAppender.RollingStyle = "Size"
  $rollingLogAppender.StaticLogFileName = $true
  $rollingLogAppender.MaxSizeRollBackups = "20"
  $rollingLogAppender.Layout = new-object log4net.Layout.PatternLayout($logPattern)
  $rollingLogAppender.Threshold = [log4net.Core.Level]::Debug
  $rollingLogAppender.ActivateOptions()
  $repository.Root.AddAppender($rollingLogAppender)
  Get-WfaLogger -info -message "[LOG] File Logger initialized"
 }


 if($LogToEventViewer){
  # create eventlog logging
  $eventAppender = new-object log4net.Appender.EventLogAppender
  $eventAppender.Name = "event"
  $eventAppender.ApplicationName = "$($LoggerName)"
  $eventAppender.EventId = 1
  $eventAppender.Layout = new-object log4net.Layout.PatternLayout($eventPattern)
  $eventAppender.Threshold = [log4net.Core.Level]::Debug
  $eventAppender.ActivateOptions()
  $repository.Root.AddAppender($eventAppender)
  Get-WfaLogger -info -message "[LOG] Event viewer Logger initialized"
 }
 
 # mark as configured
 $repository.Configured = $true
 
    $logg=[log4net.LogManager]::GetLogger("$($LoggerName)Logger","$($LoggerName)") 
    Get-WfaLogger -info -message "[LOG] Logger initialized"

 if($LogToEventViewer){
        SetLog4NetEventLogEventId -EventId $EventId -Category $Category
 }
 
 switch($Type){
        "Debug"{
            $logg.Debug($Message)
            Get-WfaLogger -info -message "[LOG][$Type] - $Message"
        }
        "Info"{
            $logg.Info($Message)
            Get-WfaLogger -info -message "[LOG][$Type] - $Message"
        }
        "Warn"{
            $logg.Warn($Message)
            Get-WfaLogger -info -message "[LOG][$Type] - $Message"
        }
        "Error"{
            $logg.Error($Message)
            Get-WfaLogger -info -message "[LOG][$Type] - $Message"
        }
        "Fatal"{
            $logg.Fatal($Message)
            Get-WfaLogger -info -message "[LOG][$Type] - $Message"
        }
    }  
  
}
Download dar

No comments :

Post a Comment