Windows Printers - enhanced agent check via plugin

Hi,

I’ve rewritten the Win_printers.ps1 to surface more data more quickly, but now am stuck…

I had to have a look as the no. of printers on my server was breaking the script (taking 5+ minutes to run). So I worked around the 2nd data set and created a table with status 1 for all and showing the number of jobs in the print queue as the only thing worth working with.

While doing this I noticed that the Get-CimInstance Win32_PerfFormattedData_Spooler_PrintQueue command surfaced different types of error as well as number of prints and number of pages printed (and more). So I wrote this to create the table including the extra data:

Get-CIMInstance Win32_PerfFormattedData_Spooler_PrintQueue | Select Name, Jobs, @{name="PrinterStatus";exp={0}}, @{name="DetectedErrorState";exp={0}}, JobErrors, JobsSpooling, MaxJobsSpooling, TotalJobsPrinted, TotalPagesPrinted  | Sort Name | format-table

But now don’t know what to do with it!!

I was trying to find the win_printers.py server component/agent based plugin but can’t find it (admittedly there is a lot to sift through) but there is nothing in the directory: local/lib/check_mk/base/plugins/agent_based

I know it is working, but can’t see where (or even if) there the server side component of this check is! If I can find it I’m convinced I can rewrite it (or copy it) to surface the additional data I’m interested in…

Can anyone help?

Cheers

Andy

Oh… I should also mention (to avoid confusion) that I’ve moved to using Get-CIMInstance instead of Get-WMIObject.

Can you please post the completed reworked script. Then i can have a look at the output and the check together.
The server side component should not so hard to modify.

Code is below (with my comments included), I’ve currently got it creating the same output as the original, but with the PrinterStatus and DetectedErrorState set to 1 (If I could NOT include these I’d be happy).

Line 22 below is commented out but would include all the columns I’d like to use. I also aim to graph the outputs, but it looks like I’ll need to use Grafana for this…

$CMK_VERSION = "2.1.0p21"
#
#  http://blogs.technet.com/b/heyscriptingguy/archive/2006/12/04/how-can-i-expand-the-width-of-the-windows-powershell-console.aspx
# Output is a 4 column table of (Name: str, Jobs: int, PrinterStatus: int, Detectederrorstate: int)
# Name is a string that may contain spaces
# <<<win_printers>>>
# Printer Stockholm                     0                   3                   0
# WH1_BC_O3_UPS                         0                   3                   0

$pshost = get-host
$pswindow = $pshost.ui.rawui

$newsize = $pswindow.buffersize
$newsize.height = 300
$newsize.width = 150
$pswindow.buffersize = $newsize

Write-Host "<<<win_printers>>>"
# $Data_Set1 = Get-WMIObject Win32_PerfFormattedData_Spooler_PrintQueue | Select Name, Jobs | Sort Name
# $Data_Set2 = Get-WmiObject win32_printer | ?{$_.PortName -notmatch '^TS'} | Select Name, @{name="Jobs";exp={$null}}, PrinterStatus, DetectedErrorState | Sort Name
#Replacing Data_set1 and 2 with a new data set 2:
# $Data_Set2 = Get-WMIObject Win32_PerfFormattedData_Spooler_PrintQueue | Select Name, Jobs, @{name="PrinterStatus";exp={0}}, @{name="DetectedErrorState";exp={0}}, JobErrors, JobsSpooling, MaxJobsSpooling, TotalJobsPrinted, TotalPagesPrinted  | Sort Name

# taking off the additioanl unneeded columns
$Data_Set2 = Get-CimInstance Win32_PerfFormattedData_Spooler_PrintQueue | Select Name, Jobs, @{name="PrinterStatus";exp={1}}, @{name="DetectedErrorState";exp={1}} | Sort Name

#
#  Merge the Job counts from Data_Set1 into Data_set2
#
#  Both "lists" are sorted into ascending Name order, so matching and merging is simple
#
# Don't bother with this
#$i = 0
#$d1 = $data_set1[0]

#foreach ($d2 in $Data_Set2) {
  #
  #  iterate through data_set1 elements until their "Name" >= the curent data_set2 element's "Name"
  #
  #while ($d1 -ne $null -and $d1.Name -lt $d2.Name) {
	#$d1 = $data_set1[++$i]
#  }
  #
  #  if we have a match, store the "Jobs" value from data_set1 in data_set2,
  #  and move on to the next data_set1 element
  #
  #  if we don't have a match, data_set1 element's "Name" > data_set2 element's "Name",
  #  so keep the data_set1 element and go on to the next data_set2 element
  #
  #if ($d1.name -eq $d2.Name) {
  #  $d2.Jobs = $d1.Jobs
  #  $d1 = $data_set1[++$i]
 # }
# }
#
#  If the "Jobs" element is Null, the printer was found in data_set2 but not in data_set1, so ignore it
#
# So we've replaced all the 'complex' faffing with one command line I don't know what CheckMK will do with the rest of the data or if it'll break everything.. 
# Going to have to find a tutorial to write add-ins
$Data_Set2 | where { $_.Jobs -ne $null } | format-table -HideTableHeaders

Is there a way to graph the data that is coming out of these checks? I’ve installed Grafana, but it doesn’t look like I can grab the metric…I had read that CheckMK stores 4 years worth of history for each metric, so it should be possible to graph any of the metrics… Or am I misunderstanding/expecting too much of RAW?

Interestingly (or not as the case may be) there is a way to use CIM to gather data from multiple sources in one script:

$s = New-CimSession -ComputerName Server1, Server2, Server3
Get-CIMInstance Win32_PerfFormattedData_Spooler_PrintQueue -CimSession $s| Select Name, Jobs, JobErrors, JobsSpooling, MaxJobsSpooling, TotalJobsPrinted, TotalPagesPrinted | Sort Name | format-table

Which creates a (seemingly deduped) table showing all the printers across all the hosts specified in alphabetical order. Thus not needing the Agent on all hosts…

Hi @Argon0

yes, I think you should be able to graph any metrics your Check produces. See more here (links to the right section): Writing your own check plug-ins

Hope this helps,
Elias

Not so easy we speak here about the windows_printers plugin and it’s performance problems.

I stand corrected, then :smiley:

You can do it this way but then you have really a own version of the win_printers.ps1 script.
Or one option would be to extend the win_printers.ps1 with a config file where you can define the hosts to check. If no config file is found it checks the local server only. With such an extension it would possible to keep it compatible with the original version.

That is what I thought, or, if you’re going to have to edit a local config file anyway, you could just make it so there was a commented/documented section in the PS1 file to specify servers to poll, or don’t do anything and it does local.

This would amount to the same thing - a better way would be to define variables from the Web front end (WATO?).

@andreas-doehler @elias.voelker Gents,

Where woudl I find the RRD files created for these services?

My Host based ones are in here: /opt/omd/sites/RSFT/var/pnp4nagios/perfdata/%Hostname%

Should the Service ones be in here too? (I can’t find them… I think they should be called “printer %printername%”)