How to count % of difference between two numbers in Powershell - powershell

i'm fairly new to powershell. I have a task to create a script that reads a log of a job run, counts the number of items by line, and then compares that count to a previous run and throws an Event log if the difference in percent exceeds 30 percent.
I'm having some difficulty finding out how to compare the job count run and compare difference in percent.
so far i have this code:
$TodayCount = $todayrun.Count
$YesterdayCount = $yesterdayrun.count
$DifferenceCount = ($TodayCount - YesterdayCount) +1
That counts the number of ints between each too, but i need to find a percentage different between the two runs so I can throw an IF statement that if difference in items is > 30 Write to event log .. for instance today count could equal 2000 lines and yesterday could equal 1800 lines or 2200 .. i just need to store the percentage difference.
Hope that makes sense, and please be gentle :)

To calculate the percentage increase: First, work out the difference (increase) between the two numbers you are comparing. Then divide the increase by the original number and multiply the answer by 100.
I've made an assumption that you would want to check if it's greater than or equal to +30% or less than or equal to -30%.
If you want greater than and less than then change -ge to -gtand -le to -lt respectively.
$TodayCount = $todayrun.Count
$YesterdayCount = $yesterdayrun.count
$DifferenceCount = $TodayCount - $YesterdayCount +1
$percentageDifference = $DifferenceCount / $TodayCount * 100
if(($percentageDifference -ge 30) -or ($percentageDifference -le -30))
{
Write-Output "Percentage difference is +/-30%"
}

Related

Counting date entries from file. - Powershell

I have a file which have several lines with different timestamps, however I want to count the timestamps from the last 15 minutes.
Counting timestamps would be easy enough, but I cannot figure out how to get the timestamps from the last 15 minutes.
Example of timestamps
2020-07-20T18:00:00Z
I have tried several things, but I couldn't get them to work. Perhaps it's just me...
I'm not sure what the formatting in your original file looks like but this code will count the entries within the last 15 minutes.
$lastFifteenMinutesCount = 0
$comparisonDate = [datetime]::UtcNow
Get-Content C:\tmp\overflow\63003625\stuff.txt | % {
if ($_ -match '(\d{4}-\d{2}-\d{2}T\d{1,2}:\d{1,2}:\d{1,2}Z)') {
$sDate = [datetime]::Parse($Matches[1]).ToUniversalTime().AddMinutes(15)
if ($sDate -ge $comparisonDate) {
$lastFifteenMinutesCount++
}
}
}
$lastFifteenMinutesCount

store data by day and hour - powershell

