What is this?

This knowledgebase contains questions and answers about PRTG Network Monitor and network monitoring in general.

Learn more

PRTG Network Monitor

Intuitive to Use. Easy to manage.
More than 500,000 users rely on Paessler PRTG every day. Find out how you can reduce cost, increase QoS and ease planning, as well.

Free Download

Top Tags


View all Tags

Can I use placeholders in file names to monitor log files?

Votes:

0

I want to monitor log files with PRTG. The names of these files contain the date of their creation, for example, the PRTG webserver log files: prtg20160114.log

Because the File sensor in PRTG does not allow placeholders for the file name, this is not the best option for me to monitor such log files. Is there a way to monitor time stamps and recent changes in the content of files using placeholders in the name for the target file?

custom-script-exe custom-sensor file file-name logfile placeholders powershell prtg

Created on Jan 21, 2016 1:19:39 PM by  Gerald Schoch [Paessler Support]

Last change on Jun 14, 2022 8:19:59 AM by  Brandy Greger [Paessler Support]



27 Replies

Accepted Answer

Votes:

0

This article applies as of PRTG 22

Monitoring files using placeholders

The File sensor can monitor a specific file on a disk if you provide the exact path and file name in the sensor settings. This sensor does not support placeholders to provide the name of the target file. Because log files often have the date of creation in their name, the File sensor might not be perfectly suitable for your scenario.

To monitor log files with a date in their name, for example, you can use a custom sensor with a PowerShell script that allows placeholders for the files that you want to monitor. We provide such a sample script below. You can just use the script and adjust the parameters to your scenario. The script also gives you an idea about how to use placeholders for monitoring files in other scenarios.

For this purpose, you need an EXE/Script Advanced sensor. This sensor can execute the sample script and shows the following data:

  • Number of files that match the pattern of the given file name with placeholders
  • Age of the oldest and newest file matching the name pattern
  • Size of the newest file matching the name pattern
  • Total size of files matching the name pattern

See below for the sample script and how to use it.

How to use the PowerShell script

  1. Open a text editor.
  2. Copy the source code from below and paste it into the editor.
  3. Adjust the default values for $path and $include to your scenario. The script as provided below looks for text files in the \temp folder of the target system. You can also control script execution with the Parameters setting of the sensor.
  4. Save the file with the extension .ps1, for example, logfileStats.ps1.
  5. Copy this file to the \Custom Sensors\EXEXML subfolder of the PRTG data directory on the probe system from which you want to monitor your files.
  6. Add an EXE/Script Advanced sensor to the target device.
    1. Select logfileStats.ps1 from the list of scripts.
    2. Provide the Parameters that you want to use to execute the script. For the sample script, these are the path to the target files and the file name pattern include. For example, to monitor log files of an Apache web server that have the date right before the file extension, you can provide the following parameter that overrides the defaults: -path \\<unc-path to share>\apache-log\*\ -include Webserver.log-*
    3. Adjust all other sensor settings to your needs.
    4. Click Create to add the sensor. The sensor shows the retrieved data in the channels Files matching pattern, Oldest File, Newest File, Newest File Size, and Size (see the bullet points above for detailed descriptions).

Note: We do not provide official support for custom sensors. Of course, you are free to adjust the script according to your needs.

Script

Param(
    [string]$path="C:\temp",
    [string]$include= "*.txt"
    )
 
