SDN - Lync Dialog Listener (LDL)

Der Lync Dialog Listener ist ein Serverprozess, der auf jedem Lync Frontend Server zu installieren ist und als CsTrustedApplication die SIP-Dialoge mit überwacht und Metadaten extrahiert und an den Lync Dialog Manager weiter gibt. Diese Seite beschreibt Installation aber auch Hintergründe und Funktionsweise.

There is an short english version available at SDN Live View

Hinweis:
Normalerweise installiert man zuerst das Backend, d.h. den LDM ehe man den LDL einrichtet.

Download

Die Installationskomponente ist Bestandteil des Lync SDN API, welches kostenfrei herunter geladen werden kann.

Lync SDN Interface
Version 2.1 http://www.microsoft.com/en-us/download/details.aspx?id=44274

Aus dem Paket benötigen sie das Paket "LyncSDNAPI.msi".

Installation Lync Dialog Listener

Der Lync Dialog Listener verbirgt sich in dem API-Paket, welches nur auf einem Lync Frontend installiert werden kann. Darauf weist Sie das Setup auch am Anfang gleich hin:

Sollten sie bereits die Version 2.0 installiert haben, dann müssen Sie diese zuerst manuell deinstallieren. Die Version 2.1 ersetzt nicht alleine die Vorgängerversion sondern verhindert die Installation.

Hinweis
Per Default installiert sich der LDL nach "C:\Program Files\Microsoft Lync Server\Microsoft Lync Dialog Listener\". Er funktioniert auch mit Lync 2010. Auf einem Lync 2013 Server sollten Sie den Pfad vielleicht anpassen, damit im Programmverzeichnis kein weiteres Verzeichnis "neben Lync 2013" auftaucht.

Bei der Wahl des Zielverzeichnisses sollten Sie überlegen, ob sie das LOG-Verzeichnis vielleicht nicht gerade in das TEMP-Verzeichniss des aktuell installierenden Benutzers legen lassen. Ich habe das auf "C:\Program Files\Microsoft Lync Server\Microsoft Lync Dialog Listener\SDNLOG" geändert.

Im zweiten Schritt müssen Sie hinterlegen, wohin der LDL die Daten sendet.

Die drei Optionen führen zu drei unterschiedlichen Folgedialogen.

  • Colocated
    Die Daten werden lokal an einen LDM gesendet.
  • Pool mit PoolFQDN
    Hierbei unterstützt der LDL optional die Abfrage eines SRV-Record

    Der Dienst sucht dabei nach einen _sdninternal._https.<domain>, der als SRV-Record den Namen und Port des Zielsystems mit dem LDM enthält
    Siehe auch "Setting up DNS SRV record " http://msdn.microsoft.com/en-us/library/office/dn785198(v=office.15).aspx

    Ohne SRV-Record kann ein FQDN angegeben werden:
  • Active/Standby
    Hierbei müssen Sie dann die beiden FQDN-Adressen eingeben

Ich nutze in der Regel den "Pool", weil ich damit einen Namen hinterlege und wer heute schon mit Hochverfügbarkeit" arbeitet, wird sowieso mit Loadbalancern arbeiten.

Seit der Version 2.1 kann nun auch eine Authentifizierung zwischen dem LDL und dem LDM vorgegeben werden.

Dienstkonto
Laut Release Notes installiert der Lync Dialog Watcher einen Windows Dienste, welcher sich mit einem Domänen-Benutzer anmelden kann. Dieses Konto muss aber in der lokalen Gruppe "RTC Server Applications" Mitglied sein.

Bei der Installation werden Sie nach der Anmeldung gefragt. "Network Service Account" ist per Default ausgewählt.

Wenn Sie stattdessen ein Dienstkonto verwenden wollen, dann müssen Sie im nächsten Dialog die Anmeldedaten eingeben.

Hinweis: Manchmal stellt das Setup dies nicht korrekt ein. Prüfen Sie dies nach der Installation, Update oder Reparatur, ob der Dienst immer noch mit dem Konto konfiguriert ist

Mehr passiert erst einmal nicht. Der Dienst startet, überwacht die SIP Dialoge und meldet diese per HTTP an den hinterlegten SDN Manager. Der Dienst wird als "Automatic (Delayed)" gestartet und ist von den Diensten "CNG Key Isolation" und natürlich "Lync Server Front-End" abhängig.

Blick hinter das Setup

Ich habe die API erst auf meinem Notebook im ICE untersucht und da hatte ich kleinen Lync Server zur Hand. Aber ein MSI-Paket lässt sich ja auch auch so auspacken.

