Beispiel #1
0
        static async Task RunAsync(Configuration config)
        {
            using var timer    = SyncHistogram.NewTimer();
            using var activity = Tracing.Trace(nameof(RunAsync));

            var fileHandler      = new IOWrapper();
            var db               = new DbClient(config, fileHandler);
            var pelotonApiClient = new Peloton.ApiClient(config.Peloton.Email, config.Peloton.Password, config.Observability.Prometheus.Enabled);
            var peloton          = new PelotonService(config, pelotonApiClient, db, fileHandler);

            await peloton.DownloadLatestWorkoutDataAsync();

            var fitConverter = new FitConverter(config, db, fileHandler);

            fitConverter.Convert();

            var tcxConverter = new TcxConverter(config, db, fileHandler);

            tcxConverter.Convert();

            var garminUploader = new GarminUploader(config, db);

            try
            {
                await garminUploader.UploadToGarminAsync();

                Health.Set(HealthStatus.Healthy);

                fileHandler.Cleanup(config.App.DownloadDirectory);
                fileHandler.Cleanup(config.App.UploadDirectory);
                foreach (var file in Directory.GetFiles(config.App.WorkingDirectory))
                {
                    File.Delete(file);
                }
            } catch (GarminUploadException e)
            {
                Log.Error(e, "Garmin upload returned an error code. Failed to upload workouts.");
                Log.Warning("GUpload failed to upload files. You can find the converted files at {@Path} \n You can manually upload your files to Garmin Connect, or wait for P2G to try again on the next sync job.", config.App.OutputDirectory);
                Health.Set(HealthStatus.UnHealthy);
            }
        }
Beispiel #2
0
        protected override Task ExecuteAsync(CancellationToken cancelToken)
        {
            _logger.Verbose("Begin.");

            Health.Set(HealthStatus.Healthy);

            try
            {
                PelotonService.ValidateConfig(_settings.Peloton);
                GarminUploader.ValidateConfig(_settings);
                Metrics.ValidateConfig(_config.Observability);
                Tracing.ValidateConfig(_config.Observability);
            }
            catch (Exception ex)
            {
                _logger.Fatal(ex, "Exception during config validation.");
                Health.Set(HealthStatus.Dead);
                Environment.Exit(-1);
            }

            return(RunAsync(cancelToken));
        }
Beispiel #3
0
        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();
            }
        }