Metric parse error with output of a PowerShell script

I have a PowerShell script that I call from Telegraf to get who is logged into a server and only display the server, user name, connection state, & logon time. I thought I had the output formatted correctly (metric_name,tag=string,tag=string field=value,field=value), but that doesn’t appear to be true.
This is the PowerShell script I have:

$Servers = @(
  "SV-DSSAAZ-DC02"
  "SV-MSA-APP01"
  "SV-ID10T-2"
  )

#Initialize $Sessions which will contain all sessions
[System.Collections.ArrayList]$Sessions = New-Object System.Collections.ArrayList($null)

#Go through each server
Foreach ($Server in $Servers)  {
	#Get the current sessions on $Server and also format the output
	$DirtyOuput = (quser /server:$Server) -replace '\s{2,}', ',' | ConvertFrom-Csv
	
	#Go through each session in $DirtyOuput
	Foreach ($session in $DirtyOuput) {
	#Initialize a temporary hash where we will store the data
	$tmpHash = @{}
	
	#Check if SESSIONNAME isn't like "console" and isn't like "rdp-tcp*"
	If (($session.sessionname -notlike "console") -AND ($session.sessionname -notlike "rdp-tcp*")) {
		#If the script is in here, the values are shifted and we need to match them correctly
		$tmpHash = @{
		Username = $session.USERNAME
		SessionName = "" #Session name is empty in this case
		ID = $session.SESSIONNAME
		State = $session.ID
		IdleTime = $session.STATE
		LogonTime = $session."IDLE TIME"
		ServerName = $Server
		}
		}Else  {
		#If the script is in here, it means that the values are correct
		$tmpHash = @{
		Username = $session.USERNAME
		SessionName = $session.SESSIONNAME
		ID = $session.ID
		State = $session.STATE
		IdleTime = $session."IDLE TIME"
		LogonTime = $session."LOGON TIME"
		ServerName = $Server
		}
		}
		#Add the hash to $Sessions
		$Sessions.Add((New-Object PSObject -Property $tmpHash)) | Out-Null
	}
}
  
#Display the sessions, sort by name, and just show Username, State, Logon time, and Server
$sessions | Sort Username |
foreach{
"RD_Sessions,host=$($_.Servername),rd_user=user user=$($_.Username),STATE=$($_.State),LOGON_TIME=$($_.LogonTime)"
}

This is the output displayed in PowerShell if I run the query manually.
PS C:> C:\Users\a-kfreeman\Desktop\RD_Sessions.ps1
RD_Sessions,host=SV-MSA-APP01,rd_user=user user=a-bsanchez,STATE=Disc,LOGON_TIME=10/20/2021 1:22 PM
RD_Sessions,host=SV-DSSAAZ-DC02,rd_user=user user=a-kfreeman,STATE=Active,LOGON_TIME=10/26/2021 10:08 AM
RD_Sessions,host=SV-MSA-APP01,rd_user=user user=a-kfreeman,STATE=Active,LOGON_TIME=10/25/2021 2:21 PM
RD_Sessions,host=SV-ID10T-2,rd_user=user user=a-kfreeman,STATE=Active,LOGON_TIME=11/2/2021 12:09 PM
RD_Sessions,host=SV-ID10T-2,rd_user=user user=kfreeman,STATE=Active,LOGON_TIME=11/2/2021 11:39 AM

This is the error I get in the Telegraf logs.
2021-11-03T17:45:00Z E! [inputs.exec] Error in plugin: metric parse error: expected field at 1:51: “RD_Sessions,host=SV-DSSAAZ-DC02,rd_user=user user=a-kfreeman,STATE=Active,LOGON_TIME=10/26/2021 10:08 AM”

I have been banging my head attempting to get this query working and fixing the output. If anyone has another PowerShell script to pull this data I would gladly switch.

I am running Telegraf 1.20.2 and InfluxDB 2.0.8

Thank You for any help.

Hi @kfree,
So I managed to successfully write your sample with the following line protocol structure:

influx write --bucket test 'RD_Sessions,host=SV-DSSAAZ-DC02,rd_user=user STATE="Active",LOGON_TIME="10/26/2021 10:08 AM"'

A few things to note:

  1. Make sure any field value that is considered a string is encapsulated with quotes “”

  2. In your final output loop. try and change the two end quotes to single quotes ‘’

Changing the last loop to what is listed below allows it to go into the database but it only submits the variable name and not the data for the variable.

foreach{
Write-Host 'RD_Sessions,host=$($_.Servername) User="$($_.Username)",State="$($_.State)",Logon_Time="$($_.LogonTime)"'
}

RD_Sessions,host=$($.Servername) User="$($.Username)",State="$($.State)",Logon_Time="$($.LogonTime)"

I’ve got a suggestion to avoid the “manual” serialization of data. you can use a powershell library to serialize the data effortlessly:

it is an official powershell library

The relevant sample usage is this one:

#Send data from Get-Process to InfluxDB using the REST API with authentication
Get-Process -Name <__Processname__> | ConvertTo-Metric -Measure test -MetricProperty CPU,PagedmemorySize -TagProperty Handles,Id,ProcessName | Write-Influx -Database windows_system_monitor -Server http://<__InfluxEndpoint__>:8086 -Credential (Get-Credential) -Verbose

In your case, you just need the ConvertTo-Metric command, it will manage the whole serialization process, managing difference between tags, fields and their relative special char escaping

Unfortunately, I need a standalone script that I can call from Telegraf that will work on Windows server 2008 and newer. I have servers running production lines that don’t have PowerShell 5 on them, and they can’t be updated without causing problems.

Then just “steal” the code from the library (or at least that single function ConvertTo-Metric), it’s public GitHub repo.
Otherwise, you will have to study some Line Protocol and manage the serialization

Could you try:

  1. replace the single quotes with double quotes around the data you’re inserting
  2. on each field string, add a backtick before the opening and closing quotes
User=`"$($_.Username)`"