REM Entpacken des MSI Archiv
msiexec /a D:\SDN\LyncSDNAPI.msi /qb TARGETDIR=D:\SDN\sdk

Danach hatte ich eine entsprechende Verzeichnisstruktur mit vielen einzelnen Dateien. Das gibt eine Vorschau auf die Installation auf dem Server.

Sie erkennen hier das eigentliche Dienstprogramm und einige DLLs drum herum. Interessant fand ich z.B.: die ServerAgent.dll, die den "dritten" Weg bei der MSPL-Schnittstelle aufzeigt.

Unter dem Verzeichnis ProgramData\Microsoft\Lync SDN API finden Sie eine REGISTER.PS1, die erst ein paar alte Eventlog-Quellen entfernt, die QoE Einrichtung prüft und ggfls. sie wart, dass ohne QoE keine QoE-Daten gemeldet werden können. Zuletzt registriert das Skript die CsTrustedApplication mit folgenden Parametern.

New-CsServerApplication `
   -Identity $registerMe -Uri http://www.microsoft.com/LC/NetworkEnlightenment `
   -Enabled $true `
   -Critical $false `
   -Priority 0

Dann  wartet die CMS-Replikation ab und starten den vorher schon durch das MSI installierten Dienst "Lync Dialog Listener". Wenn Sie die Konfiguration beim Setup korrekt eingegeben haben, ist die Einrichtung auf dem Frontend schon abgeschlossen.

Konfig-Datei

Schaut man in das Programmverzeichnis des soeben installierten Diensts, dann finden Sie eine .NET-typische Konfigurationsdatei, die den gleichen Namen wie die EXE hat und die Extension ".CONFIG" hat.

Diese Datei ist sehr interessant, da sie zum einen die beim Setup gemachten Einstellungen beinhaltet aber noch viel mehr auch Einstellungen eröffnet, die meine Aufmerksamkeit auf sich gezogen haben. Einfach zu finden ist noch die URL des Servers. (Auszug)

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="submituri" value="http://nawex13:80/LDL"/>  <!-- URI to locate the LSM (used unless checkdns is true) -->
    <add key="submituri2" value="http://localhost:9333/LDL"/>  <!-- URI to locate the LSM (used unless checkdns is true) -->
    <add key="alternativeuri" value=""/>  <!-- secondary URI to locate an LSM, in case the primäry is unavailable in a Active/Standby configuration -->
    <add key="clientcertificateid" value=""/> <!-- thumbprint of a client certificate to use to authenticate the LDL with the LSM -->
    <add key="checkdns" value="False"/>  <!-- use a URI provided by the DNS SRV record für locating a pool of LSMs -->
  </appSettings>
</configuration>

LDL Protokollierung

Interessant sind aber auch die Logging-Funktionen. Die Ausgabedateien und deren Formatierung werden in der XML-Datei definiert.

Achtung:
Die Protokolldateien werden nicht automatisch nach Ablauf einer Zeit gelöscht. Sie sollten ihre Server überwachen, um Engpässe bei der Festplattenkapazität zu erkennen und vielleicht die alten Dateien auch löschen, z.B.: durch einen geplanten Task

.NET-typisch werden zuerst Listener und Formatter definiert. Das sind alles "FileWriter", die nach 10 Megabyte eine neue Datei anfangen und jeden Tag eine neue Datei anlegen. Zudem werden über "Formatter" die Ausgaben umgestaltet:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <loggingConfiguration name="" tracingEnabled="true" defaultCategory="Error">
    <listeners>
      <add name="LNEAppLog" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.RollingFlatFileTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.RollingFlatFileTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        fileName="%TEMP%\LNEApp.log" footer="" formatter="LNEDetailFormatter"
        header="" rollFileExistsBehavior="Increment" rollInterval="Day"
        rollSizeKB="10000" traceOutputOptions="LogicalOperationStack, DateTime, Timestamp, ProcessId, ThreadId, Callstack" />
      <add name="AllDataLog" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.RollingFlatFileTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.RollingFlatFileTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        fileName="%TEMP%\AllData.log" footer="" formatter="SimpleOutput"
        header="" rollFileExistsBehavior="Increment" rollInterval="Day"
        rollSizeKB="10000" />
      <add name="QoEInputDataLog" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.RollingFlatFileTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.RollingFlatFileTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        fileName="%TEMP%\QoEInputData.log" footer="" formatter="SimpleOutput"
        header="" rollFileExistsBehavior="Increment" rollInterval="Day"
        rollSizeKB="10000" />


    <formatters>
      <add type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        template="{timestamp(local:O)}{tab}{message}{tab}{dictionary({tab}{key}: {value})}"
        name="LNEOverviewFormatter" />
      <add type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        template="{timestamp(local:O)}{tab}[{category}]{tab}{message}{tab}{dictionary({tab}{key}: {value})}"
        name="LNEDetailFormatter" />
      <add type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        template="{message}{newline}" name="SimpleOutput" />
    </formatters>