$result = ""
$size = 0
# Get the list of all files
$files =  Get-ChildItem -Path $path -include $include -Recurse | Sort-Object LastWriteTime
$count = $files.count
if ($count -gt 0)
{
    $newestfilesize = $files[-1].length
    $oldestfile = ("{0:N2}" -f (New-Timespan -end (Get-Date) -start ($files)[0].LastWriteTime).TotalDays).Replace(',','.')
    $newestfile = ("{0:N2}" -f (New-Timespan -end (Get-Date) -start ($files)[-1].LastWriteTime).TotalDays).Replace(',','.')
    foreach ($file in $files) { 
        $size += $file.length
        }
	
 

    $result += @" 
	<result>
		<value>$count</value>
		<unit>count</unit>
		<channel>Number of $($include) Files</channel>
	</result>
	<result>
		<value>$oldestfile</value>
		<unit>custom</unit>
		<CustomUnit>Days</CustomUnit>
		<float>1</float>
		<channel>Oldest File Age</channel>
	</result>
	<result>
		<value>$newestfile</value>
		<unit>custom</unit>
		<CustomUnit>Days</CustomUnit>
		<float>1</float>
		<channel>Newest File Age</channel>
	</result>
	<result>
		<value>$newestfilesize</value>
		<unit>BytesFile</unit>
		<volumeSize>Byte</volumeSize>
		<float>0</float>
		<channel>Newest File Size</channel>
	</result>
	<result>
		<value>$size</value>
		<unit>BytesFile</unit>
		<volumeSize>Byte</volumeSize>
		<channel>Total File Size</channel>
	</result>
	<text>
	OK
	</text>
"@
} else {
    $result += @" 
    <error>1</error>
	<text>
	No file found matching the filter-parameter "$include" at path "$path" 
	</text>
"@
 
}
write-host @"
<?xml version=1.0 encoding=UTF-8 ?>
<prtg>
$result
</prtg>
"@

Created on Jan 21, 2016 1:25:12 PM by  Gerald Schoch [Paessler Support]

Last change on Jan 4, 2023 2:26:53 PM by  Brandy Greger [Paessler Support]



Votes:

0

Hello,

I am currently using the script above, but unfortunately i am getting a 0 Byte value returned for the newest file size. Hopefully you can tell me what i am missing, i do not see the error.

All other values are returned OK, number of files, total file size, ages, even for the newest file the age is returned.

Kind regards,

Kevin

Screenshot: screenshot

Parameters PRTG: -path \\dehze01-wsv622\d$\_Qlikview\Production\Data\QVD\IVY\*.QVD -include *.QVD

PS1 script:

Param(
    [string]$path="d$\_Qlikview\Production\Data\QVD\IVY\*.QVD",
    [string]$include= "*.QVD"
    )
 
$result = ""
$size = 0
# Get the list of all files
$files =  Get-ChildItem -Path $path -include $include -Recurse
$count = $files.count
if ($count -gt 0)
{
    $oldestfile = ("{0:N2}" -f (New-Timespan -end (Get-Date) -start ($files)[0].LastWriteTime).TotalDays).Replace(',','.')
    $newestfile = ("{0:N2}" -f (New-Timespan -end (Get-Date) -start ($files)[-1].LastWriteTime).TotalDays).Replace(',','.')
    foreach ($file in $files) { 
        $size += $file.length
        }
 
    $result += @" 
	<result>
		<value>$count</value>
		<unit>count</unit>
		<channel>Number of QVD Files</channel>
	</result>
	<result>
		<value>$oldestfile</value>
		<unit>custom</unit>
		<CustomUnit>Days</CustomUnit>
		<float>1</float>
		<channel>Oldest File Age</channel>
	</result>
	<result>
		<value>$newestfile</value>
		<unit>custom</unit>
		<CustomUnit>Days</CustomUnit>
		<float>1</float>
		<channel>Newest File Age</channel>
	</result>
	<result>
		<value>$newestfilesize</value>
		<unit>BytesFile</unit>
		<volumeSize>Byte</volumeSize>
		<float>0</float>
		<channel>Newest File Size</channel>
	</result>
	<result>
		<value>$size</value>
		<unit>BytesFile</unit>
		<volumeSize>Byte</volumeSize>
		<channel>Total File Size</channel>
	</result>
	<text>
	OK
	</text>
"@
} else {
    $result += @" 
    <error>1</error>
	<text>
	No file found matching the filter-parameter "$include" at path "$path" 
	</text>
"@
 
}
write-host @"
<?xml version=1.0 encoding=UTF-8 ?>
<prtg>
$result
</prtg>
"@

Created on Jul 12, 2016 10:08:29 AM

Last change on Jul 14, 2016 8:04:43 AM by  Torsten Lindner [Paessler Support]



Votes:

0

When you execute it manually, what output do you get there?

Created on Jul 13, 2016 12:38:12 PM by  Stephan Linke [Paessler Support]



Votes:

0

Hello,

I am pretty sure there's something in the script which causes this. My knowledge doesn't allow me to fix it, i just copied the above and adjusted the custom options within the script.

Hopefully the creator of the script can give some more detailed information ? perhaps this script doesn't work at all. Still hoping the solution is out there, would hate to go around PRTG making scripts that generate txt output to monitor with PRTG, i liked this script because it just runs from PRTG.

Many thanks in advanced !

Kind regards,

Kevin

Created on Aug 18, 2016 7:42:28 AM



Votes:

0

I'll check out the script and let you know what I find out...

Created on Aug 18, 2016 8:41:50 AM by  Stephan Linke [Paessler Support]



Votes:

0

Turns out that the script had a few bugs:

  • $newestfilesize was never defined
  • newest and oldest file were not correctly sorted (order was alphabetical instead of by LastWriteTime)

Updated version can be found in the original answer :)

Created on Aug 19, 2016 9:41:23 AM by  Stephan Linke [Paessler Support]

Last change on Aug 19, 2016 9:41:47 AM by  Stephan Linke [Paessler Support]



Votes:

0

Thank you very, very much ! This is exactly what we where looking for.

Thanks again !

Created on Aug 22, 2016 1:24:19 PM



Votes:

0

I have problems with the script or sensor.

I am getting this : XML: Structural error in xml file, 1 open items. -- JSON: The returned json does not match the expected structure (Invalid JSON.). (code: PE231)

I have a DFS file location, which is actually a samba share. I have tried this script first on the machine but thats a unix machine and guessing a ps1 wont work on that.

so I picked another server which has acces to that file share.

The parameters :
ourdomainname.local\dfs\TriathlonFiles\locus\prod\tohost

script

Param(
    [string]$path="\\oosterberg.local\dfs\TriathlonFiles\locus\prod\tohost",
    [string]$include= "*.dat"
    )
 
$result = ""
$size = 0
# Get the list of all files
$files =  Get-ChildItem -Path $path -include $include -Recurse | Sort-Object LastWriteTime
$count = $files.count
$newestfilesize = $files[-1].length
if ($count -gt 0)
{
    $oldestfile = ("{0:N2}" -f (New-Timespan -end (Get-Date) -start ($files)[0].LastWriteTime).TotalDays).Replace(',','.')
    $newestfile = ("{0:N2}" -f (New-Timespan -end (Get-Date) -start ($files)[-1].LastWriteTime).TotalDays).Replace(',','.')
    foreach ($file in $files) { 
        $size += $file.length
        }
	
 

    $result += @" 
	<result>
		<value>$count</value>
		<unit>count</unit>
		<channel>Number of $($include) Files</channel>
	</result>
	<result>
		<value>$oldestfile</value>
		<unit>custom</unit>
		<CustomUnit>Days</CustomUnit>
		<float>1</float>
		<channel>Oldest File Age</channel>
	</result>
	<result>
		<value>$newestfile</value>
		<unit>custom</unit>
		<CustomUnit>Days</CustomUnit>
		<float>1</float>
		<channel>Newest File Age</channel>
	</result>
	<result>
		<value>$newestfilesize</value>
		<unit>BytesFile</unit>
		<volumeSize>Byte</volumeSize>
		<float>0</float>
		<channel>Newest File Size</channel>
	</result>
	<result>
		<value>$size</value>
		<unit>BytesFile</unit>
		<volumeSize>Byte</volumeSize>
		<channel>Total File Size</channel>
	</result>
	<text>
	OK
	</text>
"@
} else {
    $result += @" 
    <error>1</error>
	<text>
	No file found matching the filter-parameter "$include" at path "$path" 
	</text>
"@
 
}
write-host @"
<?xml version=1.0 encoding=UTF-8 ?>
<prtg>
$result
</prtg>
"@

Created on Aug 26, 2016 6:18:46 AM



Votes:

0

