internal SessionManager(ISessionFactory sessionFactory, ITypeLoader typeLoader, IParameterStore parameterStore, INetworkStatusProvider defaultNetworkProvider, ILoggerFactory loggerFactory) { StackTraceMinimizerExceptionExtensions.DoCompressStackTrace = true; _typeLoader = typeLoader; _parameterStore = parameterStore; _sessionFactory = sessionFactory; _loggerFactory = loggerFactory; _defaultNetworkProvider = defaultNetworkProvider; _logger = _loggerFactory.CreateLogger <SessionManager>(); _configIdMap = new PersistentConfigFileIdMap(_parameterStore); Directory.CreateDirectory(ExtraConfigDirPath); _logger.LogInformation($"Default configuration file is '{DefaultConfigPath}'"); _logger.LogInformation($"Extra configuration directory is '{ExtraConfigDirPath}'"); _defaultConfigWatcher = new FileSystemWatcher(Path.GetDirectoryName(DefaultConfigPath)) { Filter = Path.GetFileName(DefaultConfigPath) }; _extraconfigWatcher = new FileSystemWatcher(ExtraConfigDirPath) { Filter = "*.json" }; HookFileWatcherEvents(_defaultConfigWatcher); HookFileWatcherEvents(_extraconfigWatcher); instance = this; }
/// <summary> /// Determine the ID of a Session based on the config file path. /// </summary> /// <param name="configPath">Path of the config file</param> /// <returns>ID of the <see cref="ISession"/></returns> private int GetIdOfConfigFile(string configPath, PersistentConfigFileIdMap configFileIdMap) { if (configFileIdMap.TryGetValue(configPath, out int id)) { return(id); } return(configFileIdMap.MaxUsedId + 1); }
/// <summary> /// Check the config file, if it has changed, start a new session and stop the old one. /// </summary> /// <returns>True iff a new session has been successfully started.</returns> private void PollConfig(string configPath, bool isDefault, PersistentConfigFileIdMap configIdMap) { // Don't process any files outside of the expected directories. // This allows us to support validated sessions by placing them in different directories. if (!configPath.StartsWith(DefaultConfigPath) && !configPath.StartsWith(ExtraConfigDirPath)) { return; } try { var lastWriteTime = File.GetLastWriteTime(configPath); if (ConfigPathToSessionMap.TryGetValue(configPath, out var existingSession)) { // the session is running if (lastWriteTime <= existingSession.StartTime) { // the config file hasn't changed, nothing to do here return; } _logger.LogInformation($"Config file '{configPath}' has changed."); // stop the existing session TerminateSession(existingSession, false); ConfigPathToSessionMap.TryRemove(configPath, out existingSession); } else { _logger.LogInformation($"Config file '{configPath}' is added."); } // start new session var newSession = LaunchSession(configPath, isDefault, configIdMap); ConfigPathToSessionMap[configPath] = newSession; PublishCounters(string.Empty, MetricsConstants.CATEGORY_PROGRAM, CounterTypeEnum.CurrentValue, new Dictionary <string, MetricValue>() { { MetricsConstants.CONFIGS_LOADED, new MetricValue(1) }, { MetricsConstants.CONFIGS_FAILED_TO_LOAD, new MetricValue(0) }, }); } catch (SessionLaunchedException sessionLaunchEx) { _logger.LogError(0, sessionLaunchEx.InnerException, $"Error lauching session '{sessionLaunchEx.ConfigPath}'"); PublishCounters(string.Empty, MetricsConstants.CATEGORY_PROGRAM, CounterTypeEnum.CurrentValue, new Dictionary <string, MetricValue>() { { MetricsConstants.CONFIGS_LOADED, new MetricValue(0) }, { MetricsConstants.CONFIGS_FAILED_TO_LOAD, new MetricValue(1) }, }); return; } catch (Exception ex) { _logger.LogError(0, ex, $"Error while monitoring config file '{configPath}'"); return; } }
private ISession LaunchSession(string configPath, bool isDefault, PersistentConfigFileIdMap configFileIdMap) { bool isValidated = !configPath.StartsWith(DefaultConfigPath) && !configPath.StartsWith(ExtraConfigDirPath); try { Guard.ArgumentNotNullOrEmpty(configPath, nameof(configPath)); var startTime = File.GetLastWriteTime(configPath); if (isDefault) { Debug.Assert(configPath == DefaultConfigPath, $"Default config path should be {DefaultConfigPath}, but {configPath} is initialized"); } var id = isDefault ? DefaultSessionId : GetIdOfConfigFile(configPath, configFileIdMap); var config = new ConfigurationBuilder() .AddJsonFile(configPath, optional: false, reloadOnChange: false) .Build(); if (string.IsNullOrWhiteSpace(config[ConfigConstants.CONFIG_DESCRIPTIVE_NAME])) { config[ConfigConstants.CONFIG_DESCRIPTIVE_NAME] = isDefault ? "default" : Path.GetFileNameWithoutExtension(configPath); } // If the configuration has it's own credentials, use them. // Otherwise, use the creds from the default config file. // If this is the default config, set the private field so subsequent configs can use it. var credSection = config.GetSection("Credentials"); var configHasCredentials = credSection.GetChildren().Any(); if (configHasCredentials) { _logger.LogDebug("Configuration {0} has credentials, these will be used for sources.", id); if (isDefault) { _defaultCredentialConfig = credSection; } } else { _logger.LogDebug("Configuration {0} has no credentials, using default credential section for sources.", id); credSection = _defaultCredentialConfig; } var session = _sessionFactory.Create(id, config, startTime, _typeLoader, _parameterStore, _loggerFactory, _defaultNetworkProvider, credSection, isValidated); // start the session _logger.LogDebug("Starting session {0}", id); session.Start(); if (!isDefault) { configFileIdMap[configPath] = id; } return(session); } catch (Exception ex) { throw new SessionLaunchedException(configPath, ex); } }