Schon der Lync Dialog Listener kann also mehr als nur die SIP-Dialoge an den Lync Dialog Manager senden, sondern schon selbst loggen. Allerdings muss die Funktion aktiviert sein. Dazu gibt es weitere "Schalter":

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <loggingConfiguration name="" tracingEnabled="true" defaultCategory="Error">
    <categorySources>
      <add switchValue="Off" name="Debug">
        <listeners>
          <add name="LNEAppLog" />
        </listeners>
      </add>
      <add switchValue="All" name="Init">
        <listeners>
          <add name="LNEAppLog" />
        </listeners>
      </add>
      <add switchValue="All" name="Error">
        <listeners>
          <add name="LNEAppLog" />
        </listeners>
      </add>
      <add switchValue="All" name="Settings">
        <listeners>
          <add name="LNEAppLog" />
        </listeners>
      </add>
      <add switchValue="All" name="CleanUp">
        <listeners>
          <add name="LNEAppLog" />
        </listeners>
      </add>
      <add switchValue="Off" name="QoEInputData">
        <listeners>
          <add name="QoEInputDataLog" />
          <add name="AllDataLog" />
        </listeners>
      </add>
      <add switchValue="Off" name="DialogData">
        <listeners>
          <add name="AllDataLog" />
          <add name="DialogDataLog" />
        </listeners>
      </add>

Dies ist nur eine Teilmenge aber es ist unschwer zu erkennen, das "Init", "Error", Settings" auf "ALL" steht, während "DEBUG" aber auch "QoEInputData" und "DialogData" auf "Off" steht.

LDL QoE Protokollierung

Das ist aber noch noch alles, denn passend zur QoE gibt es noch Einstellungen, mit denen anscheinend eine Datenbank mit Anmeldedaten hinterlegt werden kann:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
...
    <add key="qoedatabasename" value="" />
    <add key="qoedatabaseUsername" value="" />
    <add key="qoedatabasepassword" value="" />

Leider weiß ich nicht, wie die Daten hier anzugeben sind, ob der LDL auf die Lync QoE-Datenbank zugreifen will oder dies eine autarke Datenbank ist. Weiter unten im XML-File werden dann sogar noch Grenzwerte definiert. Hier ein Auszug:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="audio-DegradationAvgOptimal" value="0.6" />
    <add key="audio-DegradationAvgAcceptable" value="1" />
    <add key="audio-RoundTripOptimal" value="200" />
    <add key="audio-RoundTripAcceptable" value="500" />
    <add key="audio-PacketLossRateOptimal" value="0.02" />
    <add key="audio-PacketLossRateAcceptable" value="0.05" />
    <add key="audio-JitterInterArrivalOptimal" value="15" />
    <add key="audio-JitterInterArrivalAcceptable" value="25" />
    <add key="audio-RatioConcealedSamplesAvgOptimal" value="0.03" />

Vielleicht können Sie nun verstehen, warum mich die "Lync SDN API" elektrisiert hat. Ich hatte schon länger vor ein MSPL-Skript zu schreiben, welches auf dem Server aus den SIP-Dialogen z.B. solche Daten extrahiert und auch erfasst, welche "INVITE" und "BYE"-Pakete einen Verbindungsaufbau und Abbau anzeigen. Mit der Lync SDN API scheint Microsoft schon ein fertiges Modul mir zu liefern.

Und ich werde den Verdacht nicht los, dass dieses Modul in Office 365 vielleicht schon aktiv für die Überwachung von Lync Servern genutzt wird, denn so lassen sich auch Fehler quasi in Realtime erkennen. Doch dazu später mehr.

Dienst manuell aufrufen

Auch wenn das Setup den Dienst schon komplett installiert hat, können Sie die EXE auch interaktiv in einer CMD-Box starten.

Achtung:
Per Default läuft der Dienst als "Network Service" und hat ausreichend Rechte. Wird er als "Benutzer" gestartet, muss das Konto Mitglied der lokalen Gruppe "RTC Server Applications" sein.