Did you execute Set-ExecutionPolicy RemoteSigned in a administrative 32bit PowerShell already? Does the script work in a normal powershell?

Created on Aug 26, 2016 7:09:40 AM by  Stephan Linke [Paessler Support]

Last change on Aug 26, 2016 7:10:14 AM by  Stephan Linke [Paessler Support]



Votes:

0

The Get-ExecutionPolicy gives unrestricted back.

No it wont work in a normal powershell, it gives this:

PS C:\> Get-executionpolicy
Unrestricted
PS C:\> .\dat-files
Unable to index into an object of type System.IO.FileInfo.
At C:\DAT-Files.ps1:11 char:26
+ $newestfilesize = $files[ <<<< -1].length
    + CategoryInfo          : InvalidOperation: (-1:Int32) [], RuntimeException
    + FullyQualifiedErrorId : CannotIndex

<?xml version=1.0 encoding=UTF-8 ?>
<prtg>
    <error>1</error>
        <text>
        No file found matching the filter-parameter "*.dat" at path "\\oosterberg.local\dfs\TriathlonFiles\locus\prod\to
host"
        </text>
</prtg>
PS C:\>

I tried the example script with a C:\temp path and txt file in it, and then the sensor work. I think its something with the pad, though the path I am using is correct

Created on Aug 26, 2016 7:34:13 AM



Votes:

0

It's quite possible that PRTG can't access the path properly which would explain the fileinfo exception - it simply can't list any files on there from what it seems.

Created on Aug 26, 2016 7:45:04 AM by  Stephan Linke [Paessler Support]



Votes:

0

Yes, I'm trying to get a point with it. Its a share which I can acces from the probe. Its also a share on a unix machine. The root of machine has other credentials to acces but able to acces the shares with windows credentials as samba does the trick.

Powershell can user unc paths. I dont see the problem actually, I created the sensor on the probe device.

I tried a windows share (windows machine) with a doc file, locally on the probe with powershel the scripts works, when I create a sensor on the probe and it wont work.

Created on Aug 26, 2016 7:59:41 AM



Votes:

0

Can you execute

Get-ChildItem -Path "\\oosterberg.local\dfs\TriathlonFiles\locus\prod\tohost"

...in a powershell just fine? On the actual probe? Do you run the script on an actual remote probe? Did you set the executionpolicy on the remote probe itself as well?

Created on Aug 26, 2016 8:24:54 AM by  Stephan Linke [Paessler Support]



Votes:

0

Hi, after some time testing this i stumbled across the following:

  • script runs fine on prtg-server
  • script runs fine on my Window 7 desktop
  • script runs fine the the server/share to be monitored

I want to check, if filenames with text *a9r* are existent in a directory. Existence is bad, absence is good.

Sample output, five files found:

<?xml version=1.0 encoding=UTF-8 ?> <prtg> <result> <value>5</value> <unit>count</unit> <channel>Number of *a9r* Files**</channel> </result> <result> <value>7,01</value> <unit>custom</unit> <CustomUnit>Days</CustomUnit> <float>1</float> <channel>Oldest File Age</channel> </result> <result> <value>0,00</value> <unit>custom</unit> <CustomUnit>Days</CustomUnit> <float>1</float> <channel>Newest File Age</channel> </result> <result> <value>1673</value> <unit>BytesFile</unit> <volumeSize>Byte</volumeSize> <float>0</float> <channel>Newest File Size</channel> </result> <result> <value>1673</value> <unit>BytesFile</unit> <volumeSize>Byte</volumeSize> <channel>Total File Size</channel> </result> <text> OK

Putting it to work in PRTG in Custom Sensors\EXEXML results in No file found matching the filter-parameter "*a9r*" at path SERVER\C$\temp\*. But there are five files present. What else can i try?

Created on Dec 14, 2017 1:34:20 PM



Votes:

0

What path are you actually using? If you want to access the administrative C:\ share,
you'll need C$\temp\ instead of \ \<hostname>\C$\temp


Kind regards,
Stephan Linke, Tech Support Team

Created on Dec 18, 2017 8:30:42 AM by  Stephan Linke [Paessler Support]