Id like to be able to store, change, and retrieve data by day and hour using powershell.
For instance, I have a list of data from which I can extract the dayOfMonth, hour, max, active, average.
I would like to be able to stick the 3 latter values in an array indexed by day and hour.
The raw data might look like this: (the avg val wouldnt be there yet):
12/13/19,08:13:04,13,13
12/13/19,08:43:04,10,9
12/13/19,09:13:04,11,9
12/13/19,09:43:04,12,7
12/13/19,08:13:04,10,12
12/14/19,08:13:04,8,2
12/14/19,08:43:04,10,4
12/14/19,09:13:04,8,7
12/14/19,09:43:04,11,1
12/14/19,10:13:04,9,7
I wish to be able to store the maxChannel,maxActive, and average, for each hour of each day, so the data in the array would look like this:
day,hr,max,actv,avg
13,8,13,13,11
13,9,12,9,8
13,10,12,2,2
14,8,10,4,3
14,9,11,7,4
14,10,9,7,7
I tried to store it in a previously created array
$arrOut2 = #() #summary data
like this(which needless to say didnt work):
initialize each needed row
ForEach ($line in $arrFile)
{
$arrLine = $line.split(",") #create an array with each word in line its own element
$Date=$arrLine[0]
$Time=$arrLine[1]
$ChanM=$arrLine[2]
$ChanA=$arrLine[3]
$DateA=$Date.Split("/")
$Day=$DateA[1]
$TimeA=$Time.Split(":")
$Hour=[int]$TimeA[0]
$arrOut2 += ,#[$Day][$Hour](0,0,0)
}
ForEach ($line in $arrFile)
{
$arrLine = $line.split(",") #create an array with each word in line its own element
$Date=$arrLine[0]
$Time=$arrLine[1]
$ChanM=$arrLine[2]
$ChanA=$arrLine[3]
$DateA=$Date.Split("/")
$Day=$DateA[1]
$TimeA=$Time.Split(":")
$Hour=[int]$TimeA[0]
IF (($Hour -ge 8) -And ($Hour -lt 17)) {
$AvCnt=$AvCnt+1 #count Intervals for averaging
$AvTot=$AvTot+$ChanA #sum active channels for averaging
$AvgActChan=$AvTot/$AvCnt
IF($ChanC -GT $arrOut2[$Hour][0]){$arrOut2[$Hour][0]=$ChanC} #grab max chanC frm current hr
IF($ChanA -GT $arrOut2[$Hour][1]){$arrOut2[$Hour][0]=$ChanC} #grab max chan Actv frm curr hr
$ArrOut2[$Day][$Hour][2]=$AvgActChan #grab curnt chan Avg Active from current hour
}
}
As you can see in the first forloop, I am attempting to use day and hour as indices. Powershell just doesnt like that - at least in that format.
Does anyone have any ideas of how I can accomplish this? I know I could keep track of the current day and hour, then process it in separate variables, then when I see the day or hour change, write those to a separate array, but the data is quite a bit messier than Ive represented in this example and that would make the whole thing quite messy, when processing it within an array would be so much cleaner.
Appreciate any suggestions
thanks
I would sort it this way:
$data = import-csv data.txt -header date,time,a,b
$data | sort date,time

Summary Percentage Yes vs No

