I-Synergy.Framework.AspNetCore.Monitoring 2025.11029.10201.38-preview

Prefix Reserved
This is a prerelease version of I-Synergy.Framework.AspNetCore.Monitoring.
There is a newer prerelease version of this package available.
See the version list below for details.
dotnet add package I-Synergy.Framework.AspNetCore.Monitoring --version 2025.11029.10201.38-preview
                    
NuGet\Install-Package I-Synergy.Framework.AspNetCore.Monitoring -Version 2025.11029.10201.38-preview
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="I-Synergy.Framework.AspNetCore.Monitoring" Version="2025.11029.10201.38-preview" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="I-Synergy.Framework.AspNetCore.Monitoring" Version="2025.11029.10201.38-preview" />
                    
Directory.Packages.props
<PackageReference Include="I-Synergy.Framework.AspNetCore.Monitoring" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add I-Synergy.Framework.AspNetCore.Monitoring --version 2025.11029.10201.38-preview
                    
#r "nuget: I-Synergy.Framework.AspNetCore.Monitoring, 2025.11029.10201.38-preview"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package I-Synergy.Framework.AspNetCore.Monitoring@2025.11029.10201.38-preview
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=I-Synergy.Framework.AspNetCore.Monitoring&version=2025.11029.10201.38-preview&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=I-Synergy.Framework.AspNetCore.Monitoring&version=2025.11029.10201.38-preview&prerelease
                    
Install as a Cake Tool

I-Synergy Framework AspNetCore Monitoring

Real-time monitoring and communication infrastructure using SignalR for ASP.NET Core applications. This package provides SignalR hub integration, monitor services for publishing events, connection management, and group-based messaging for building real-time dashboards, notifications, and collaboration features.

NuGet License .NET

Features

  • SignalR hub integration with OpenIddict authentication
  • Monitor service for publishing real-time events to groups
  • Connection lifecycle management with automatic group assignment
  • User and account-based groups for tenant isolation
  • Generic event publishing with typed entity support
  • Real-time notifications for connected/disconnected users
  • Detailed error logging for debugging SignalR connections
  • Scalable architecture supporting multiple concurrent connections

Installation

Install the package via NuGet:

dotnet add package I-Synergy.Framework.AspNetCore.Monitoring

Quick Start

1. Configure Monitoring Services

In your Program.cs:

using ISynergy.Framework.AspNetCore.Monitoring.Extensions;

var builder = WebApplication.CreateBuilder(args);

// Add monitoring with SignalR (specify your entity type)
builder.Services.AddMonitorSignalR<MonitorEvent>();

builder.Services.AddControllers();

var app = builder.Build();

// Map the monitor hub
app.MapHub<MonitorHub>("/hubs/monitor");

app.Run();

2. Using the Monitor Service

Publish events to connected clients:

using ISynergy.Framework.Monitoring.Abstractions.Services;
using Microsoft.AspNetCore.Mvc;

[ApiController]
[Route("api/[controller]")]
public class OrdersController : ControllerBase
{
    private readonly IMonitorService<OrderEvent> _monitorService;

    public OrdersController(IMonitorService<OrderEvent> monitorService)
    {
        _monitorService = monitorService;
    }

    [HttpPost]
    public async Task<IActionResult> CreateOrder([FromBody] CreateOrderRequest request)
    {
        var order = await CreateOrderAsync(request);

        // Publish event to all users in the account group
        await _monitorService.PublishAsync(
            channel: request.AccountId.ToString(),
            eventname: "OrderCreated",
            data: new OrderEvent
            {
                OrderId = order.Id,
                Status = "Created",
                CreatedAt = DateTime.UtcNow
            });

        return Ok(order);
    }

    [HttpPut("{id}")]
    public async Task<IActionResult> UpdateOrderStatus(
        int id,
        [FromBody] UpdateOrderStatusRequest request)
    {
        var order = await UpdateOrderAsync(id, request);

        // Notify users about status change
        await _monitorService.PublishAsync(
            channel: order.AccountId.ToString(),
            eventname: "OrderStatusChanged",
            data: new OrderEvent
            {
                OrderId = order.Id,
                Status = order.Status,
                UpdatedAt = DateTime.UtcNow
            });

        return Ok(order);
    }
}

public class OrderEvent
{
    public int OrderId { get; set; }
    public string Status { get; set; }
    public DateTime CreatedAt { get; set; }
    public DateTime? UpdatedAt { get; set; }
}

3. Client-Side Connection (JavaScript/TypeScript)

Connect to the SignalR hub from your frontend:

import * as signalR from "@microsoft/signalr";

// Configure connection with authentication
const connection = new signalR.HubConnectionBuilder()
    .withUrl("/hubs/monitor", {
        accessTokenFactory: () => getAuthToken()
    })
    .withAutomaticReconnect()
    .configureLogging(signalR.LogLevel.Information)
    .build();

// Listen for order events
connection.on("OrderCreated", (event) => {
    console.log("New order created:", event);
    updateOrdersList(event);
});

connection.on("OrderStatusChanged", (event) => {
    console.log("Order status changed:", event);
    updateOrderStatus(event);
});

// Listen for user connection events
connection.on("Connected", (message) => {
    console.log(`User connected: ${message.Data}`);
    updateOnlineUsers(message);
});

connection.on("Disconnected", (message) => {
    console.log(`User disconnected: ${message.Data}`);
    updateOnlineUsers(message);
});

// Start connection
async function startConnection() {
    try {
        await connection.start();
        console.log("SignalR Connected");
    } catch (err) {
        console.error("SignalR Connection Error:", err);
        setTimeout(startConnection, 5000);
    }
}

// Handle disconnections
connection.onclose(async () => {
    await startConnection();
});

// Get authentication token
function getAuthToken() {
    return localStorage.getItem("authToken");
}

// Start the connection
startConnection();

4. Client-Side Connection (.NET Client)

Connect from a .NET application:

using Microsoft.AspNetCore.SignalR.Client;

public class MonitorClient : IAsyncDisposable
{
    private readonly HubConnection _connection;

    public MonitorClient(string hubUrl, string accessToken)
    {
        _connection = new HubConnectionBuilder()
            .WithUrl(hubUrl, options =>
            {
                options.AccessTokenProvider = () => Task.FromResult(accessToken);
            })
            .WithAutomaticReconnect()
            .Build();

        // Register event handlers
        _connection.On<OrderEvent>("OrderCreated", OnOrderCreated);
        _connection.On<OrderEvent>("OrderStatusChanged", OnOrderStatusChanged);
        _connection.On<HubMessage<string>>("Connected", OnUserConnected);
        _connection.On<HubMessage<string>>("Disconnected", OnUserDisconnected);
    }

    public async Task StartAsync()
    {
        await _connection.StartAsync();
    }

    private void OnOrderCreated(OrderEvent orderEvent)
    {
        Console.WriteLine($"Order created: {orderEvent.OrderId}");
    }

    private void OnOrderStatusChanged(OrderEvent orderEvent)
    {
        Console.WriteLine($"Order {orderEvent.OrderId} status: {orderEvent.Status}");
    }

    private void OnUserConnected(HubMessage<string> message)
    {
        Console.WriteLine($"User connected: {message.Data}");
    }

    private void OnUserDisconnected(HubMessage<string> message)
    {
        Console.WriteLine($"User disconnected: {message.Data}");
    }

    public async ValueTask DisposeAsync()
    {
        if (_connection != null)
        {
            await _connection.DisposeAsync();
        }
    }
}

// Usage
var client = new MonitorClient("https://api.example.com/hubs/monitor", authToken);
await client.StartAsync();

Core Components

Hubs

ISynergy.Framework.AspNetCore.Monitoring.Hubs/
└── MonitorHub                    # SignalR hub with authentication

Services

ISynergy.Framework.AspNetCore.Monitoring.Services/
└── MonitorService<TEntity>       # Publish events to hub groups

Extensions

ISynergy.Framework.AspNetCore.Monitoring.Extensions/
├── ServiceCollectionExtensions   # DI configuration
├── HostApplicationBuilderExtensions  # Builder configuration
└── ApplicationBuilderExtensions  # Middleware configuration

Advanced Features

Publishing to Specific Users

The MonitorHub automatically creates groups based on user ID and account ID:

using ISynergy.Framework.Monitoring.Abstractions.Services;

public class NotificationService
{
    private readonly IMonitorService<NotificationEvent> _monitorService;

    public NotificationService(IMonitorService<NotificationEvent> monitorService)
    {
        _monitorService = monitorService;
    }

    public async Task SendToUserAsync(string userId, NotificationEvent notification)
    {
        // Send to specific user's group
        await _monitorService.PublishAsync(
            channel: userId,
            eventname: "Notification",
            data: notification);
    }

    public async Task SendToAccountAsync(Guid accountId, NotificationEvent notification)
    {
        // Send to all users in an account
        await _monitorService.PublishAsync(
            channel: accountId.ToString(),
            eventname: "Notification",
            data: notification);
    }

    public async Task BroadcastAsync(NotificationEvent notification)
    {
        // Send to all connected users
        await _monitorService.PublishAsync(
            channel: "all",
            eventname: "Notification",
            data: notification);
    }
}

Custom Event Types

Define strongly-typed events for different scenarios:

// Base event
public abstract class MonitorEvent
{
    public string EventId { get; set; } = Guid.NewGuid().ToString();
    public DateTime Timestamp { get; set; } = DateTime.UtcNow;
}

// Specific event types
public class OrderEvent : MonitorEvent
{
    public int OrderId { get; set; }
    public string Status { get; set; }
    public decimal Amount { get; set; }
}

public class InventoryEvent : MonitorEvent
{
    public int ProductId { get; set; }
    public int Quantity { get; set; }
    public string Action { get; set; } // Added, Removed, Updated
}

public class UserActivityEvent : MonitorEvent
{
    public string UserId { get; set; }
    public string Action { get; set; }
    public string Resource { get; set; }
}

// Register multiple monitor services
builder.Services.AddMonitorSignalR<OrderEvent>();
builder.Services.AddSingleton<IMonitorService<InventoryEvent>, MonitorService<InventoryEvent>>();
builder.Services.AddSingleton<IMonitorService<UserActivityEvent>, MonitorService<UserActivityEvent>>();

Connection State Management

Track connection states in your hub:

using ISynergy.Framework.AspNetCore.Monitoring.Hubs;
using Microsoft.AspNetCore.SignalR;

public class CustomMonitorHub : MonitorHub
{
    private readonly IConnectionTracker _connectionTracker;

    public CustomMonitorHub(
        ILogger<CustomMonitorHub> logger,
        IConnectionTracker connectionTracker)
        : base(logger)
    {
        _connectionTracker = connectionTracker;
    }

    public override async Task OnConnectedAsync()
    {
        await base.OnConnectedAsync();

        var accountId = Context.User.GetAccountId();
        var userId = Context.User.GetUserId();

        // Track connection
        await _connectionTracker.AddConnectionAsync(
            Context.ConnectionId,
            userId,
            accountId);

        // Send current online users to the connected client
        var onlineUsers = await _connectionTracker.GetOnlineUsersAsync(accountId);
        await Clients.Caller.SendAsync("OnlineUsers", onlineUsers);
    }

    public override async Task OnDisconnectedAsync(Exception exception)
    {
        var accountId = Context.User.GetAccountId();
        var userId = Context.User.GetUserId();

        // Remove connection
        await _connectionTracker.RemoveConnectionAsync(
            Context.ConnectionId,
            userId,
            accountId);

        await base.OnDisconnectedAsync(exception);
    }
}