Votes:

0

Thank you for the answer.

Update: The monitor is working now, it simply failed because of this setting:

Sicherheitskontext
wrong: Sicherheitskontext des Probe-Dienstes verwenden
right: Die Zugangsdaten für Windows des übergeordneten Geräts verwenden

Path in script (this works, C$\temp\ does not work). The script is executed on PRTG-Server so it seems logic to me to add the SERVER name.

Param( [string]$path='\ \SERVER\C$\temp\*', [string]$include= '*a9r*' )

The only thing i am not able to do is to teach him, that absence of a9r is good, presence of a9r is bad. It still needs one a9r in C:\temp file to show green sensor value. Zero a9r-file results in sensor getting grey and red. Any hint on this?

Created on Dec 18, 2017 12:47:28 PM



Votes:

0

Is the script actually returning 0 or an empty string as result when no a9r files are present?


Kind regards,
Stephan Linke, Tech Support Team

Created on Dec 18, 2017 8:08:09 PM by  Stephan Linke [Paessler Support]



Votes:

0

Zero a9r files:

Yellow (W) Sensor A9R
No file found matching the filter-parameter "*a9r*" at path "\ \SERVER\C$\temp\*" .... i guess this is the result of the else-clause in the script from Gerald Schoch

<error>1</error>
	<text>
	No file found matching the filter-parameter "$include" at path "$path" 
	</text>

"No data" in the channel fields of sensor.

After 600 seconds: Red A9R: No file found matching the filter-parameter "*a9r*" at path "
ctps01\C$\temp\*"

But running the powershell-script with zero a9r in directory results in

Cannot index into a null array. At D:\Program Files (x86)\PRTG Network Monitor\Custom Sensors\EXEXML\A9R-check.ps1:11 char:1 + $newestfilesize = $files[-1].length + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (:) [], RuntimeException + FullyQualifiedErrorId : NullArray

Created on Dec 19, 2017 12:37:13 PM



Votes:

0

Ah, well you need to capture the error correctly (i.e. output 0 files). Try/Catch is your friend here :)


Kind regards,
Stephan Linke, Tech Support Team

Created on Dec 19, 2017 1:06:08 PM by  Stephan Linke [Paessler Support]



Votes:

1

For me, there were two bugs in this script:

1: Fails, if only ONE file found

With only ONE file found, this command does not return an array but a single item!

So this IF statement will fail because single item doesn't have a count property:

$count = $files.count
if ($count -gt 0)

Therefore, this line $files = Get-ChildItem -Path $path -include $include -Recurse | Sort-Object LastWriteTime

has to be corrected with a surrounding @( ) to always return an array: $files = @(Get-ChildItem -Path $path -include $include -Recurse | Sort-Object LastWriteTime)

See Technet Forum: GetChildItem count returns null if there is one file in a folder

2: Move $newestfilesize infto IF

