PRTG has many standard sensors, but one I was always missing is a daily page count compare. The standard printer sensor gives you a total page count – but this to some extend will always be a graph that only will go up. You can only estimate the total page counts in those graphs.
If you ever looked in to the IT Assets database project, you will see that in the Printers area there is a possibility to enable detailed graphs for relative page counts.
Why is this important you might wonder. The answer is simple, as an IT Manager you need to know if a certain kind of a printer makes sense at a certain location. If you have a low end printer for only casual print-outs but you have a total over e.g. 10,000 pages printed every month, you might need to reconsider the printer model. The reasons would likely be:
- higher cost per page
- constant toner exchange of a compared more expensive toner cartridge
- maintenance cost
- you might need to constantly maintenance the printer
- the cost for the maintenance kit are relatively high
- downtime issues
- due to toner empty
- printer needs maintenance again
- less pages in paper tray
On the other hand, a printer might also be overkill for a certain area and not be cost efficient. Those conditions also might change over time of course. Further is there often the question – is a single area printer (copier) better or multiple smaller printers. This of course can go pretty far and you want to consider Lean processes, Six Sigma guidelines and others along with this data.
How ever, I started a first draft of a script that provides me at least the total page count relative to each day in PRTG. This sure is not as efficient yet as I do this in the IT Assets database printer module, where I collect data e.g. every 30 minutes in a huge table and then later calculate all the data in a daily range respective monthly range while collecting total page counts and possibly counts per copy vs. print outs and additionally color vs. black and white print. But at least it is a start.
Below you find the first draft of this script.
One thing to know – you will need to run the following command in order to install the PowerShell SNMP module on your PRTG probing server:
1 | Install-Module -Name SNMP |
The current version of the PRTG script:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 | #For PRTG - default parameter list: #-deviceID %deviceid -targetHost '%host' -OID '1.3.6.1.2.1.43.10.2.1.4.1.1' #find a list with OID examples at the following link as they differ by vendor and partly model #https://www.it-admins.com/it-assets-database/online-manual/printers/ param( [Parameter( Mandatory = $true )][int]$deviceID, [Parameter( Mandatory = $true )][string]$targetHost, [Parameter( Mandatory = $true )][string]$OID = "", [string]$Community = "public" ) Import-Module -Name SNMP [string]$ErrorText = "" #will hold error information to be returned to PRTG text field / sensor message [int]$ErrorValue = 0 #default no errors initiated with 0 (0 = OK | 1 = Warning | 2 = Error) [string]$LogFile = "$PSScriptRoot\PrinterLog_$deviceID.log" [int]$result = -2 #standard response would be negative 2 as initialized integer value try{ $result = (Get-SNMPdata -IP $targetHost -OID $OID -Community $Community).Data #if no error occured, we have the current page count as a result } catch { $result = -1 #if any error happened, we now have the result set to negative 1 $ErrorText += "error: can't read SNMP OID value from device " $ErrorValue = 2 } [int]$returnValue = 0 #default return value, integer, initialized with 0 [string]$LogFileContent = -1 #default logfilecontent is integer, intialized with negative 1 [string]$LogFileDate [int]$LogFileCount = -1 if ($result -gt 0) { #we seem to have a page count from SNMP if (Test-Path $LogFile -PathType Leaf){ #we do have an exisiting LogFile try{ $LogFileContent = Get-Content $LogFile -Raw if ($LogFileContent.Length -gt 0){ $LogFileDate = $LogFileContent.Split("|")[0] $LogFileCount = $LogFileContent.Split("|")[1] } else { #LogFile empty $LogFileCount = 0 $ErrorText += "warning: initial run or no logfile yet " $ErrorValue = 1 } } catch { $LogFileCount = -2 #negative 2 as error catch } finally { if ($LogFileCount -gt 0){ #no error occured as for the LogFile reading if (($result - $LogFileCount) -gt -1){ #it should be either the same value or higher then the last logfile value $returnValue = $result - $LogFileCount } else { #LogFile value is higher then current count - this is weird #still returning this - but it will show a negative count and should raise a flag $returnValue = $result - $LogFileCount $ErrorText += "error: logfile value higher then current printer read " $ErrorValue = 2 } } else { #there was some kind of error in the LogFile read - not an integer value or new Logfile started and result was 0 $ErrorText += "error: can't read logfile for data compare " $ErrorValue = 2 } } } else { #no LogFile yet - will need one but return value as difference initially will stay 0 #we set the LogFileContent to 0 as this is the current status $LogFileCount = 0 $ErrorText += "warning: initial run or no logfile yet or wrong data format " $ErrorValue = 1 } #we need to write the positive SNMP OID result to the LogFile #but only if the date differs more then 1x day [bool]$WriteLog = $false [string]$CurrentDate = (Get-Date -Format yyyy-MM-dd) if ($LogFileDate.Length -gt 0){ try{ if ((New-TimeSpan -Start $LogFileDate -End $CurrentDate).Days -gt 1){ #date difference more then 1 day $WriteLog = $true } else { #date difference not sufficient - same day? Future? if ((New-TimeSpan -Start $LogFileDate -End $CurrentDate).Days -lt 0){ #LogFile newer then current date? That's just wrong $WriteLog = $true $ErrorText += "warning: Logfile date above current date $LogFileDate - rewriting log" $ErrorValue = 1 } else { #not greater then 1 day (0 and 1) or less must be equal as a result... #nothing to do as WriteLog is initialized false } } } catch { #couldn't compare the date - let's write the Log to be save $WriteLog = $true } } else { #LogFileDate length 0 means we need to write a logfile as it might not exist $WriteLog = $true } if ($WriteLog){ try { Set-Content -Path $LogFile -Value "$CurrentDate|$result" $LogFileDate = $CurrentDate } catch { #there was an issue writing to the LogFile $ErrorText += "error: can't write to logfile " $ErrorValue = 2 } } } else { #no pagecount available due to errors or issues #uncomment the next line for debugging only #$returnValue = $result #the returnValue will now show the current result value and point therefor to the error section $ErrorText += "error: no pagecount available " $ErrorValue = 2 } #Assuming no errors - the text result will be the last LogFile date if ($ErrorText.Length -eq 0){ $ErrorText = "Last LogFile write date: $LogFileDate" } $XML = "<prtg> <result> <channel>last relative Page Count</channel> <value>$returnValue</value> </result> <result> <channel>last total from Printer</channel> <value>$result</value> </result> <result> <channel>last total from LogFile</channel> <value>$LogFileCount</value> </result> <result> <channel>Script Error Status</channel> <value>$ErrorValue</value> <LimitMode>1</LimitMode> <LimitMaxWarning>0</LimitMaxWarning> <LimitMaxError>1</LimitMaxError> </result> <text>$ErrorText</text> </prtg>" Function WriteXmlToScreen ([xml]$XML) #just to make it clean XML code... { $StringWriter = New-Object System.IO.StringWriter; $XmlWriter = New-Object System.Xml.XmlTextWriter $StringWriter; $XmlWriter.Formatting = "indented"; $xml.WriteTo($XmlWriter); $XmlWriter.Flush(); $StringWriter.Flush(); Write-Output $StringWriter.ToString(); } WriteXmlToScreen $XML; |