Real-Time Dashboard

Build a real-time monitoring dashboard:

// Backend service
public class DashboardService
{
    private readonly IMonitorService<DashboardMetric> _monitorService;
    private readonly IMetricsCollector _metricsCollector;
    private Timer _timer;

    public DashboardService(
        IMonitorService<DashboardMetric> monitorService,
        IMetricsCollector metricsCollector)
    {
        _monitorService = monitorService;
        _metricsCollector = metricsCollector;
    }

    public void StartMonitoring(Guid accountId)
    {
        _timer = new Timer(async _ =>
        {
            var metrics = await _metricsCollector.GetCurrentMetricsAsync();

            await _monitorService.PublishAsync(
                channel: accountId.ToString(),
                eventname: "DashboardUpdate",
                data: new DashboardMetric
                {
                    ActiveUsers = metrics.ActiveUsers,
                    OrdersPerHour = metrics.OrdersPerHour,
                    Revenue = metrics.Revenue,
                    ServerLoad = metrics.ServerLoad
                });
        }, null, TimeSpan.Zero, TimeSpan.FromSeconds(5));
    }
}

public class DashboardMetric
{
    public int ActiveUsers { get; set; }
    public int OrdersPerHour { get; set; }
    public decimal Revenue { get; set; }
    public double ServerLoad { get; set; }
}

Frontend (React example):

import { useEffect, useState } from 'react';
import * as signalR from '@microsoft/signalr';

interface DashboardMetric {
    activeUsers: number;
    ordersPerHour: number;
    revenue: number;
    serverLoad: number;
}

export function Dashboard() {
    const [metrics, setMetrics] = useState<DashboardMetric | null>(null);
    const [connection, setConnection] = useState<signalR.HubConnection | null>(null);

    useEffect(() => {
        const newConnection = new signalR.HubConnectionBuilder()
            .withUrl('/hubs/monitor', {
                accessTokenFactory: () => getAuthToken()
            })
            .withAutomaticReconnect()
            .build();

        newConnection.on('DashboardUpdate', (metric: DashboardMetric) => {
            setMetrics(metric);
        });

        newConnection.start()
            .then(() => console.log('Connected to monitoring hub'))
            .catch(err => console.error('Connection error:', err));

        setConnection(newConnection);

        return () => {
            newConnection.stop();
        };
    }, []);

    return (
        <div className="dashboard">
            <MetricCard
                title="Active Users"
                value={metrics?.activeUsers ?? 0}
            />
            <MetricCard
                title="Orders/Hour"
                value={metrics?.ordersPerHour ?? 0}
            />
            <MetricCard
                title="Revenue"
                value={`$${metrics?.revenue?.toFixed(2) ?? '0.00'}`}
            />
            <MetricCard
                title="Server Load"
                value={`${metrics?.serverLoad?.toFixed(1) ?? '0.0'}%`}
            />
        </div>
    );
}

Usage Examples

Real-Time Collaboration

Implement collaborative editing features:

public class DocumentService
{
    private readonly IMonitorService<DocumentChangeEvent> _monitorService;

    public DocumentService(IMonitorService<DocumentChangeEvent> monitorService)
    {
        _monitorService = monitorService;
    }

    public async Task UpdateDocumentAsync(
        Guid documentId,
        string userId,
        DocumentChange change)
    {
        // Save the change
        await SaveChangeAsync(documentId, change);

        // Notify all users viewing this document
        await _monitorService.PublishAsync(
            channel: documentId.ToString(),
            eventname: "DocumentChanged",
            data: new DocumentChangeEvent
            {
                DocumentId = documentId,
                UserId = userId,
                Change = change,
                Timestamp = DateTime.UtcNow
            });
    }
}

// Client-side (TypeScript)
connection.on("DocumentChanged", (event) => {
    if (event.userId !== currentUserId) {
        // Apply changes from other users
        applyDocumentChange(event.change);
    }
});