Natürlich beschwert sich das Programm, dass es kein Dienst ist und ohne Berechtigungen kann er auch keine Performance Counter anlegen und auf meiner Workstation kommt das Programm schon gar nicht an einen Lync Server. Aber sie können so natürlich Fehler beim Start erkennen.

Zudem ist schön zu sehen, dass das Programm eine Verbindung zum Server aufbaut und nicht umgekehrt. Dazu versucht es den "Lync ServerAgent" zu erreichen.

SIP Adress Obfuscator

Wenn Sie sich die XML-Daten anschauen, dann erkennen sie hier nicht, dass der UserPart der SIP-Adresse eigentlich "frank.carius" lautet. Der Default scheint der LDL den Userpart einer SIP-Adresse zu "verstümmeln". Ich tippe auf einen einfachen Hash-Wert. Der Schutz ist aber nicht besonders hoch, denn auch wenn der Vorgang nicht reversibel ist, so ergibt der gleiche Eingabewert auch immer die gleiche Ausgabe. Ich brauche zumindest für die internen SIP-URIs einfach nur per CSV diese zu exportieren und dem Programm "SipObfuscator.exe" vorzuwerfen.

C:\SDN\sdk\Program Files\Microsoft Lync Server\Microsoft Lync SDN API\SipObfuscator.exe" frank.carius@msxfaq.net
FB051BCCFF88FAD68E3BE528C9D8FE08@msxfaq.net

So kann ich mir ganz schnell eine eigene "Rainbow-Table" erstellen um jeder kryptischen SIP-URI den Klarnamen zuzuordnen.

Sie können diese unkenntlichmachung abschalten. In der Konfigurationsdatei stellen Sie den Wert von "hidepii" auf False.

Beim SDN SDK 2.1 ist der Key gar nicht mehr vorhanden, aber kann natürlich addiert werden

    <add key="hidepii" value="False" />  <!-- Disable Obfuscation  -->

Dann werden die SIP-URLs unverfälscht weiter gegeben. Das funktioniert auch mit SDN 2.1.

Eventlog

Der Lync Dialog Manager legt auch eine eigene Eventlog Kategorie an, die als eigener Eintrag zu sehen ist:

Folgende Eventlogs habe ich bislang gesehen.

Severity Eventid Text

Error

0

Lync Dialog Listener failed: Could not contact the Lync ServerAgent and the Lync Front-End

Information

2

Identified a conversation with less than acceptable quality

Error

2

ERROR: Server unavailable

Error

3

ERROR: Must be running under an account that is a member of the "RTC Server Applications" local group

Error

8

Could not contact the Lync ServerAgent and the Lync Front-End

Information

101

Lync DialogListener NT Service started.

Information

104

The Service was stopped.

Etwas irritiert mich die doppelvergabe der ID 2 für zwei unterschiedliche Events.

Performance Counter

DDer Lync Dialog Watcher installiert nicht nur ein Eventlog, sondern auch noch ein paar Performance Counter

Die Beschreibung der Felder liefert aber nur bedingt weitere Informationen

Counter Beschreibung

# call messages failed

Total number of send failures (regardless whether resending succeeded)

# call messages sent overall

Total number of call related messages sent successfully - counting every destination

# messages / Sec

Number of messages sent per second

# messages attempted to send overall

Number of messages overall attempted to send.

# messages attempting to send

Number of messages currently attempting to send.

# messages failed processing

Total number messages that failed during processing

# Messages Received

Total number of call related messages received

# undeliverable messages

Total number messages that were not received at a destination - even with attempting to resend

# unique call messages sent

Total number of unique call related messages attempted to sent (regardless of to how many destinations)

length of longest queue

Longest send message queue

HTTP-Ziele, Sicherheit

Per Default erfolgt die Verbindung vom LDL-Service zum nächsten Hop per HTTP und damit unverschlüsselt. Auch konnte ich nicht sehen, dass der LDL irgendwie eine Authentifizierung unterstützt. Das ist aus Sicherheitsaspekten natürlich kritisch zu sehen aber auf der anderen Seite natürlich auch die einfachste Version. Da Server und Gegenstelle in der Regel in einem gesicherten Servernetz stehen, kann dies toleriert werden. Die SIP-URLs sind ja per Default zumindest "leicht" unkenntlich gemacht.

Das Backend, welches durch den Lync Dialog Manager bereit gestellt wird, bietet aber neben http/9333 auch noch eine https-Verbindung auf Port 9332 an. Seit SDN 2.1 kann der LDL sich gegenüber dem LDM auch mit einem Client Zertifikat ausweisen.

Weitere Links