TIPS & TRICKS

Windows Print Monitoring in Splunk 6

Splunk 6 has been out almost six months and I have not yet finished covering all the new Windows features. Let’s continue doing that by looking at print monitoring. If you have ever wanted to do charge back reporting for print jobs but lacked the data, then this is for you. The Windows Print Monitor is a new data input in the Splunk 6 Universal Forwarder (ok – it’s also available on Splunk Enterprise).

The idea of this is fairly simple. Install a Splunk 6 Universal Forwarder on your print servers, set up the data input and you will get data. There are two types of data you can get – inventory type information such as the printers, the ports they are attached to (on Windows, servers always connect to printers via ports – even on the network) and the drivers running them are the first. You can monitor this information by enabling them in the inputs.conf like this:

[WinPrintMon://printer]
type=printer
interval=600
baseline=1
disabled=0

[WinPrintMon://driver]
type=driver
interval=600
baseline=1
disabled=0

[WinPrintMon://port]
type=port
interval=600
baseline=1
disabled=0

You will note that there is an interval, measured in seconds. This allows you to capture changes within a certain time period. Print Servers are generally not busy servers so a low interval is generally ok. However, the process does iterate over all the printer objects in the server, so it depends on your environment. Since I generally recommend you install the Splunk Add-on for Windows on all Windows hosts, you can put this in the local inputs.conf of that add-on. You will get events like this from these inputs:

04/21/2014 13:51:59.486
operation=set
type=Printer
ComputerName=ops-sys-001
printer=HP LaserJet M3035 mfp PCL6
share=
port=IPAddress
driver=HP LaserJet M3035 mfp PCL6
comment=None
location=
separate_file=
print_processor=hpzppwn7
data_type="RAW"
parameters=
status="normal"
attributes=979
priority=6
default_priority=2
jobs=8
average_PagePerMinute=73

Note that the type field is Printer. The other type fields for inventory are PrintDriver and PrintPort. You can use these events to create inventory type lookups of all the information. When doing this, I would not include the dynamic fields – jobs or average_PagePerMinute – these would cause unnecessary updates to your lookup file. We’ve discussed generating lookup files in prior blog posts, so I won’t go over them here.

The (to my mind) more interesting input is the Job input. You define it like this:

[WinPrintMon://jobs]
type=job
interval=60
baseline=0
disabled=0

This writes out an event per print job and they look something like this:

04/21/2014 13:52:19.486
operation=add
type=PrintJob
printer=HP LaserJet M3035 mfp PCL6
ComputerName=ops-sys-001
machine=ops-sys-001
user=adrian
document=wallstreetjournal.htm
notify_name=adrian
JobId=35
data_type="NT EMF 1.008"
print_processor=hpzppwn7
parameters=
driver_name="HP LaserJet M3035 mfp PCL6
status=printing
priority=5
total_pages=9
size_bytes=397039
submitted_time=04/21/2014 13:51:40.131
page_printed=7

Producing a report by user for the number of pages printed on a per-printer basis is fairly easy:

sourcetype=WinPrintMon type=PrintJob operation=add | stats sum(page_printed) by user

However, let’s go a little bit further. Let’s say that we have generated a lookup table that has three fields, like this:

host,printer,cost
ops-sys-001,HP LaserJet M3035 mfp PCL6,0.02

We now now augment our search as follows:

sourcetype=WinPrintMon type=PrintJob operation=add
    | lookup printerCost host,printer OUTPUT cost
    | eval cost=if(isnull(cost),0.01,cost)
    | eval job_cost=cost * page_printed
    | stats sum(page_printed) as pagecount, sum(job_cost) as total_cost by user

Note our use of the eval to set a default value for cost, just in case one is not specified. We are almost at an ideal search. However, this isn’t suitable as a chargeback report because we want this by department. To turn a user into a department, you can use another lookup or you can use Active Directory:

sourcetype=WinPrintMon type=PrintJob operation=add
    | lookup printerCost host,printer OUTPUT cost
    | eval cost=if(isnull(cost),0.01,cost)
    | eval job_cost=cost * page_printed
    | stats sum(page_printed) as pagecount, sum(job_cost) as total_cost by user
    | rex field=user "^(?[^\\]+)\\(?.*)"
    | ldapfilter domain=$src_nt_domain$ search="(sAMAccountName=$src_user$)" attrs="department"
    | eval department=if(isnull(department),"UNKNOWN",department)
    | stats sum(pagecount) as pagecount, sum(total_cost) as total_cost by department

The additional work separates out the username we get from the WinPrintMon into domain and user, then we use these to create an Active Directory Filter to retrieve the department. Finally, just as in the case of the page cost, we provide a default for the case when the department is not known and do the calculation. You may be wondering why we do stats twice – once at the user level and once at the department level. This is for efficiency. Do you want hundreds of thousands of ldap queries going to Active Directory, or just a couple of hundred? I suspect the latter.

You should now have the capabilities in your hand for providing chargeback reporting of print jobs to departments. With these capabilities, you can provide accounting with a report on a regular basis (as a CSV), provide individual reports for departments as needed and look at individual users.

Splunk
Posted by

Splunk

Join the Discussion