Real-Time Notifications

Send instant notifications to users:

public class NotificationHub
{
    private readonly IMonitorService<Notification> _monitorService;

    public NotificationHub(IMonitorService<Notification> monitorService)
    {
        _monitorService = monitorService;
    }

    public async Task SendNotificationAsync(
        string userId,
        string title,
        string message,
        NotificationType type)
    {
        await _monitorService.PublishAsync(
            channel: userId,
            eventname: "Notification",
            data: new Notification
            {
                Title = title,
                Message = message,
                Type = type,
                Timestamp = DateTime.UtcNow
            });
    }
}

// Client-side
connection.on("Notification", (notification) => {
    showToast(notification.title, notification.message, notification.type);
});

Best Practices

Use groups to efficiently broadcast messages to multiple connected clients without iterating through all connections.

Always implement automatic reconnection on the client side to handle network interruptions gracefully.

Monitor SignalR connection count and message throughput to ensure your infrastructure can handle the load.

Hub Design

  • Keep hub methods focused and simple
  • Use groups for efficient message routing
  • Implement proper authentication and authorization
  • Log connection events for monitoring
  • Handle exceptions gracefully
  • Limit message size to avoid performance issues

Scalability

  • Use Azure SignalR Service for production scaling
  • Implement backplane (Redis) for multi-server deployments
  • Monitor hub performance and connection metrics
  • Set connection limits based on server capacity
  • Use distributed caching for connection state
  • Consider message batching for high-frequency updates

Security

  • Always require authentication for sensitive hubs
  • Validate user permissions before sending messages
  • Use groups to enforce tenant isolation
  • Encrypt sensitive data in messages
  • Implement rate limiting for hub methods
  • Audit hub access and message patterns

Performance

  • Minimize message payload size
  • Batch frequent updates when possible
  • Use compression for large messages
  • Implement client-side throttling
  • Cache frequently accessed data
  • Monitor and optimize hub method execution time

Testing

Example unit tests for monitoring services:

using ISynergy.Framework.Monitoring.Abstractions.Services;
using Microsoft.AspNetCore.SignalR;
using Moq;
using Xunit;

public class MonitorServiceTests
{
    [Fact]
    public async Task PublishAsync_PublishesToCorrectGroup()
    {
        // Arrange
        var mockHubContext = new Mock<IHubContext<MonitorHub>>();
        var mockClients = new Mock<IHubClients>();
        var mockGroupClients = new Mock<IClientProxy>();

        mockHubContext.Setup(h => h.Clients).Returns(mockClients.Object);
        mockClients.Setup(c => c.Group(It.IsAny<string>())).Returns(mockGroupClients.Object);

        var service = new MonitorService<OrderEvent>(mockHubContext.Object);

        var orderEvent = new OrderEvent
        {
            OrderId = 123,
            Status = "Created"
        };

        // Act
        await service.PublishAsync("account-123", "OrderCreated", orderEvent);

        // Assert
        mockClients.Verify(c => c.Group("account-123"), Times.Once);
        mockGroupClients.Verify(
            c => c.SendCoreAsync(
                "OrderCreated",
                It.Is<object[]>(o => o[0] == orderEvent),
                default),
            Times.Once);
    }
}

Dependencies

  • Microsoft.AspNetCore.SignalR - SignalR infrastructure
  • Microsoft.AspNetCore.SignalR.Core - Core SignalR abstractions
  • ISynergy.Framework.Core - Core framework utilities
  • ISynergy.Framework.Monitoring.Abstractions - Monitoring abstractions
  • ISynergy.Framework.MessageBus - Message bus models

Documentation

For more information about the I-Synergy Framework:

  • I-Synergy.Framework.Core - Core framework components
  • I-Synergy.Framework.AspNetCore - Base ASP.NET Core integration
  • I-Synergy.Framework.AspNetCore.Authentication - Authentication utilities
  • I-Synergy.Framework.MessageBus - Message bus infrastructure
  • I-Synergy.Framework.Monitoring.Abstractions - Monitoring contracts

