diff --git a/Demos.sln b/Demos.sln
index d883716..dabb7b6 100644
--- a/Demos.sln
+++ b/Demos.sln
@@ -6,7 +6,8 @@ MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenTap.Plugins.Demo.Battery", "Battery\OpenTap.Plugins.Demo.Battery.csproj", "{6ED5480D-D6A0-48E3-9B94-599568294626}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenTap.Plugins.Demo.ResultsAndTiming", "ResultsAndTiming\OpenTap.Plugins.Demo.ResultsAndTiming.csproj", "{400E13F0-E63E-496B-9E3F-955BECC22444}"
-
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Metrics", "MetricsDemo\Metrics.csproj", "{AD785327-C02C-41CE-894C-AED4C8625172}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -22,6 +23,10 @@ Global
{400E13F0-E63E-496B-9E3F-955BECC22444}.Debug|Any CPU.Build.0 = Debug|Any CPU
{400E13F0-E63E-496B-9E3F-955BECC22444}.Release|Any CPU.ActiveCfg = Release|Any CPU
{400E13F0-E63E-496B-9E3F-955BECC22444}.Release|Any CPU.Build.0 = Release|Any CPU
+ {AD785327-C02C-41CE-894C-AED4C8625172}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AD785327-C02C-41CE-894C-AED4C8625172}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AD785327-C02C-41CE-894C-AED4C8625172}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AD785327-C02C-41CE-894C-AED4C8625172}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/MetricsDemo/Metrics.csproj b/MetricsDemo/Metrics.csproj
new file mode 100644
index 0000000..dda1640
--- /dev/null
+++ b/MetricsDemo/Metrics.csproj
@@ -0,0 +1,47 @@
+
+
+ false
+ false
+ false
+ true
+
+
+ netstandard2.0
+ TUI
+
+
+
+ package.xml
+ false
+
+
+
+ true
+
+
+
+
+ net472
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/MetricsDemo/ProcessMetrics.cs b/MetricsDemo/ProcessMetrics.cs
new file mode 100644
index 0000000..679dc10
--- /dev/null
+++ b/MetricsDemo/ProcessMetrics.cs
@@ -0,0 +1,67 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using OpenTap.Metrics;
+
+namespace OpenTap.Demonstration
+{
+
+ public class ProcessMetrics : IMetricSource, IOnPollMetricsCallback
+ {
+ public Stopwatch runnerTimer = Stopwatch.StartNew();
+ public Dictionary prevCpuByPid = new Dictionary();
+ public Dictionary prevCpuTotalByPid = new Dictionary();
+
+ [Metric("Process Memory", null, MetricKind.Poll, DefaultPollRate = 5, DefaultEnabled = true)]
+ public double Memory { get; set; }
+ [Metric("Process CPU", null, MetricKind.Poll, DefaultPollRate = 5, DefaultEnabled = true)]
+ public double CPU { get; set; }
+
+ public ProcessMetrics()
+ {
+ // Initialize the process metrics
+ }
+
+ public void OnPollMetrics(IEnumerable metrics)
+ {
+ Memory = GetMemoryUsageForProcess(Process.GetCurrentProcess().Id);
+ CPU = GetCPUUsageForProcess(Process.GetCurrentProcess().Id);
+ }
+
+ private float GetCPUUsageForProcess(int processId)
+ {
+ if (processId == 0)
+ return 0;
+ var proc = Process.GetProcessById(processId);
+ long runnerCpu = proc.TotalProcessorTime.Ticks;
+ long runnerCpuTotal = runnerTimer.Elapsed.Ticks;
+ if (!prevCpuByPid.ContainsKey(processId))
+ {
+ prevCpuByPid[processId] = 0;
+ prevCpuTotalByPid[processId] = 0;
+ }
+
+ var result = (float)(100.0 * (runnerCpu - prevCpuByPid[processId]) / (runnerCpuTotal - prevCpuTotalByPid[processId])) / Environment.ProcessorCount;
+ prevCpuByPid[processId] = runnerCpu;
+ prevCpuTotalByPid[processId] = runnerCpuTotal;
+ return result;
+ }
+
+ private long GetMemoryUsageForProcess(int processId)
+ {
+ if (processId == 0)
+ return 0;
+ try
+ {
+ var proc = Process.GetProcessById(processId);
+ return proc.WorkingSet64;
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException("'Memory usage' for a process metric failed", ex);
+ }
+ }
+
+ }
+
+}
diff --git a/MetricsDemo/package.xml b/MetricsDemo/package.xml
new file mode 100644
index 0000000..5e3126e
--- /dev/null
+++ b/MetricsDemo/package.xml
@@ -0,0 +1,16 @@
+
+
+
+ This is my OpenTAP plugin package.
+
+
+
+
+
+