$count = $files.count
$newestfilesize = $files[-1].length
if ($count -gt 0)
{

should be corrected to

$count = $files.count
if ($count -gt 0)
{
   $newestfilesize = $files[-1].length

to prevent errors on an empty array

Created on Sep 18, 2018 10:25:33 AM



Votes:

0

Hi ITSE,

Thanks, I've updated the script accordingly. Much appreciated!


Kind regards,
Stephan Linke, Tech Support Team

Created on Sep 18, 2018 11:18:23 AM by  Stephan Linke [Paessler Support]



Votes:

0

Hi guys,

I got issues getting the Skript running: Access denied. Please check your Windows credentials. (code: PE095).

I use the Windows credentials of the parent device. The user has local admin rights on the system where I want to check a folder for avhdx-files. I used these parameters: -path
*Target-Hostname*\C$\ClusterStorage -include *.avhdx. The skript runs on the PRTG-host and on the target host sucessfully. The PRTG-host is a non-domain machine. The target host is a domain-member. I even tried a user with domain-admin rights, but still access denied. Other sensors, which also need credentials, work fine on the target host.

Here is the logfile I get, when I tick "Write EXE result to disk":

Data['linuxloginpassword'].asString := '';
Data['notonpod'].asString := '0';
Data['fastcount'].asString := '0';
Data['lastmsg'].asString := '#O95';
Data['resultfile'].asString := 'Result of Sensor 4200.txt';
Data['windowsloginusername'].asString := '*user defined in parent device*';
Data['hostv6'].asString := '';
Data['exefile'].asString := 'file-stats.ps1';
Data['lastuptime'].asString := '0';
Data['writeresult'].asString := '1';
Data['blockedsens'].asString := '';
Data['reqmsginterval'].asString := '60';
Data['windowslogindomain'].asString := '*mydomain*';
Data['tlsexplicit_imap'].asString := '';
Data['channelnames'].asString := '';
Data['tlsexplicit_default'].asString := '';
Data['canlinux'].asString := '0';
Data['isexesensor'].asString := '1';
Data['windowsloginpassword'].asString := '***';
Data['environment'].asString := '';
Data['mutexname'].asString := '';
Data['channelinfos'].asString := '{}';
Data['uptimecount'].asString := '0';
Data['interfacenumber'].asString := '';
Data['reboot'].asString := '43507.3921698611';
Data['usednstime'].asString := '0';
Data['linuxlogindomain'].asString := '';
Data['exeparamshash'].asString := 'da39a3ee5e6b4b0d3255bfef95601890afd80709';
Data['tlsexplicit_port'].asString := '';
Data['monitorchange'].asString := '';
Data['inerror'].asString := '1';
Data['inum'].asString := '';
Data['sensorid'].asString := '4200';
Data['ipversion'].asString := '0';
Data['tlsexplicit_smtp'].asString := '';
Data['host'].asString := '*targetip*';
Data['exeparamscache'].asString := '';
Data['usewindowsauthentication'].asString := '1';
Data['simulate'].asString := '0';
Data['tlsexplicit_ftp'].asString := '';
Data['timeout'].asString := '60';
Data['exeparams'].asString := '';
Data['momopersistent'].asString := '';
Data['tlsexplicit_pop3'].asString := '';

Any ideas, what the problem could be? I'm running PRTG 18.4.

Thanks, Phil

Created on Feb 12, 2019 11:25:25 AM

Last change on Feb 12, 2019 11:31:54 AM by  Stephan Linke [Paessler Support]



Votes:

0

Please try the following notation instead:

-path '\\%host\C$\ClusterStorage' -include '*.avhdx'

If that doesn't work, please try to execute PowerShell with -noprofile, executing the script within that session:

powershell.exe -noprofile

PRTG Scheduler | PRTGapi | Feature Requests | WMI Issues | SNMP Issues

Kind regards,
Stephan Linke, Tech Support Team

Created on Feb 12, 2019 1:12:24 PM by  Stephan Linke [Paessler Support]



Votes:

0

Hi Stephan,

thanks for your fast respond. I tried different Notations, but no effect. I also defined the two parameters directly in the script and tried to run it in PRTG - again access denied.

I run the script on the PRTG-host and on the target-host with the -noprofile parameter - worked both fine.

Created on Feb 12, 2019 3:43:01 PM



Votes:

0

Is your Probe or Core Service running as a different user by any chance?


PRTGapi | Feature Requests | WMI Issues | SNMP Issues

Kind regards,
Stephan Linke, Tech Support Team

Created on Feb 13, 2019 12:40:07 PM by  Stephan Linke [Paessler Support]



Votes:

0

Both services running as local system.

Created on Feb 15, 2019 6:27:36 AM



Votes:

0

Then I'm not really sure what the issue could be. Did you try a different folder path and file type?


PRTGapi | Feature Requests | WMI Issues | SNMP Issues

Kind regards,
Stephan Linke, Tech Support Team

Created on Feb 18, 2019 9:40:53 AM by  Stephan Linke [Paessler Support]




Disclaimer: The information in the Paessler Knowledge Base comes without warranty of any kind. Use at your own risk. Before applying any instructions please exercise proper system administrator housekeeping. You must make sure that a proper backup of all your data is available.