StreamLink.NET
Clock Offset and Latency Measurement

StreamLink can calculate the clock offset between Liberator and StreamLink, the one-way heartbeat message latency between Liberator and StreamLink, and the latency of the records it receives from Liberator. StreamLink stores the results of these calculations and makes them available through the StreamLink API.

The clock offset calculation can be enabled or disabled, but must be enabled if you want StreamLink to calculate heartbeat message or record latency, as it is used in all latency calculations.

Related Documents

StreamLink Configuration XML Reference: Describes the XML-based tags and attributes you can use to configure StreamLink applications.

 

Clock Offset

The following parameters configure the sync messages that determine when clock offset is calculated:

The sync message parameters can be specified using the <RttpService> tag in the application XML configuration file, or in code as attributes of an IConnectionConfiguration instance:

Configuring sync messages in XML

  
<RttpService Name="Example RTTP Service" SyncSpacing="2000" SyncInitialSpacing="200" SyncSize="10">
  

Configuring sync messages in StreamLink code

  
IStreamLinkConfiguration config = SimpleConfiguration.CreateType1Connection("localhost", 15000);
IConnectionConfiguration connectionConfiguration = config.ConnectionConfiguration;
connectionConfiguration.SyncSpacing = 2000;
connectionConfiguration.SyncInitialSpacing = 200;
connectionConfiguration.SyncSize = 10;
  

When StreamLink is configured to calculate clock offset, it periodically sends time stamped sync messages to Liberator. Liberator adds its own timestamp to each sync message it receives, and immediately returns the sync message to StreamLink. StreamLink uses the sync message with the quickest round trip time from the last SyncSize messages to calculate the clock offset between Liberator and StreamLink. Because the value of SyncInitialSpacing is less than the value of SyncSpacing, the time it takes to send and receive the first SyncSize messages is reduced.

You can retrieve the result of the latest clock offset calculation using the Statistics property of an IStreamLinkProvider.

  
IStreamLinkProvider provider = myStreamLink.StreamLinkProvider;
IStatistics statistics = provider.Statistics;
long clockOffset = statistics.ClockOffset;
  

Heartbeat Latency

Liberator 5.1 and above can be requested to send heartbeat messages that StreamLink uses to calculate the average and latest heartbeat message latency between Liberator and StreamLink. Note that heartbeat message latency can only be calculated if the clock offset between Liberator and StreamLink is available (see Clock Offset above).

The following parameter determines how often Liberator sends a heartbeat message:

The heartbeat message interval can be specified using the <RttpService> tag in the application XML configuration file, or in code as attributes of an IConnectionConfiguration instance:

Configuring the heartbeat in XML

  
<RttpService Name="Example RTTP Service" HeartbeatInterval="4000">
  

Configuring the heartbeat in StreamLink code

  
IStreamLinkConfiguration config = SimpleConfiguration.CreateType1Connection("localhost", 15000);
IConnectionConfiguration connectionConfiguration = config.ConnectionConfiguration;
connectionConfiguration.HeartbeatInterval = 4000;
  

You can retrieve the calculated latency of heartbeat messages using the Statistics property of an IStreamLinkProvider:

  
IStreamLinkProvider provider = myStreamLink.StreamLinkProvider;
IStatistics statistics = provider.Statistics;
long latestLatency = statistics.Latency;
long averageLatency = statistics.AverageLatency;
  

Note that StreamLink uses the arithmetic average of the last SyncSize latency values to calculate the average heartbeat latency (see Clock Offset above for a description of SyncSize).

Statistics Listener

You can implement and register a Caplin.StreamLink.IStatisticsListener that is notified when the statistics object containing the clock offset and heartbeat latency is updated:

  
public class ExampleStatisticsListener: IStatisticsListener
{
    public void StatisticsUpdated(IStatisticsEvent ev)
    {
        String msg = String.Format("Received statistics update {0}", ev.Statistics.ToString());
        this.Logger.Log(SourceLevels.Information, "Example", msg);
    }  
}

IStatisticsListener listener = new ExampleStatisticsListener();
IStreamLinkProvider provider = myStreamLink.StreamLinkProvider;
provider.AddStatisticsListener(listener);
  

In this example, the statistics listener ExampleStatisticsListener simply logs the latest statistics as a string.

Record Latency

If StreamLink is configured to calculate the clock offset between Liberator and StreamLink, and if the records received from Liberator contain a timestamp field, the getLatency(string timeStampField) method of the IRecordEvent interface can be used to obtain the latency of received records.

  
public void RecordUpdated(ISubscription subscription, IRecordEvent ev)
{
    long latency = ev.getLatency("dTimeStamp");
    this.Logger.Log(SourceLevels.Information, "Example", "Latency= " + latency);
}
  

In this example, the custom RecordUpdated() method simply logs the record latency as a string.

The latency of type 2 and type 3 records can be retrieved in a similar manner using the IRecordType2Event and IRecordType3Event interfaces.

Note that you can configure Liberator to add a timestamp field to every record that it sends, by adding the following line to the Liberator configuration file rttpd.conf:

  
timestamp-field dTimeStamp
  

For further information, see the document Caplin Liberator Administration Guide.