Basically I'm looking for a formula to see how many times Yes was used vs. No.
I have something like this:
(({Command.result} ="Yes") / {Command.result})*100
Which makes sense in my head, but I keep getting:
A number, or currency amount is required.
Your current formula attempts to divide a boolean type through by a string. You can only perform division with numbers.
Instead, create two formulas as individual counts of Yes or No:
#YesCount:
If ({Command.result} = "Yes") Then 1 Else 0
#NoCount:
If ({Command.result} = "No") Then 1 Else 0
For the percentage, create two more formulas:
#YesPercent:
100 / Count ({Command.result}) * Sum ({#YesCount})
#NoPercent:
100 / Count ({Command.result}) * Sum ({#NoCount})

Creating PowerShell if statement for True over time

I have CSV document. Each row of the CSV has a timestamp, along with various performance metrics as they were when recorded at that time.
What I want to be able to do is consume the csv and perform a logic test on it of this kind of nature:
If said metric is above a specified threshold for a specified amount of time = True
I can easily setup a logic statement comparing two numbers/metrics, but I wasn't sure how to add in the component as to whether that condition is true for a certain amount of time.
CSV might look something like this:
time,KB/sec,IOPS,Avg. Latency ms
8/6/2017 10:30,10616.79606,117.2243058,35.63250298
8/6/2017 10:20,11337.82872,149.4084982,28.55670254
8/6/2017 10:17,12276.47016,172.2729097,25.43457276
8/6/2017 10:14,10125.01863,106.2432985,37.38492431
8/6/2017 10:11,12185.1857,127.452136,32.40784617
So I might want to know if the latency is consistently over a certain amount for a couple of hours for instance
I could use a bit of direction and would greatly appreciate any help anyone can provide.
First you need to convert the values from your CSV from string to the proper type (DateTime and double respectively).
Import-Csv 'C:\path\to\your.csv' | ForEach-Object {
$_.time = [DateTime]$_.time
$_.'KB/sec' = [double]$_.'KB/sec'
$_.IOPS = [double]$_.IOPS
...
}
Check if the value in question is above the given threshold. You have 3 cases to cover:
The value exceeds the threshold for the first time: remember the current timestamp.
The value exceeds the threshold and also exceeded it in the previous iteration: calculate the difference between the current timestamp and the previously remembered timestamp. Return $true if the timespan is greater than the maximum duration you want to accept.
The value does not exceed the threshold: forget the previously remembered timestamp.
Well not knowing exactly what you're aiming for perhaps the below will help.
function Monitor-Something
{
Param
(
$Date = '8/6/2017',
$StartTime = '10:17',
$StopTime = '10:30',
$Threshold,
$CSVLogfile = 'C:\temp\test.csv'
)
Begin
{
}
Process
{
$csv = Import-Csv $CSVLogfile
[datetime]$monitorStart = $("$Date $StartTime")
[datetime]$monitorStop = $("$Date $StopTime")
foreach($item in $csv)
{
[datetime]$objDateTime = $item.time
if($objDateTime -gt $monitorStart -and $objDateTime -lt $monitorStop)
{
#do stuff here, compare against your threshold report things build an object for an output
$item.IOPS #This is here just to show you a successful result
}
}
}
End
{
#return some report or object that you can analyze
}
}

In Powershell, How to generate a random variable (exponential) with a specified mean?

I am trying to write a basic simulation (a queue), which relies on generating random expovariates. While Powershell offers a Get-Random function, you can specify a min and a max, but it doesn't have anywhere near Python's random.expovariate(lambd) function.
Supposedly this is the model I should be following: log(1-$u)/(−λ)
The excellent Python documentation has this to say about it:
"Exponential distribution. lambd is 1.0 divided by the desired mean. It should be nonzero. (The parameter would be called “lambda”, but that is a reserved word in Python.) Returned values range from 0 to positive infinity if lambd is positive, and from negative infinity to 0 if lambd is negative.". In another description, "expovariate() produces an exponential distribution useful for simulating arrival or interval time values for in homogeneous Poisson processes such as the rate of radioactive decay or requests coming into a web server.
The Pareto, or power law, distribution matches many observable phenomena and was popularized by Chris Anderon’s book, The Long Tail. The paretovariate() function is useful for simulating allocation of resources to individuals (wealth to people, demand for musicians, attention to blogs, etc.)."
I have tried writing this in Powershell, but my distributions are way off. If I put in a mean of 3 I am getting the results that closely follow the results I should get from a mean of 1. My code is closely modeled on John D. Cook's SimpleRNG C# library.
function GetUniform #GetUint
{
Return Get-Random -Minimum -0.00 -Maximum 1
}
# Get exponential random sample with specified mean
function GetExponential_SpecMean{
param([double]$mean)
if ($mean -le 0.0)
{
Write-Host "Mean must be positive. Received $mean."
}
$a = GetExponential
$R = $mean * $a
Return $R
}
# Get exponential random sample with mean 1
function GetExponential
{
$x = GetUniform
Return -[math]::log10(1-$x) # -Math.Log( GetUniform() );
}
cls
$mean5 = 1
$rangeBottom = 0.0
$rangeTop = 1.0
$j = 0
$k = 0
$l = 0
for($i=1; $i -le 1000; $i++){
$a = GetExponential_SpecMean $mean5
if($a -le 1.0){Write-Host $a;$j++}
if($a -gt 1.0){Write-Host $a;$k++}
if(($a -gt $rangeBottom) -and ($a -le $rangeTop)){#Write-Host $a;
$l++}
Write-Host " -> $i "
}
Write-Host "One or less: $j"
Write-Host "Greater than one: $k"
Write-Host "Total in range between bottom $rangeBottom and top $rangeTop : $l"
For a sample of 1000 and a Mean ($mean5) of 1, I should get (I believe) 500 results that are 1.0 or less and 500 that are greater than 1.0 (1:1 ratio), however I am getting a ratio of about 9:1 with a mean of 1 and a ratio of about 53:47 using a mean of 3.
There is some discussion in this Stack Overflow question with some good background, but it is not specific to Powershell: Pseudorandom Number Generator - Exponential Distribution
I see you are using [Math]::log10() which is logarithm with base 10, and all the functions I see in your links use natural logarithm. You should instead use [Math]::Log() in place of log10. Should do.