Exemple #1
0
        public Startup(AppConfiguration configuration, Settings settings, ISyncService syncService)
        {
            _config      = configuration;
            _settings    = settings;
            _syncService = syncService;

            FlurlConfiguration.Configure(_config.Observability);

            var runtimeVersion = Environment.Version.ToString();
            var os             = Environment.OSVersion.Platform.ToString();
            var osVersion      = Environment.OSVersion.VersionString;
            var version        = Constants.AppVersion;

            BuildInfo.WithLabels(version, os, osVersion, runtimeVersion).Set(1);
            _logger.Debug("App Version: {@Version}", version);
            _logger.Debug("Operating System: {@Os}", osVersion);
            _logger.Debug("DotNet Runtime: {@DotnetRuntime}", runtimeVersion);
        }
        static void Main(string[] args)
        {
            Console.WriteLine("Peloton To Garmin");
            var config = new Configuration();

            Health.Set(HealthStatus.Healthy);

            var runtimeVersion = Environment.Version.ToString();
            var os             = Environment.OSVersion.Platform.ToString();
            var osVersion      = Environment.OSVersion.VersionString;
            var assembly       = Assembly.GetExecutingAssembly();
            var versionInfo    = FileVersionInfo.GetVersionInfo(assembly.Location);
            var version        = versionInfo.ProductVersion;

            try
            {
                IConfiguration configProviders = new ConfigurationBuilder()
                                                 .AddJsonFile(Path.Join(Environment.CurrentDirectory, "configuration.local.json"), optional: true, reloadOnChange: true)
                                                 .AddEnvironmentVariables(prefix: "P2G_")
                                                 .AddCommandLine(args)
                                                 .Build();

                configProviders.GetSection(nameof(App)).Bind(config.App);
                configProviders.GetSection(nameof(Format)).Bind(config.Format);
                configProviders.GetSection(nameof(Peloton)).Bind(config.Peloton);
                configProviders.GetSection(nameof(Garmin)).Bind(config.Garmin);
                configProviders.GetSection(nameof(Observability)).Bind(config.Observability);
                configProviders.GetSection(nameof(Developer)).Bind(config.Developer);

                // https://github.com/serilog/serilog-settings-configuration
                Log.Logger = new LoggerConfiguration()
                             .ReadFrom.Configuration(configProviders, sectionName: $"{nameof(Observability)}:Serilog")
                             .Enrich.WithSpan()
                             .CreateLogger();

                ChangeToken.OnChange(() => configProviders.GetReloadToken(), () =>
                {
                    Log.Information("Config change detected, reloading config values.");
                    configProviders.GetSection(nameof(App)).Bind(config.App);
                    configProviders.GetSection(nameof(Format)).Bind(config.Format);
                    configProviders.GetSection(nameof(Peloton)).Bind(config.Peloton);
                    configProviders.GetSection(nameof(Garmin)).Bind(config.Garmin);
                    configProviders.GetSection(nameof(Developer)).Bind(config.Developer);

                    GarminUploader.ValidateConfig(config);

                    Log.Information("Config reloaded. Changes will take effect at the end of the current sleeping cycle.");
                });

                Log.Debug("P2G Version: {@Version}", version);
                Log.Debug("Operating System: {@Os}", osVersion);
                Log.Debug("DotNet Runtime: {@DotnetRuntime}", runtimeVersion);

                PelotonService.ValidateConfig(config.Peloton);
                GarminUploader.ValidateConfig(config);
                Common.Metrics.ValidateConfig(config.Observability);
                Tracing.ValidateConfig(config.Observability);

                FlurlConfiguration.Configure(config);
            }
            catch (Exception e)
            {
                Log.Fatal(e, "Exception during config setup.");
                Health.Set(HealthStatus.Dead);
                throw;
            }

            IDisposable dotNetRuntimeMetrics = null;

            try
            {
                using var metrics       = Common.Metrics.EnableMetricsServer(config.Observability.Prometheus);
                using var tracing       = Tracing.EnableTracing(config.Observability.Jaeger);
                using var tracingSource = new ActivitySource("ROOT");

                if (config.Observability.Prometheus.Enabled)
                {
                    dotNetRuntimeMetrics = DotNetRuntimeStatsBuilder
                                           .Customize()
                                           .WithContentionStats()
                                           .WithJitStats()
                                           .WithThreadPoolStats()
                                           .WithGcStats()
                                           .WithExceptionStats()
                                           .StartCollecting();
                }

                BuildInfo.WithLabels(version, os, osVersion, runtimeVersion).Set(1);

                if (config.Peloton.NumWorkoutsToDownload <= 0)
                {
                    Console.Write("How many workouts to grab? ");
                    int num = Convert.ToInt32(Console.ReadLine());
                    config.Peloton.NumWorkoutsToDownload = num;
                }

                if (config.App.EnablePolling)
                {
                    while (config.App.EnablePolling)
                    {
                        RunAsync(config).GetAwaiter().GetResult();
                        Log.Information("Sleeping for {@Seconds} seconds...", config.App.PollingIntervalSeconds);

                        var now         = DateTime.UtcNow;
                        var nextRunTime = now.AddSeconds(config.App.PollingIntervalSeconds);
                        NextSyncTime.Set(new DateTimeOffset(nextRunTime).ToUnixTimeSeconds());
                        Thread.Sleep(config.App.PollingIntervalSeconds * 1000);
                    }
                }
                else
                {
                    RunAsync(config).GetAwaiter().GetResult();
                }
            }
            catch (Exception e)
            {
                Log.Fatal(e, "Uncaught Exception.");
                Health.Set(HealthStatus.Dead);
            }
            finally
            {
                Log.CloseAndFlush();
                Console.ReadLine();
                dotNetRuntimeMetrics?.Dispose();
            }
        }