• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

DemoBytom / DemoEngine / 24967157351

26 Apr 2026 09:11PM UTC coverage: 28.482% (+0.2%) from 28.251%
24967157351

push

coveralls.net

DemoBytom
Add OpenTelemetry to engine

1225 of 4301 relevant lines covered (28.48%)

0.32 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

72.34
/src/Demo.Engine.Core/Services/FpsTimer.cs
1
// Copyright © Michał Dembski and contributors.
2
// Distributed under MIT license. See LICENSE file in the root for more information.
3

4
using System.Diagnostics;
5
using System.Diagnostics.Metrics;
6
using Demo.Engine.Core.Interfaces;
7
using Demo.Engine.Core.ValueObjects;
8
using Microsoft.Extensions.Logging;
9

10
namespace Demo.Engine.Core.Services;
11

12
internal sealed class FpsTimer(
1✔
13
    ILogger<FpsTimer> logger)
1✔
14
    : IFpsTimer
15
{
16
    private static readonly Gauge<int> _upsGauge = Instrumentation.Meter.CreateGauge<int>(
17
        "demo.engine.ups.gauge",
18
        "ups",
19
        "Updates per second");
20

21
    internal sealed class SurfaceFpsCounter(
2✔
22
        ILogger logger,
2✔
23
        RenderingSurfaceId surfaceId)
2✔
24
        : IFpsTimer.IFpsInternalTimer
25
    {
26
        private readonly ILogger _logger = logger;
2✔
27
        private readonly RenderingSurfaceId _surfaceId = surfaceId;
2✔
28

29
        private float _averageMs { get; set; } = 0.0f;
30
        private ulong _fpsCounter { get; set; } = 1;
2✔
31
        private long _start;
32
        private long _seconds = Stopwatch.GetTimestamp();
2✔
33

34
        private static readonly Gauge<int> _fpsGauge = Instrumentation.Meter.CreateGauge<int>(
×
35
            "demo.engine.fps.gauge",
×
36
            "fps",
×
37
            "Frames per second");
×
38

39
        public void Start()
40
            => _start = Stopwatch.GetTimestamp();
2✔
41

42
        public void Stop()
43
        {
44
            var dt = Stopwatch.GetElapsedTime(_start);
2✔
45

46
            _averageMs += (dt.Milliseconds - _averageMs) / _fpsCounter;
2✔
47
            ++_fpsCounter;
2✔
48

49
            if (Stopwatch.GetElapsedTime(_seconds).TotalSeconds >= 1)
50
            {
51
                _logger.LogAverageSurfaceFps(
×
52
                    _surfaceId,
×
53
                    _averageMs,
×
54
                    _fpsCounter);
×
55

56
                _fpsGauge.Record((int)_fpsCounter,
×
57
                    new KeyValuePair<string, object?>("surfaceId", _surfaceId));
×
58

59
                _averageMs = 0.0f;
×
60
                _fpsCounter = 1;
×
61
                _seconds = Stopwatch.GetTimestamp();
×
62
            }
63
        }
2✔
64
    }
65

66
    private readonly ILogger<FpsTimer> _logger = logger;
1✔
67
    private readonly Dictionary<RenderingSurfaceId, SurfaceFpsCounter> _surfaceFpsCounters = [];
1✔
68

69
    public void StartRenderingTimer(
70
        RenderingSurfaceId surfaceId)
71
    {
72
        if (!_surfaceFpsCounters.TryGetValue(
73
            surfaceId,
74
            out var fpsCounter))
75
        {
76
            fpsCounter = new SurfaceFpsCounter(
77
                _logger,
78
                surfaceId);
79

80
            _surfaceFpsCounters.Add(
81
                surfaceId,
82
                fpsCounter);
83
        }
84

85
        fpsCounter.Start();
86
    }
87

88
    public FpsTimerScope StartRenderingTimerScope(
89
        RenderingSurfaceId surfaceId)
90
    {
91
        if (!_surfaceFpsCounters.TryGetValue(
1✔
92
            surfaceId,
1✔
93
            out var fpsCounter))
1✔
94
        {
95
            fpsCounter = new SurfaceFpsCounter(
1✔
96
                _logger,
1✔
97
                surfaceId);
1✔
98

99
            _surfaceFpsCounters.Add(
1✔
100
                surfaceId,
1✔
101
                fpsCounter);
1✔
102
        }
103

104
        return new FpsTimerScope(
1✔
105
            fpsCounter);
1✔
106
    }
107

108
    public void StopRenderingTimer(
109
        RenderingSurfaceId surfaceId)
110
    {
111
        if (_surfaceFpsCounters.TryGetValue(
112
            surfaceId,
113
            out var fpsCounter))
114
        {
115
            fpsCounter.Stop();
116
        }
117
    }
118

119
    private float _averageMs { get; set; } = 0.0f;
120
    private ulong _upsCounter { get; set; } = 1;
1✔
121
    private long _start;
122
    private long _seconds = Stopwatch.GetTimestamp();
1✔
123

124
    public void StartUpdateTimer()
125
        => _start = Stopwatch.GetTimestamp();
1✔
126

127
    public void StopUpdateTimer()
128
    {
129
        var dt = Stopwatch.GetElapsedTime(_start);
1✔
130

131
        _averageMs += (dt.Milliseconds - _averageMs) / _upsCounter;
1✔
132
        ++_upsCounter;
1✔
133

134
        if (Stopwatch.GetElapsedTime(_seconds).TotalSeconds >= 1)
135
        {
136
            _logger.LogAverageUps(
137
                _averageMs,
138
                _upsCounter);
139

140
            _upsGauge.Record((int)_upsCounter);
141

142
            _averageMs = 0.0f;
143
            _upsCounter = 1;
144
            _seconds = Stopwatch.GetTimestamp();
145
        }
146
    }
1✔
147
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc