// Note: this class should be used only via the simulation context // to ensure that concurrent simulations don't share data public RateLimiting( IRateLimitingConfig config, ILogger log, IInstance instance) { this.log = log; this.clusterSize = 1; this.instance = instance; // TODO: these initializations will be moved to Init when SimulationManager is // integrated. this.connections = new PerSecondCounter( config.ConnectionsPerSecond, "Device connections", this.log); this.registryOperations = new PerMinuteCounter( config.RegistryOperationsPerMinute, "Registry operations", this.log); this.twinReads = new PerSecondCounter( config.TwinReadsPerSecond, "Twin reads", this.log); this.twinWrites = new PerSecondCounter( config.TwinWritesPerSecond, "Twin writes", this.log); this.messaging = new PerSecondCounter( config.DeviceMessagesPerSecond, "Device msg/sec", this.log); }
// TODO: https://github.com/Azure/device-simulation-dotnet/issues/80 //private readonly PerDayCounter messagingDaily; public RateLimiting( IRateLimitingConfig config, ILogger log) { this.connections = new PerSecondCounter( config.ConnectionsPerSecond, "Device connections", log); this.registryOperations = new PerMinuteCounter( config.RegistryOperationsPerMinute, "Registry operations", log); this.twinReads = new PerSecondCounter( config.TwinReadsPerSecond, "Twin reads", log); this.twinWrites = new PerSecondCounter( config.TwinWritesPerSecond, "Twin writes", log); this.messaging = new PerSecondCounter( config.DeviceMessagesPerSecond, "Device msg/sec", log); //this.messagingDaily = new PerDayCounter( // config.DeviceMessagesPerDay, "Device msg/day", log); // The class should be a singleton, if this appears more than once // something is not setup correctly and the rating won't work. // TODO: enforce the single instance, compatibly with the use of // Parallel.For in the simulation runner. // https://github.com/Azure/device-simulation-dotnet/issues/79 log.Info("Rate limiting started. This message should appear only once in the logs.", () => { }); }
public SimulationRunner( IRateLimitingConfig ratingConfig, IRateLimiting rateLimiting, ISimulationConcurrencyConfig simulationConcurrencyConfig, ILogger logger, IDiagnosticsLogger diagnosticsLogger, IDeviceModels deviceModels, IDeviceModelsGeneration deviceModelsOverriding, IDevices devices, ISimulations simulations, IFactory factory) { this.connectionLoopSettings = new ConnectionLoopSettings(ratingConfig); this.propertiesLoopSettings = new PropertiesLoopSettings(ratingConfig); this.simulationConcurrencyConfig = simulationConcurrencyConfig; this.log = logger; this.diagnosticsLogger = diagnosticsLogger; this.deviceModels = deviceModels; this.deviceModelsOverriding = deviceModelsOverriding; this.devices = devices; this.simulations = simulations; this.factory = factory; this.startLock = new { }; this.running = false; this.starting = false; this.rateLimiting = rateLimiting; this.deviceStateActors = new ConcurrentDictionary <string, IDeviceStateActor>(); this.deviceConnectionActors = new ConcurrentDictionary <string, IDeviceConnectionActor>(); this.deviceTelemetryActors = new ConcurrentDictionary <string, IDeviceTelemetryActor>(); this.devicePropertiesActors = new ConcurrentDictionary <string, IDevicePropertiesActor>(); }
// Note: this class should be used only via the simulation context // to ensure that concurrent simulations don't share data public RateLimiting( IRateLimitingConfig config, ILogger log, IInstance instance) { this.log = log; this.clusterSize = 1; this.instance = instance; }
// Map API model to service model, keeping the original fields when needed public Simulation ToServiceModel( Simulation existingSimulation, IRateLimitingConfig defaultRateLimits, string id = "") { var now = DateTimeOffset.UtcNow; // ID can be empty, e.g. with POST requests this.Id = id; // Use the existing simulation fields if available, so that read-only values are not lost // e.g. the state of partitioning, device creation, etc. var result = new Simulation(); if (existingSimulation != null) { result = existingSimulation; } result.ETag = this.ETag; result.Id = this.Id; result.Name = this.Name; result.Description = this.Description; result.StartTime = DateHelper.ParseDateExpression(this.StartTime, now); result.EndTime = DateHelper.ParseDateExpression(this.EndTime, now); result.DeviceModels = this.DeviceModels?.Select(x => x.ToServiceModel()).ToList(); result.RateLimits = this.RateLimits.ToServiceModel(defaultRateLimits); result.ReplayFileId = this.ReplayFileId; result.ReplayFileRunIndefinitely = this.ReplayFileIndefinitely; // Overwrite the value only if the request included the field, i.e. don't // enable/disable the simulation if the user didn't explicitly ask to. if (this.Enabled.HasValue) { result.Enabled = this.Enabled.Value; } // Overwrite the value only if the request included the field, i.e. don't // delete all devices if the user didn't explicitly ask to. if (this.DeleteDevicesWhenSimulationEnds.HasValue) { result.DeleteDevicesWhenSimulationEnds = this.DeleteDevicesWhenSimulationEnds.Value; } foreach (var hub in this.IotHubs) { var connString = SimulationIotHub.ToServiceModel(hub); if (!result.IotHubConnectionStrings.Contains(connString)) { result.IotHubConnectionStrings.Add(connString); } } return(result); }
public static SimulationRateLimits FromServiceModel(IRateLimitingConfig simulationRateLimits) { return(new SimulationRateLimits { ConnectionsPerSecond = simulationRateLimits.ConnectionsPerSecond, RegistryOperationsPerMinute = simulationRateLimits.RegistryOperationsPerMinute, TwinReadsPerSecond = simulationRateLimits.TwinReadsPerSecond, TwinWritesPerSecond = simulationRateLimits.TwinWritesPerSecond, DeviceMessagesPerSecond = simulationRateLimits.DeviceMessagesPerSecond }); }
public IRateLimitingConfig ToServiceModel(IRateLimitingConfig defaultRateLimits) { var connectionsPerSecond = this.ConnectionsPerSecond > 0 ? this.ConnectionsPerSecond : defaultRateLimits.ConnectionsPerSecond; var registryOperationsPerMinute = this.RegistryOperationsPerMinute > 0 ? this.RegistryOperationsPerMinute : defaultRateLimits.RegistryOperationsPerMinute; var twinReadsPerSecond = this.TwinReadsPerSecond > 0 ? this.TwinReadsPerSecond : defaultRateLimits.TwinReadsPerSecond; var twinWritesPerSecond = this.TwinWritesPerSecond > 0 ? this.TwinWritesPerSecond : defaultRateLimits.TwinWritesPerSecond; var deviceMessagesPerSecond = this.DeviceMessagesPerSecond > 0 ? this.DeviceMessagesPerSecond : defaultRateLimits.DeviceMessagesPerSecond; return(new RateLimitingConfig { ConnectionsPerSecond = connectionsPerSecond, RegistryOperationsPerMinute = registryOperationsPerMinute, TwinReadsPerSecond = twinReadsPerSecond, TwinWritesPerSecond = twinWritesPerSecond, DeviceMessagesPerSecond = deviceMessagesPerSecond }); }
public SimulationsController( ISimulations simulationsService, IConnectionStringValidation connectionStringValidation, IIothubMetrics iothubMetrics, IRateLimitingConfig defaultRatingConfig, IPreprovisionedIotHub preprovisionedIotHub, ISimulationAgent simulationAgent, IFactory factory, ILogger logger) { this.simulationsService = simulationsService; this.connectionStringValidation = connectionStringValidation; this.iothubMetrics = iothubMetrics; this.defaultRatingConfig = defaultRatingConfig; this.simulationAgent = simulationAgent; this.factory = factory; this.log = logger; }
public void Init(IRateLimitingConfig config) { this.instance.InitOnce(); this.connections = new PerSecondCounter( config.ConnectionsPerSecond, "Device connections", this.log); this.registryOperations = new PerMinuteCounter( config.RegistryOperationsPerMinute, "Registry operations", this.log); this.twinReads = new PerSecondCounter( config.TwinReadsPerSecond, "Twin reads", this.log); this.twinWrites = new PerSecondCounter( config.TwinWritesPerSecond, "Twin writes", this.log); this.messaging = new PerSecondCounter( config.DeviceMessagesPerSecond, "Device msg/sec", this.log); this.instance.InitComplete(); }
public PropertiesLoopSettings(IRateLimitingConfig ratingConfig) { this.ratingConfig = ratingConfig; this.NewLoop(); }
public ConnectionLoopSettings(IRateLimitingConfig ratingConfig) { this.ratingConfig = ratingConfig; this.NewLoop(); }