Support

For issues, questions, or contributions, please visit the GitHub repository.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2025.11102.11228.52-preview 0 11/2/2025
2025.11102.10309.42-preview 0 11/2/2025
2025.11029.11433.38-preview 112 10/29/2025
2025.11029.10201.38-preview 131 10/29/2025
2025.11027.11947.55-preview 154 10/27/2025
2025.11022.12207.12-preview 149 10/22/2025
2025.11019.12053.37-preview 152 10/19/2025
2025.11016.11750.24-preview 152 10/16/2025
2025.11015.10219.44-preview 147 10/15/2025
2025.11014.10245.12-preview 150 10/14/2025
2025.11012.10130.11-preview 84 10/12/2025
2025.11010.10052.52-preview 142 10/9/2025
2025.11001.12118.13-preview 155 10/1/2025
2025.10925.10144.25-preview 171 9/25/2025
2025.10921.11353.29-preview 197 9/21/2025
2025.10913.11841.29-preview 143 9/13/2025
2025.10912.12351.59-preview 95 9/12/2025
2025.10912.10210.52-preview 166 9/12/2025
2025.10911.10131.43-preview 154 9/10/2025
2025.10910.12340.34-preview 166 9/10/2025
2025.10910.11327.15-preview 154 9/10/2025
2025.10910.11206.45-preview 159 9/10/2025
2025.10910.10230.58-preview 158 9/10/2025
2025.10908.12343.47-preview 164 9/8/2025
2025.10904.12337.35-preview 181 9/4/2025
2025.10904.12245.51-preview 171 9/4/2025
2025.10904.11425.5-preview 178 9/4/2025
2025.10904.10323.39-preview 173 9/4/2025
2025.10826.11425.3-preview 232 8/26/2025
2025.10825.12350.9-preview 183 8/25/2025
2025.10810.10248-preview 127 8/10/2025
2025.10809.10146.35-preview 160 8/9/2025
2025.10806.12031.49-preview 243 8/6/2025
2025.10806.11955.54-preview 237 8/6/2025
2025.10806.11433.24-preview 240 8/6/2025
2025.10709.10105.39-preview 165 7/8/2025
2025.10707.12320.3-preview 172 7/7/2025
2025.10706.11957.9-preview 168 7/6/2025
2025.10702.11752.47-preview 161 7/2/2025
2025.10702.11256.17-preview 170 7/2/2025
2025.10702.11119.10-preview 167 7/2/2025
2025.10702.10000.31-preview 156 7/1/2025
2025.10701.11524.1-preview 161 7/1/2025
2025.10701.11310.13-preview 175 7/1/2025
2025.10630.12022.58-preview 150 6/30/2025
2025.10612.12134.8-preview 299 6/12/2025
2025.10611.12313.53-preview 315 6/11/2025
2025.10603.10159.54-preview 157 6/3/2025
2025.10602.11908.9-preview 162 6/2/2025
2025.10601.10124.29-preview 110 5/31/2025
2025.10531.12235.29-preview 121 5/31/2025
2025.10530.10121.50-preview 172 5/29/2025
2025.10527.12202.4-preview 168 5/27/2025
2025.10526.12034.25-preview 157 5/26/2025
2025.10521.11828.30-preview 170 5/21/2025
2025.10520.11715.6-preview 167 5/20/2025
2025.10520.11515.16-preview 164 5/20/2025
2025.10518.12303.43-preview 181 5/18/2025
2025.10518.11257.36-preview 180 5/18/2025
2025.10517.12347.27-preview 126 5/17/2025
2025.10517.12003.6-preview 133 5/17/2025
2025.10516.11720.13-preview 211 5/16/2025
2025.10514.12334.2-preview 258 5/14/2025
2025.10514.10015.27-preview 252 5/13/2025
2025.10511.11032.32-preview 185 5/11/2025
2025.10413.11530 242 4/13/2025
2025.10413.11434.33-preview 211 4/13/2025
2025.10413.10205.50-preview 160 4/13/2025
2025.10412.11526.4-preview 129 4/12/2025
2025.10412.10141 143 4/12/2025
2025.10411.11811.23-preview 148 4/11/2025
2025.10411.11645.1-preview 154 4/11/2025
2025.10410.11458.35-preview 193 4/10/2025
2025.10405.10143.28-preview 114 4/5/2025
2025.10403.12208.1-preview 190 4/3/2025
2025.10403.11954.16-preview 186 4/3/2025
2025.10401.11908.24-preview 175 4/1/2025
2025.10401.11559.45-preview 184 4/1/2025
2025.10331.12215.59-preview 170 3/31/2025
2025.10331.12130.34-preview 177 3/31/2025
2025.10331.10056.40-preview 169 3/30/2025
2025.10328.10150.21-preview 156 3/28/2025
2025.10323.11359-preview 298 3/23/2025
2025.10320.11800 181 3/20/2025
2025.10320.11616.45-preview 177 3/20/2025
2025.10320.10000 178 3/19/2025
2025.10319.12311.26-preview 176 3/19/2025
2025.10319.12238.6-preview 175 3/19/2025
2025.10319.12057.59-preview 176 3/19/2025
2025.10318.10055 188 3/18/2025
2025.10317.11728.13-preview 176 3/17/2025
2025.10317.11201.3-preview 187 3/17/2025
2025.10315.11523.14-preview 107 3/15/2025
2025.10305.12342 258 3/5/2025
2025.10305.12321.9-preview 227 3/5/2025
2025.10301.12313 153 3/1/2025
2025.10301.12129.38-preview 119 3/1/2025
2025.10221.10043.29-preview 133 2/21/2025
2025.1051.1246 147 2/20/2025
2025.1051.44.54-preview 122 2/20/2025
2025.1044.1 138 2/13/2025
2025.1044.0.2-preview 125 2/13/2025
2025.1043.0.2-preview 139 2/12/2025
2025.1041.0.1-preview 138 2/10/2025
2025.1038.1 147 2/7/2025
2025.1038.0.1-preview 111 2/7/2025
2025.1035.1 149 2/4/2025
2025.1035.0.1-preview 117 2/4/2025
2025.1034.1 149 2/3/2025
2025.1034.0.1-preview 124 2/3/2025
2025.1033.0.5-preview 122 2/2/2025
2025.1033.0.3-preview 125 2/2/2025
2025.1033.0.2-preview 133 2/2/2025
2025.1033.0.1-preview 133 2/2/2025
2025.1025.1 151 1/25/2025
2025.1025.0.1-preview 127 1/25/2025
2025.1021.1 159 1/21/2025
2025.1021.0.1-preview 114 1/21/2025
2025.1020.1 133 1/20/2025
2025.1020.0.3-preview 119 1/20/2025
2025.1020.0.1-preview 127 1/20/2025
2025.1018.0.7-preview 126 1/18/2025
2025.1018.0.5-preview 120 1/18/2025
2025.1018.0.4-preview 122 1/18/2025
2025.1017.0.2-preview 101 1/17/2025
2025.1017.0.1-preview 124 1/17/2025
2025.1016.0.1-preview 117 1/16/2025
2025.1010.1 138 1/10/2025
2025.1010.0.1-preview 114 1/9/2025
2025.1009.0.3-preview 107 1/9/2025
2025.1007.1 145 1/7/2025
2025.1007.0.5-preview 109 1/7/2025
2025.1007.0.3-preview 118 1/7/2025
2025.1006.1 139 1/7/2025
2025.1005.1 158 1/5/2025
2025.1005.0.2-preview 118 1/5/2025
2025.1004.1 145 1/4/2025
2024.1366.1 150 12/31/2024
2024.1366.0.2-preview 156 12/31/2024
2024.1366.0.1-preview 138 12/31/2024
2024.1365.0.2-preview 110 12/30/2024
2024.1365.0.1-preview 125 12/30/2024
2024.1361.0.2-preview 125 12/26/2024
2024.1353.0.1-preview 127 12/18/2024
2024.1352.0.3-preview 120 12/17/2024
2024.1352.0.2-preview 110 12/17/2024
2024.1352.0.1-preview 126 12/17/2024
2024.1351.1 145 12/16/2024
2024.1351.0.3-preview 127 12/16/2024
2024.1350.1 160 12/15/2024
2024.1343.1 149 12/8/2024
2024.1339.1 146 12/4/2024
2024.1336.1 145 12/1/2024
2024.1332.1 147 11/27/2024
2024.1330.1 144 11/25/2024
2024.1328.1 147 11/23/2024
2024.1325.1 144 11/20/2024
2024.1323.1 144 11/18/2024
2024.1316.1 95 11/11/2024
2024.1307.1 99 11/2/2024
2024.1300.1 90 10/26/2024
2024.1294.1 120 10/20/2024
2024.1290.1 144 10/16/2024
2024.1283.1 155 10/8/2024
2024.1282.1 140 10/8/2024
2024.1278.1 155 10/4/2024
2024.1277.1 142 10/3/2024
2024.1275.2 148 10/1/2024
2024.1275.1 150 10/1/2024
2024.1274.1 145 9/30/2024
2024.1263.1 151 9/19/2024
2024.1261.1 193 9/17/2024
2024.1258.1 151 9/13/2024
2024.1257.1 154 9/13/2024
2024.1256.1 151 9/12/2024
2024.1254.1 156 9/10/2024
2024.1250.1 154 9/6/2024
2024.1249.1 171 9/5/2024
2024.1246.1 157 9/2/2024
2024.1245.1 149 9/1/2024
2024.1237.1 178 8/24/2024
2024.1235.0.1-preview 165 8/23/2024
2024.1230.1 151 8/18/2024
2024.1229.1 161 8/16/2024
2024.1228.1 157 8/15/2024
2024.1222.1 169 8/8/2024
2024.1221.1 142 8/7/2024
2024.1221.0.2-preview 150 8/8/2024
2024.1221.0.1-preview 144 8/8/2024
2024.1220.1 147 8/7/2024
2024.1219.0.2-preview 136 8/6/2024
2024.1219.0.1-preview 123 8/6/2024
2024.1217.0.2-preview 103 8/4/2024
2024.1217.0.1-preview 101 8/4/2024
2024.1216.0.2-preview 87 8/3/2024
2024.1216.0.1-preview 92 8/3/2024
2024.1208.0.1-preview 138 7/26/2024
2024.1207.0.7-preview 135 7/25/2024
2024.1207.0.5-preview 113 7/25/2024
2024.1166.1 165 6/14/2024
2024.1165.1 133 6/13/2024
2024.1164.1 139 6/12/2024
2024.1162.1 156 6/10/2024
2024.1158.1 162 6/6/2024
2024.1156.1 144 6/4/2024
2024.1152.1 161 5/31/2024
2024.1151.1 163 5/29/2024
2024.1150.2 155 5/29/2024
2024.1150.1 149 5/29/2024
2024.1149.1 154 5/28/2024
2024.1147.1 145 5/26/2024
2024.1146.2 142 5/25/2024
2024.1146.1 141 5/25/2024
2024.1145.1 144 5/24/2024
2024.1135.2 153 5/14/2024
2024.1135.1 132 5/14/2024
2024.1134.1 132 5/13/2024
2024.1130.1 132 5/9/2024
2024.1123.1 144 5/2/2024
2024.1121.1 172 4/30/2024
2024.1114.1 171 4/22/2024