{"id":1572,"date":"2016-08-23T21:18:08","date_gmt":"2016-08-23T21:18:08","guid":{"rendered":"http:\/\/wp.andreas.bieri.name\/myblog\/?p=1572"},"modified":"2016-08-23T21:18:08","modified_gmt":"2016-08-23T21:18:08","slug":"skype-cdr-daten-mit-splunk-auswerten","status":"publish","type":"post","link":"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/2016\/08\/23\/skype-cdr-daten-mit-splunk-auswerten\/","title":{"rendered":"Skype CDR Daten mit Splunk auswerten (Teil 1)"},"content":{"rendered":"<p>Siehe auch\u00a0<a href=\"http:\/\/wp.andreas.bieri.name\/myblog\/index.php\/2016\/08\/22\/skype-lcsdr-in-splunk-teil-2\/\" target=\"_blank\" rel=\"noopener noreferrer\">Teil 2<\/a>\u00a0und <a href=\"http:\/\/wp.andreas.bieri.name\/myblog\/index.php\/2016\/10\/20\/skype-cdr-daten-mit-splunk-auswerten-teil-3\/\" target=\"_blank\" rel=\"noopener noreferrer\">Teil 3<\/a>.<\/p>\n<h3><\/h3>\n<h3>Der Bedarf<\/h3>\n<p>Dieser Artikel entstand aus den W\u00fcnschen vieler Lync\/Skype for Business Kunden nach Reports und Statistiken. \u00a0Es scheint anscheinend nicht ein sehr verbreitetes Wissen zu sein, wie aus den Daten in der lcscdr und qoemetric Datenbanken sinnvolle Reports gebaut werden k\u00f6nnen. Ich habe mir deshalb selber einige M\u00f6glichkeiten \u00fcberlegt:<\/p>\n<ol>\n<li>Monitoring Server Reports (eig. SQL Server Reporting Sevices Reports): ein n\u00fctzliches Grundset kommt ja mit. Wie man die anpasst, ist eher wenig unbekannt, geht aber soweit ganz gut. Reports k\u00f6nnen auch verschickt (per Mail abonniert) werden. Nachteil: ein Lync Monitoring Server muss vorhanden sein; manchmal streiken die Reports hartn\u00e4ckig und der grafische Overhead ist nicht immer angebracht (bei der Weiterverarbeitung).<br \/>\nIch schreibe noch einen Blog dazu. Hier ein Beispiel: <a href=\"http:\/\/guybachar.net\/2015\/08\/10\/how-to-build-a-custom-report-for-lyncskype-for-business\/\" target=\"_blank\" rel=\"noopener noreferrer\">How to build a custom report for Lync\/Skype for Business<\/a><\/li>\n<li>Erweiterung mit Datenfeeds und Power Pivot Techniken, siehe den Blog von Ilse van Criekinge:\u00a0<a href=\"https:\/\/blogs.technet.microsoft.com\/ilvancri\/2012\/03\/09\/extending-your-lync-monitoring-data-using-powerpivot-and-power-view\/\" target=\"_blank\" rel=\"noopener noreferrer\">Extending your Lync monitoring data using PowerPivot and Power View<\/a>. Dies er\u00f6ffnet ganz coole M\u00f6glichkeiten, sofern man sich gut damit auskennt. F\u00fcr mich das zu sehr Neuland. Einige Versuche scheiterten an irgendwelchen Berechtigungen und ich habe es nicht mehr verfolgt.<\/li>\n<li>Eigene Auswertungen mit gescripteten Exports aus der DB. Naheliegenderweise schlage ich dazu Powershell vor. Hier stellt sich die Frage, wie man die Resultate auswertet und pr\u00e4sentiert.<\/li>\n<li>Wie 3., aber mit Einlieferung der Daten in Splunk.<\/li>\n<\/ol>\n<p>Aufgrund meiner Kriterien:<\/p>\n<ul>\n<li>Reporting ohne Monitoring Server (Monitoring muss in der Topologie definiert sein, aber kein Monitoring Server ist notwendig)<\/li>\n<li>maschinenauswertbare Reports ohne grafischen Ballast (low footprint)<\/li>\n<li>Langzeit-Archivierung<\/li>\n<li>flexible Visualisierungsm\u00f6glicheiten<\/li>\n<\/ul>\n<p>habe ich mich entschieden, den Weg 4) mit dem eigenen Export und Splunk weiter zu verfolgen. Als Einf\u00fchrung lese und h\u00f6re man die Pr\u00e4sentation\u00a0<a href=\"http:\/\/video.ch9.ms\/sessions\/lync\/2014\/SERV303_Hoey.pptx\" target=\"_blank\" rel=\"noopener noreferrer\">Hardcore Lync Analytics (Lync Conference 2014)<\/a>\u00a0auf Channel9.<\/p>\n<p><img loading=\"lazy\" class=\"wp-image-1594 aligncenter\" src=\"http:\/\/wp.andreas.bieri.name\/wp-content\/uploads\/2016\/08\/lcscdr1.jpg\" alt=\"lcscdr1\" width=\"608\" height=\"342\" srcset=\"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/wp-content\/uploads\/2016\/08\/lcscdr1.jpg 1408w, http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/wp-content\/uploads\/2016\/08\/lcscdr1-300x169.jpg 300w, http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/wp-content\/uploads\/2016\/08\/lcscdr1-768x433.jpg 768w, http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/wp-content\/uploads\/2016\/08\/lcscdr1-1024x577.jpg 1024w\" sizes=\"(max-width: 608px) 100vw, 608px\" \/><\/p>\n<h3>Datenquelle lcscdr DB<\/h3>\n<p>Die Schema der lcscdr Datenbank ist prinzipiell <a href=\"https:\/\/technet.microsoft.com\/en-us\/library\/gg398570.aspx\" target=\"_blank\" rel=\"noopener noreferrer\">bei Microsoft dokumentiert,<\/a> diese ist aber l\u00fcckenhaft und es gibt\u00a0keine Erkl\u00e4rungen zu den Zusammenh\u00e4ngen dazwischen. Weitere Erkl\u00e4rungen zu den Stored Procedures sind \u00fcberhaupt nicht zu finden (nur tables und views).<\/p>\n<p>dbo.Users: alle Users mit der Zuordnung UserId zu UserUri (=SIP oder Telefonnummer)<\/p>\n<p><img loading=\"lazy\" class=\"wp-image-1591 aligncenter\" src=\"http:\/\/wp.andreas.bieri.name\/wp-content\/uploads\/2016\/08\/dbousers.png\" alt=\"dbousers\" width=\"836\" height=\"311\" srcset=\"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/wp-content\/uploads\/2016\/08\/dbousers.png 984w, http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/wp-content\/uploads\/2016\/08\/dbousers-300x112.png 300w, http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/wp-content\/uploads\/2016\/08\/dbousers-768x286.png 768w\" sizes=\"(max-width: 836px) 100vw, 836px\" \/><\/p>\n<p>dbo.SessionDetails: aller Verbindungen aller Typen mit vollen Details<\/p>\n<p><img loading=\"lazy\" class=\"wp-image-1592 aligncenter\" src=\"http:\/\/wp.andreas.bieri.name\/wp-content\/uploads\/2016\/08\/dbosessions.png\" alt=\"dbosessions\" width=\"821\" height=\"341\" srcset=\"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/wp-content\/uploads\/2016\/08\/dbosessions.png 937w, http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/wp-content\/uploads\/2016\/08\/dbosessions-300x125.png 300w, http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/wp-content\/uploads\/2016\/08\/dbosessions-768x319.png 768w\" sizes=\"(max-width: 821px) 100vw, 821px\" \/><\/p>\n<p>dbo.VoipDetails: Verbindungen mit mindestens einem PSTN Teilnehmer, der Anrufer ist <em>FromNumberId<\/em>, der Angerufene <em>ConnectedNumberId<\/em>.<\/p>\n<p><img loading=\"lazy\" class=\"wp-image-1586 aligncenter\" src=\"http:\/\/wp.andreas.bieri.name\/wp-content\/uploads\/2016\/08\/splunk2-1.png\" alt=\"splunk2\" width=\"796\" height=\"480\" srcset=\"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/wp-content\/uploads\/2016\/08\/splunk2-1.png 934w, http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/wp-content\/uploads\/2016\/08\/splunk2-1-300x181.png 300w, http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/wp-content\/uploads\/2016\/08\/splunk2-1-768x463.png 768w\" sizes=\"(max-width: 796px) 100vw, 796px\" \/><\/p>\n<p>dbo.Phones: Zuordnung von\u00a0FromNumberId und\u00a0ConnectedNumberId zu einer Telefonnummer. Beachte, dass beide Teilnehmer f\u00fcr\u00a0Enterprise Voice enabled sein m\u00fcssen und deshalb beide eine Telefonnummer besitzen.<\/p>\n<h3><img loading=\"lazy\" class=\"wp-image-1587 aligncenter\" src=\"http:\/\/wp.andreas.bieri.name\/wp-content\/uploads\/2016\/08\/splunk1.png\" alt=\"splunk1\" width=\"609\" height=\"491\" srcset=\"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/wp-content\/uploads\/2016\/08\/splunk1.png 676w, http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/wp-content\/uploads\/2016\/08\/splunk1-300x242.png 300w\" sizes=\"(max-width: 609px) 100vw, 609px\" \/><\/h3>\n<h3>Stored Procedures<\/h3>\n<p>Die Reports des Monitoring Servers sind unterschiedlich komplex. Einige bestehen aus umfangreichen Queries, die auf dem Reporting Services Server direkt ausgef\u00fchrt werden. Andere bestehen nur aus einem einzigen Aufruf einer Stored Procedure\u00a0plus grafischem Beigem\u00fcse. F\u00fcr die P2P\u00a0und Conferencing Summary Reports werden nur Stored Procedures aufgerufen. Sowas l\u00e4sst sich nat\u00fcrlich einfach mit einem Script bewerkstelligen. Der Monitoring Server ist dabei gar nicht mehr involviert.<\/p>\n<p><img loading=\"lazy\" class=\"wp-image-1588 aligncenter\" src=\"http:\/\/wp.andreas.bieri.name\/wp-content\/uploads\/2016\/08\/p2p-sql1.png\" alt=\"p2p-sql1\" width=\"863\" height=\"403\" srcset=\"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/wp-content\/uploads\/2016\/08\/p2p-sql1.png 1015w, http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/wp-content\/uploads\/2016\/08\/p2p-sql1-300x140.png 300w, http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/wp-content\/uploads\/2016\/08\/p2p-sql1-768x359.png 768w\" sizes=\"(max-width: 863px) 100vw, 863px\" \/><\/p>\n<p><img loading=\"lazy\" class=\"wp-image-1589 aligncenter\" src=\"http:\/\/wp.andreas.bieri.name\/wp-content\/uploads\/2016\/08\/p2p-sql2.png\" alt=\"p2p-sql2\" width=\"872\" height=\"285\" srcset=\"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/wp-content\/uploads\/2016\/08\/p2p-sql2.png 1059w, http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/wp-content\/uploads\/2016\/08\/p2p-sql2-300x98.png 300w, http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/wp-content\/uploads\/2016\/08\/p2p-sql2-768x251.png 768w, http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/wp-content\/uploads\/2016\/08\/p2p-sql2-1024x335.png 1024w\" sizes=\"(max-width: 872px) 100vw, 872px\" \/><\/p>\n<p>&nbsp;<\/p>\n<h3>Zeit- und Datumsberechnungen<\/h3>\n<p>Die Zeit- und Datumsberechnungen sind sehr m\u00fchsam, da verschiedene Zeitzonen und\u00a0Zeitformate ber\u00fccksichtigt werden m\u00fcssen. Die Reports sind z.T. mit UTC hardcoded programmiert &#8211; sie erwarten die Zeitparameter mit einer Angabe der Zeitzone (culture), liefern die Resultate aber immer in UTC zur\u00fcck. F\u00fcr Tagesstatistiken sind Fehler aber nicht sehr st\u00f6rend. Eine falsch berechnete Stunde wird noch zum Vortag gerechnet (oder zum n\u00e4chsten Tag geschlagen).<\/p>\n<pre>$currentDate =\u00a0 ( [datetime](get-date -format \"yyyy-MM-dd\" )).AddMonths(-1)\n$firstDayMonth = get-date $currentDate -Day 1 -format \"yyyy-MM-dd\" \n$lastDayMonth = get-date ((get-date $currentDate -Day 1).AddMonths(1).AddSeconds(-1)) -format \"yyyy-MM-dd\" \n# $lastDayMonth = [datetime]$lastDayMonth -format \"yyyy-MM-dd hh:mm:ss\" \n$global:startTime = ([string]$firstDayMonth) + \" 00:00:00\"\n$global:endTime = ([string]$lastDayMonth) + \" 23:59:59\"<\/pre>\n<pre>function getFirstDayLastMonth {\n# determine first and last day of last month or current month\n# $useLastMonth = 0: use current month\n# returns datetime in form \"2016-02-26 00:00:00\". Reformatting applied later\n#\nparam ( )\n$currentDate =\u00a0 ( [datetime](get-date -format \"yyyy-MM-dd\" )).AddMonths(-1)\n$firstDayMonth = get-date $currentDate -Day 1 -format \"yyyy-MM-dd\"\n$lastDayMonth = get-date ((get-date $currentDate -Day 1).AddMonths(1).AddSeconds(-1)) -format \"yyyy-MM-dd\"\n# $lastDayMonth = [datetime]$lastDayMonth -format \"yyyy-MM-dd hh:mm:ss\"\n$global:startTime = ([string]$firstDayMonth) + \" 00:00:00\"\n$global:endTime = ([string]$lastDayMonth) + \" 23:59:59\"\n}<\/pre>\n<pre>function getFirstHourLastDay {\n# determine first and last hour of the previous day\n# returns datetime in form \"2016-04-07 00:00:00\"\nparam (\u00a0 )\n$previousDay = get-date ([DateTime]::Today.AddDays(-1) ) -format \"yyyy-MM-dd\"\n$global:startTime = ([string]$previousDay) + \" 00:00:00\"\n$global:endTime = ([string]$previousDay) + \" 23:59:59\"\n}<\/pre>\n<p>Ben\u00f6tigt man h\u00e4ufiger Umrechnungen in verschiedene Zeitzinen, kann das Script <a href=\"https:\/\/blogs.msdn.microsoft.com\/rslaten\/2014\/08\/04\/converting-times-from-one-time-zone-to-another-time-zone-in-powershell\/\" target=\"_blank\" rel=\"noopener noreferrer\">ConvertTimeZones.ps1 <\/a>n\u00fctzlich sein.<\/p>\n<p><img loading=\"lazy\" class=\"alignleft size-full wp-image-1674\" src=\"http:\/\/wp.andreas.bieri.name\/wp-content\/uploads\/2016\/08\/timezones1-1.png\" alt=\"timezones1\" width=\"1438\" height=\"88\" srcset=\"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/wp-content\/uploads\/2016\/08\/timezones1-1.png 1438w, http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/wp-content\/uploads\/2016\/08\/timezones1-1-300x18.png 300w, http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/wp-content\/uploads\/2016\/08\/timezones1-1-768x47.png 768w, http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/wp-content\/uploads\/2016\/08\/timezones1-1-1024x63.png 1024w\" sizes=\"(max-width: 1438px) 100vw, 1438px\" \/><\/p>\n<p>Wer es noch genauer haben will, liest diesen Artikel: <a href=\"https:\/\/blogs.msdn.microsoft.com\/sergey_babkins_blog\/2015\/02\/20\/time-conversions-in-powershell-and-net-in-general\/\" target=\"_blank\" rel=\"noopener noreferrer\">Time conversions in PowerShell (and .NET in general)<\/a>.<\/p>\n<p>&nbsp;<\/p>\n<h3>Parameter\u00fcbergabe vorbereiten<\/h3>\n<p>Mein Script kann mehrere Statistiken ausgeben. Dazu wird in einer CSV Datei pro Zeile ein sog. Workorder definiert:<\/p>\n<pre><strong>sip,monthy,daily,storedprocname,reportfilename,reportsubject,mailrecipient<\/strong>\ndummy,no,yes,CdrP2PActSumReport,P2P-ActivitySummaryReport,\"P2P Anrufe\",andreas.bieri1@domain.com\ndummy,no,yes,CdrConfActSumReport,CdrConfActSumReport,\"Konferenzstatistik\",andreas.bieri1@domain.com\nrgs.058xxxxxxx@domain.com,true,false,CdrRGSUsageTrend,RGS-Report-058xxxxxxx,\"RGS 058xxxxxxx\",andreas.bieri1@domain.com<\/pre>\n<p>Das Script liest die Workorders aus der CSV aus und bereite die Parameter entsprechend vor. Jede Stored Procedure hat ihre eigenen obligatorischen oder optionalen Parameter.<\/p>\n<pre>import-csv -path $inputFile -delimiter ',' |\u00a0 % {\ntry {\n # read CSV with word orders\n $rgsSIP = [string]$_.sip<\/pre>\n<pre> # switch: daily report with hourly granularity or monthly with daily granularity\n # in CSV two columns daily, monthly; fill exactly one with yes\n $rgsMonthly = $false\n $rgsDaily = $false<\/pre>\n<pre> # read name of stored procedure\n $storedprocCSV = [string]$_.storedprocname\n # prepare output\n $rgsReportfilename = [string]$_.reportfilename\n $rgsReportSubject = [string]$_.reportsubject\n $rgsMailTo = [string]$_.mailrecipient<\/pre>\n<pre> #check we have a valid input line\n if ( $rgsSIP -eq $null -or $rgsMonthly -eq $null -or $rgsDaily -eq $null -or $rgsReportfilename -eq $null) {\n throw ('Invalid input line - missing value')\n }<\/pre>\n<pre> # define monthly\/daily reporting\n # set to true (default false)\n if ( ($_.monthly -eq \"true\") -or ($_.monthly -eq \"True\") ) {\n $rgsMonthly = $true\n }\n if ( ($_.daily -eq \"true\") -or ($_.daily -eq \"True\") ) {\n $rgsDaily = $true\n }\nif ( ($rgsMonthly -eq $false -and $rgsDaily -eq $false) -or ($rgsMonthly -eq $true -and $rgsDaily -eq $true)) {\n throw ('Invalid input line - exactly one of monthly\/daily option must be set')\n }\n # define time span $startTime and $endTime\n # SQL format does not work: \"N'26-02-2016T00:00:00'\" use format 2016-03-01 00:00:00 and 2016-03-31 23:59:59\n if ( $rgsMonthly -eq \"true\" ) {\n getFirstDayLastMonth\n }\n if ( $rgsDaily -eq \"true\" ) {\n getFirstHourLastDay\n }<\/pre>\n<pre> # Testing only: specify date directly\n #$global:startTime = \"2016-02-29 22:00:00\"\n #$global:endTime = \"2016-03-30 22:00:00\"<\/pre>\n<pre>catch {\n $msg = \"*** Script catch error: $error[0]\"\n $msg\n $msg &gt;&gt; $logFile\n }<\/pre>\n<p>&nbsp;<\/p>\n<h3>SQL Query<\/h3>\n<p>Das Kernst\u00fcck des Scripts f\u00fchrt die Stored Procedures mit den passenden Parameter aus und holt die Resultate in ein Array.<\/p>\n<p>Es wird ein SqlDataAdapter Objekt erzeugt<\/p>\n<pre># create report: prepare SQL query, execute and store result\n$DataSet = New-Object System.Data.DataSet\n$SqlConnection = New-Object System.Data.SqlClient.SqlConnection\n$SqlCmd = New-Object System.Data.SqlClient.SqlCommand\n$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter<\/pre>\n<p>die Verbindung zur DB wird gebildet<\/p>\n<pre># connect string to db\n $SqlConnection.ConnectionString = \"Server = $SqlServer; Database = $SqlCatalog; Integrated Security = True\"<\/pre>\n<p>Powershell wartet nur 30 Sekunden auf den Query, das reicht in der Regel nicht bei grossen Datenmengen.<\/p>\n<pre># define timeout value: default it will wait only 30s\n $SqlCmd.CommandTimeout = 300<\/pre>\n<p>wir wollen eine stored procedure starten und teilen das auch so mit<\/p>\n<pre># indicate that we are working with stored procedure\n $SqlCmd.CommandType=[System.Data.CommandType]\u2019StoredProcedure\u2019\n# supply the name of the stored procedure\n #$SqlStoredProcName = \"CdrP2PActSumReport\"\n #$SqlStoredProcName = \"DiagShowEndpointsByClientApp\"\n #$SqlStoredProcName = \"CdrRGSUsageTrend\"\n $SqlStoredProcName = $storedprocCSV\n $SqlCmd.CommandText = $SqlStoredProcName<\/pre>\n<p>jede SP verlangt ihre Parameter; hier ist eine Fallunterscheidung zu machen<\/p>\n<pre># supply standard parameters for SP\n $SqlCmd.Parameters.AddWithValue(\"@_StartTime\",[datetime]$global:startTime) | Out-Null\n $SqlCmd.Parameters.AddWithValue(\"@_EndTime\",[datetime]$global:endTime) | Out-Null\n $SqlCmd.Parameters.AddWithValue(\"@_Interval\",[int]1440) | Out-Null\n $SqlCmd.Parameters.AddWithValue(\"@_WindowSize\",[int]1440) | Out-Null<\/pre>\n<pre># supply non-standard parameters for SP\n if ($SqlStoredProcName -eq \"CdrRGSUsageTrend\") {\n # special treatment\n  $SqlCmd.Parameters.AddWithValue(\"@_WorkflowUri\", $rgsSIP) | Out-Null\n }<\/pre>\n<p>Schliesslich wird die Query geschickt:<\/p>\n<pre> #\u2014\u2014\u2014\u2014- execute command and close connection\n $SqlCmd.Connection = $SqlConnection\n $SqlAdapter.SelectCommand = $SqlCmd\n $SqlAdapter.Fill($DataSet) | Out-Null\n $SqlConnection.Close()<\/pre>\n<p>Das Resultat wird im Objekt $Dataset gespeichert.<\/p>\n<h3>Postprocessing<\/h3>\n<p>F\u00fcr den RGS Report ist es n\u00f6tig, die Rohdaten noch geeignet zusammenzurechnen. Hier zeigt sich wieder die St\u00e4rke der kraftstrotzenden Muschel: ich erweitere das $Dataset mit neuen Spalten, iteriere durch alle Zeilen und berechne die Inhalte. Der Zeitstempel wird noch etwas vereinfacht.<\/p>\n<pre># switch for special parameters, post treatment of results\n #\n if ($SqlStoredProcName -eq \"CdrRGSUsageTrend\") {\n # add calculated columns\n $DataSet.Tables[0].Columns.Add(\"Day\") | Out-Null\n $DataSet.Tables[0].Columns.Add(\"ReceivedCalls\") | Out-Null\n $DataSet.Tables[0].Columns.Add(\"SuccessfulCalls\") | Out-Null\n $DataSet.Tables[0].Columns.Add(\"OfferedCalls\") | Out-Null\n $DataSet.Tables[0].Columns.Add(\"AnsweredCalls\") | Out-Null\n $DataSet.Tables[0].Columns.Add(\"TransferredCalls\") | Out-Null\n ($DataSet.Tables[0]) | foreach {\n $_.ReceivedCalls\u00a0\u00a0\u00a0 = $_.SOCCnt + $_.FOCCnt\n $_.SuccessfulCalls\u00a0 = $_.SOCCnt + 0\n $_.OfferedCalls\u00a0\u00a0\u00a0\u00a0 = $_.SACCnt + $_.FACCnt\n $_.AnsweredCalls\u00a0\u00a0\u00a0 = $_.SLCnt + 0\n if (-not $_.AnsweredCalls ) {\u00a0 $_.AnsweredCalls = \"9999\"}\n $_.TransferredCalls = $_.STCCnt + $_.FTCCnt\n # shorten date (samples column)\n $nextDay = [datetime]( ([datetime]$_.Sample).tostring('yyy\/MM\/dd') )\n $_.Day = ( $nextDay.AddDays(1) ).tostring('yyy\/MM\/dd')\n # debug\n #Write-Host $_.Day\n }\n }<\/pre>\n<p>F\u00fcr die Ausgabe werden nur die neuen Spalten ausgew\u00e4hlt.<\/p>\n<pre># special treatments for output formatting\n if ($SqlStoredProcName -eq \"CdrRGSUsageTrend\") {\n $DataSet.Tables[0]\u00a0 | select-object -Property\u00a0 Day,ReceivedCalls,SuccessfulCalls,OfferedCalls,AnsweredCalls,TransferredCalls | Export-CSV $datafilename -Delimiter \" \" -encoding UTF8 -NoTypeInformation\n }<\/pre>\n<p>F\u00fcr die anderen Reports ist keine solche Nachbearbeitung n\u00f6tig.<\/p>\n<pre>if ($SqlStoredProcName -eq \"CdrP2PActSumReport\") {\n $DataSet.Tables[0]\u00a0 | Export-CSV -Delimiter \";\" $datafilename -encoding UTF8 -NoTypeInformation\n }<\/pre>\n<p>&nbsp;<\/p>\n<h3>Report per Mail<\/h3>\n<p>Selbstverst\u00e4ndlich k\u00f6nnen die Resultate mit Powershell ganz einfach per Mail verschickt werden. Das brauchen wir aber nicht, da Splunk direkt die geschriebene Datei liest.<\/p>\n<pre># send report\n $MailMessage = New-Object system.net.mail.mailmessage\n $MailMessage.from = \"xxxxx@domain.com\"\n $MailMessage.To.add($rgsMailTo)\n $MailMessage.bcc.add(\"yyyyy@domain.com\")\n $MailMessage.Subject = \"Test Reporting $rgsReportSubject\"\n $MailMessage.IsBodyHtml = $false\n $MailMessage.Body = \"Guten Tag `n `n Angeh\u00e4ngt ist die Statistik f\u00fcr die $rgsReportSubject f\u00fcr den vergangenen Monat.\u00a0 `n `n Freundliche Gr\u00fcsse `n Ihr Admin\"\n #$MailMessage.Attachments.add($datafilename)\n #$SmtpServer.Send($MailMessage)\n $MailMessage.Dispose()<\/pre>\n<p>&nbsp;<\/p>\n<h3>Indizierung in Splunk<\/h3>\n<p>Die Daten werden von Splunk eingelesen und m\u00fcssen interpretiert werden. Dazu wurde eine Lync Splunk App entwickelt, die den Speicherordner \u00fcberwacht und jede \u00c4nderung an der Ausgabedatei bemerkt. Die Reportdaten k\u00f6nnen somit t\u00e4glich in die gleiche Datei geschrieben werden und ein Cleanup von alten Dateien er\u00fcbrigt sich. Splunk versteht das CSV Datenformat, sodass die Felder problemlos geparst werden k\u00f6nnen. F\u00fcr Berechnungen kann man dann mit sch\u00f6nen und sprechenden Variablennamen auf die Felder zugreifen..<\/p>\n<p>(<a href=\"http:\/\/wp.andreas.bieri.name\/myblog\/index.php\/2016\/08\/22\/skype-lcsdr-in-splunk-teil-2\/\">Fortsetzung: Teil II<\/a>)<\/p>\n<h4><\/h4>\n","protected":false},"excerpt":{"rendered":"<p>Siehe auch\u00a0Teil 2\u00a0und Teil 3. Der Bedarf Dieser Artikel entstand aus den W\u00fcnschen vieler Lync\/Skype for Business Kunden nach Reports und Statistiken. \u00a0Es scheint anscheinend nicht ein sehr verbreitetes Wissen zu sein, wie aus den Daten in der lcscdr und qoemetric Datenbanken sinnvolle Reports gebaut werden k\u00f6nnen. Ich habe mir deshalb selber einige M\u00f6glichkeiten \u00fcberlegt: [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[10,6],"tags":[77,100,122,128,130],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v18.3 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Skype CDR Daten mit Splunk auswerten (Teil 1) - Merkbar.<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/2016\/08\/23\/skype-cdr-daten-mit-splunk-auswerten\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Skype CDR Daten mit Splunk auswerten (Teil 1) - Merkbar.\" \/>\n<meta property=\"og:description\" content=\"Siehe auch\u00a0Teil 2\u00a0und Teil 3. Der Bedarf Dieser Artikel entstand aus den W\u00fcnschen vieler Lync\/Skype for Business Kunden nach Reports und Statistiken. \u00a0Es scheint anscheinend nicht ein sehr verbreitetes Wissen zu sein, wie aus den Daten in der lcscdr und qoemetric Datenbanken sinnvolle Reports gebaut werden k\u00f6nnen. Ich habe mir deshalb selber einige M\u00f6glichkeiten \u00fcberlegt: [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/2016\/08\/23\/skype-cdr-daten-mit-splunk-auswerten\/\" \/>\n<meta property=\"og:site_name\" content=\"Merkbar.\" \/>\n<meta property=\"article:published_time\" content=\"2016-08-23T21:18:08+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/wp.andreas.bieri.name\/wp-content\/uploads\/2016\/08\/lcscdr1.jpg\" \/>\n<meta name=\"twitter:card\" content=\"summary\" \/>\n<meta name=\"twitter:label1\" content=\"Verfasst von\" \/>\n\t<meta name=\"twitter:data1\" content=\"wp_blogadmin\" \/>\n\t<meta name=\"twitter:label2\" content=\"Gesch\u00e4tzte Lesezeit\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebSite\",\"@id\":\"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/#website\",\"url\":\"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/\",\"name\":\"Merkbar.\",\"description\":\"IT, Elektronik und Mathematik\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"de\"},{\"@type\":\"ImageObject\",\"@id\":\"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/2016\/08\/23\/skype-cdr-daten-mit-splunk-auswerten\/#primaryimage\",\"inLanguage\":\"de\",\"url\":\"http:\/\/wp.andreas.bieri.name\/wp-content\/uploads\/2016\/08\/lcscdr1.jpg\",\"contentUrl\":\"http:\/\/wp.andreas.bieri.name\/wp-content\/uploads\/2016\/08\/lcscdr1.jpg\"},{\"@type\":\"WebPage\",\"@id\":\"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/2016\/08\/23\/skype-cdr-daten-mit-splunk-auswerten\/#webpage\",\"url\":\"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/2016\/08\/23\/skype-cdr-daten-mit-splunk-auswerten\/\",\"name\":\"Skype CDR Daten mit Splunk auswerten (Teil 1) - Merkbar.\",\"isPartOf\":{\"@id\":\"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/2016\/08\/23\/skype-cdr-daten-mit-splunk-auswerten\/#primaryimage\"},\"datePublished\":\"2016-08-23T21:18:08+00:00\",\"dateModified\":\"2016-08-23T21:18:08+00:00\",\"author\":{\"@id\":\"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/#\/schema\/person\/47691942dec3f2eb9d34bb8b5507870d\"},\"breadcrumb\":{\"@id\":\"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/2016\/08\/23\/skype-cdr-daten-mit-splunk-auswerten\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/2016\/08\/23\/skype-cdr-daten-mit-splunk-auswerten\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/2016\/08\/23\/skype-cdr-daten-mit-splunk-auswerten\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Startseite\",\"item\":\"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Skype CDR Daten mit Splunk auswerten (Teil 1)\"}]},{\"@type\":\"Person\",\"@id\":\"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/#\/schema\/person\/47691942dec3f2eb9d34bb8b5507870d\",\"name\":\"wp_blogadmin\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/#personlogo\",\"inLanguage\":\"de\",\"url\":\"http:\/\/1.gravatar.com\/avatar\/d0dc804558b03f640b22e497ec010c9a?s=96&d=mm&r=g\",\"contentUrl\":\"http:\/\/1.gravatar.com\/avatar\/d0dc804558b03f640b22e497ec010c9a?s=96&d=mm&r=g\",\"caption\":\"wp_blogadmin\"},\"url\":\"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/author\/wp_blogadmin\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Skype CDR Daten mit Splunk auswerten (Teil 1) - Merkbar.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/2016\/08\/23\/skype-cdr-daten-mit-splunk-auswerten\/","og_locale":"de_DE","og_type":"article","og_title":"Skype CDR Daten mit Splunk auswerten (Teil 1) - Merkbar.","og_description":"Siehe auch\u00a0Teil 2\u00a0und Teil 3. Der Bedarf Dieser Artikel entstand aus den W\u00fcnschen vieler Lync\/Skype for Business Kunden nach Reports und Statistiken. \u00a0Es scheint anscheinend nicht ein sehr verbreitetes Wissen zu sein, wie aus den Daten in der lcscdr und qoemetric Datenbanken sinnvolle Reports gebaut werden k\u00f6nnen. Ich habe mir deshalb selber einige M\u00f6glichkeiten \u00fcberlegt: [&hellip;]","og_url":"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/2016\/08\/23\/skype-cdr-daten-mit-splunk-auswerten\/","og_site_name":"Merkbar.","article_published_time":"2016-08-23T21:18:08+00:00","og_image":[{"url":"http:\/\/wp.andreas.bieri.name\/wp-content\/uploads\/2016\/08\/lcscdr1.jpg"}],"twitter_card":"summary","twitter_misc":{"Verfasst von":"wp_blogadmin","Gesch\u00e4tzte Lesezeit":"8 Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebSite","@id":"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/#website","url":"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/","name":"Merkbar.","description":"IT, Elektronik und Mathematik","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"de"},{"@type":"ImageObject","@id":"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/2016\/08\/23\/skype-cdr-daten-mit-splunk-auswerten\/#primaryimage","inLanguage":"de","url":"http:\/\/wp.andreas.bieri.name\/wp-content\/uploads\/2016\/08\/lcscdr1.jpg","contentUrl":"http:\/\/wp.andreas.bieri.name\/wp-content\/uploads\/2016\/08\/lcscdr1.jpg"},{"@type":"WebPage","@id":"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/2016\/08\/23\/skype-cdr-daten-mit-splunk-auswerten\/#webpage","url":"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/2016\/08\/23\/skype-cdr-daten-mit-splunk-auswerten\/","name":"Skype CDR Daten mit Splunk auswerten (Teil 1) - Merkbar.","isPartOf":{"@id":"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/#website"},"primaryImageOfPage":{"@id":"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/2016\/08\/23\/skype-cdr-daten-mit-splunk-auswerten\/#primaryimage"},"datePublished":"2016-08-23T21:18:08+00:00","dateModified":"2016-08-23T21:18:08+00:00","author":{"@id":"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/#\/schema\/person\/47691942dec3f2eb9d34bb8b5507870d"},"breadcrumb":{"@id":"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/2016\/08\/23\/skype-cdr-daten-mit-splunk-auswerten\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/2016\/08\/23\/skype-cdr-daten-mit-splunk-auswerten\/"]}]},{"@type":"BreadcrumbList","@id":"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/2016\/08\/23\/skype-cdr-daten-mit-splunk-auswerten\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Startseite","item":"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/"},{"@type":"ListItem","position":2,"name":"Skype CDR Daten mit Splunk auswerten (Teil 1)"}]},{"@type":"Person","@id":"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/#\/schema\/person\/47691942dec3f2eb9d34bb8b5507870d","name":"wp_blogadmin","image":{"@type":"ImageObject","@id":"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/#personlogo","inLanguage":"de","url":"http:\/\/1.gravatar.com\/avatar\/d0dc804558b03f640b22e497ec010c9a?s=96&d=mm&r=g","contentUrl":"http:\/\/1.gravatar.com\/avatar\/d0dc804558b03f640b22e497ec010c9a?s=96&d=mm&r=g","caption":"wp_blogadmin"},"url":"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/author\/wp_blogadmin\/"}]}},"_links":{"self":[{"href":"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/wp-json\/wp\/v2\/posts\/1572"}],"collection":[{"href":"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/wp-json\/wp\/v2\/comments?post=1572"}],"version-history":[{"count":0,"href":"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/wp-json\/wp\/v2\/posts\/1572\/revisions"}],"wp:attachment":[{"href":"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/wp-json\/wp\/v2\/media?parent=1572"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/wp-json\/wp\/v2\/categories?post=1572"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/ec2-52-29-166-97.eu-central-1.compute.amazonaws.com\/myblog\/wp-json\/wp\/v2\/tags?post=1572"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}