{"id":1171,"date":"2014-01-15T13:00:57","date_gmt":"2014-01-15T13:00:57","guid":{"rendered":"http:\/\/writeasync.net\/?p=1171"},"modified":"2014-01-12T02:40:16","modified_gmt":"2014-01-12T02:40:16","slug":"using-pla-dll-to-manage-real-time-trace-sessions","status":"publish","type":"post","link":"http:\/\/writeasync.net\/?p=1171","title":{"rendered":"Using PLA.dll to manage real-time trace sessions"},"content":{"rendered":"<p>As previously discussed, PLA.dll can help you <a href=\"http:\/\/writeasync.net\/?p=711\">collect perf counters<\/a>, <a href=\"http:\/\/writeasync.net\/?p=891\">collect ETW trace logs<\/a>, and <a href=\"http:\/\/writeasync.net\/?p=1041\">create performance alerts<\/a>. But what about <a href=\"http:\/\/writeasync.net\/?p=981\">real-time trace sessions<\/a>? PLA.dll can manage those, too!<\/p>\n<p>A real-time trace session has some similarities to a collector set for ETW trace logs, with a few important differences:<\/p>\n<ul>\n<li>The collector set name should be prefixed with the &#8220;Session&#8221; namespace.<\/li>\n<li>The collector can only contain a single trace data collector; the collector should specify the real-time stream mode and a session name.<\/li>\n<li>The collector set is automatically deleted when it is stopped.<\/li>\n<\/ul>\n<p>Armed with this knowledge, we can update the <a href=\"https:\/\/github.com\/brian-dot-net\/writeasync\/tree\/master\/projects\/PlaSample\">PlaSample<\/a> project with support for real-time session management.<\/p>\n<p>We&#8217;ll start with the properties of the collector, defined in a new class since it is different enough from the existing trace collector type:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic class RealTimeTraceCollectorInfo\r\n{\r\n    public RealTimeTraceCollectorInfo(string name)\r\n    {\r\n        this.Name = name;\r\n        this.Providers = new List&lt;ProviderInfo&gt;();\r\n    }\r\n\r\n    public string Name { get; private set; }\r\n\r\n    public uint? BufferSizeInKB { get; set; }\r\n\r\n    public TimeSpan? FlushTimer { get; set; }\r\n\r\n    public uint? MaximumBuffers { get; set; }\r\n\r\n    public uint? MinimumBuffers { get; set; }\r\n\r\n    public IList&lt;ProviderInfo&gt; Providers { get; private set; }\r\n}\r\n<\/pre>\n<p>The <code>ProviderInfo<\/code> type was already defined previously for the existing trace collector code, so we leverage it directly.<\/p>\n<p>Now we just need to create the collector set. Since there are no meaningful operations that a user can do with the data collector set itself (e.g. trying to call <code>Delete()<\/code> will actually throw an exception), we&#8217;ll just return the underlying <code>ISessionController<\/code>.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic ISessionController Create()\r\n{\r\n    \/\/ Data collector set is the core abstraction for collecting diagnostic data.\r\n    DataCollectorSet dcs = new DataCollectorSet();\r\n\r\n    \/\/ Create a data collector for traces.\r\n    ITraceDataCollector dc = (ITraceDataCollector)dcs.DataCollectors.CreateDataCollector(DataCollectorType.plaTrace);\r\n    dc.name = this.Name;\r\n    dcs.DataCollectors.Add(dc);\r\n\r\n    \/\/ We need to set real-time mode and the session name\r\n    dc.StreamMode = StreamMode.plaRealTime;\r\n    dc.SessionName = this.Name;\r\n\r\n    \/\/ Set various values (if present)\r\n    SetValue(dc, this.BufferSizeInKB, (d, v) =&gt; d.BufferSize = v);\r\n    SetValue(dc, this.FlushTimer, (d, v) =&gt; d.FlushTimer = (uint)v.TotalSeconds);\r\n    SetValue(dc, this.MaximumBuffers, (d, v) =&gt; d.MaximumBuffers = v);\r\n    SetValue(dc, this.MinimumBuffers, (d, v) =&gt; d.MinimumBuffers = v);\r\n\r\n    \/\/ Build up the list of providers.\r\n    foreach (ProviderInfo providerInfo in this.Providers)\r\n    {\r\n        TraceDataProvider provider = dc.TraceDataProviders.CreateTraceDataProvider();\r\n        dc.TraceDataProviders.Add(provider);\r\n\r\n        provider.Guid = providerInfo.Id;\r\n        AddValue(provider.KeywordsAll, providerInfo.KeywordsAll);\r\n        AddValue(provider.KeywordsAny, providerInfo.KeywordsAny);\r\n        AddValue(provider.Level, providerInfo.Level);\r\n    }\r\n\r\n    \/\/ Now actually create (or modify existing) the set.\r\n    \/\/ We explicitly specify the 'Session' namespace for real-time collectors.\r\n    dcs.Commit(&quot;Session\\\\&quot; + this.Name, null, CommitMode.plaCreateOrModify);\r\n\r\n    \/\/ Return an opaque wrapper with which the user can control the session.\r\n    return new CollectorSetWrapper(dcs);\r\n}\r\n\r\nprivate static void SetValue&lt;TClass, TValue&gt;(TClass c, TValue? v, Action&lt;TClass, TValue&gt; setValue) where TValue : struct\r\n{\r\n    if (v.HasValue)\r\n    {\r\n        setValue(c, v.Value);\r\n    }\r\n}\r\n\r\nprivate static void AddValue&lt;TValue&gt;(IValueMap map, TValue? v) where TValue : struct\r\n{\r\n    if (v.HasValue)\r\n    {\r\n        map.Add(v.Value);\r\n    }\r\n}\r\n<\/pre>\n<p>The user just has to call <code>Start()<\/code> to begin delivering events and <code>Stop()<\/code> to stop <strong>and delete<\/strong> the session, as shown in this sample code:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nprivate static void CreateRealTimeTraceCollector()\r\n{\r\n    RealTimeTraceCollectorInfo info = new RealTimeTraceCollectorInfo(&quot;MyRealTimeCollector&quot;);\r\n\r\n    \/\/ Microsoft-Windows-Kernel-Process         \r\n    Guid providerId = new Guid(&quot;{22FB2CD6-0E7B-422B-A0C7-2FAD1FD0E716}&quot;);\r\n\r\n    info.Providers.Add(new ProviderInfo(providerId) { Level = 5 });\r\n\r\n    ISessionController controller = info.Create();\r\n    controller.Start();\r\n\r\n    Thread.Sleep(5000);\r\n\r\n    controller.Stop();\r\n}\r\n<\/pre>\n<p>As always, remember to run <strong>elevated<\/strong> to manage real-time trace sessions.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>As previously discussed, PLA.dll can help you collect perf counters, collect ETW trace logs, and create performance alerts. But what about real-time trace sessions? PLA.dll can manage those, too! A real-time trace session has some similarities to a collector set&hellip; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[71],"tags":[],"class_list":["post-1171","post","type-post","status-publish","format-standard","hentry","category-diagnostics"],"_links":{"self":[{"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/posts\/1171","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/writeasync.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1171"}],"version-history":[{"count":0,"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/posts\/1171\/revisions"}],"wp:attachment":[{"href":"http:\/\/writeasync.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1171"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/writeasync.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1171"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/writeasync.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1171"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}