diff --git a/README.md b/README.md index 62bb7cc..373bf8d 100644 --- a/README.md +++ b/README.md @@ -167,19 +167,21 @@ MVC-контроллеры из плагинов тоже подключаютс ### Ключевые переменные приложения -| Переменная | Обязательность | Значение по умолчанию | Где используется | Назначение | -| ------------------------- | --------------------------------------- | ------------------------------------------ | --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `MODEUS_URL` | Нет | `https://sfedu.modeus.org/` | код | Базовый URL`Modeus` | -| `TOKEN` | Условно обязательна | нет | код | Готовый JWT для`Modeus`; если не задан, приложение попытается получить токен через `AUTH_URL` | -| `AUTH_URL` | Условно обязательна | `http://msauth:8080/auth/ms` | код | URL сервиса, который возвращает новый JWT | -| `AUTH_API_KEY` | Нет | пусто | код | API key для вызова`AUTH_URL`, передаётся как `X-API-Key` | -| `API_KEY` | Условно обязательна | нет | код | Ключ для маршрутов, защищённых схемой`ApiKey` | -| `UPDATE_JWT_CRON` | Нет | `0 0 4 ? * *` | код | Cron для фонового обновления JWT | -| `UPDATE_EMPLOYEES_CRON` | Нет | `0 0 6 ? * *` | код | Cron для фонового обновления индекса сотрудников | -| `PERMIT_LIMIT` | Нет | `40` | код | Лимит запросов в окне rate limiter | -| `TIME_LIMIT` | Нет | `10` | код | Длина окна rate limiter в секундах | -| `TZ` | Нет | `Europe/Moscow` | код | Таймзона для запросов к`Modeus` и генерации `ICS` | -| `Sentry:Dsn` | Нет | пустая строка | код | DSN для Sentry | +| Переменная | Обязательность | Значение по умолчанию | Где используется | Назначение | +| ----------------------------- | ------------------- | ---------------------------- | ---------------- | --------------------------------------------------------------------------------------------- | +| `MODEUS_URL` | Нет | `https://sfedu.modeus.org/` | код | Базовый URL`Modeus` | +| `TOKEN` | Условно обязательна | нет | код | Готовый JWT для`Modeus`; если не задан, приложение попытается получить токен через `AUTH_URL` | +| `AUTH_URL` | Условно обязательна | `http://msauth:8080/auth/ms` | код | URL сервиса, который возвращает новый JWT | +| `AUTH_API_KEY` | Нет | пусто | код | API key для вызова`AUTH_URL`, передаётся как `X-API-Key` | +| `API_KEY` | Условно обязательна | нет | код | Ключ для маршрутов, защищённых схемой`ApiKey` | +| `UPDATE_JWT_CRON` | Нет | `0 0 4 ? * *` | код | Cron для фонового обновления JWT | +| `UPDATE_EMPLOYEES_CRON` | Нет | `0 0 6 ? * *` | код | Cron для фонового обновления индекса сотрудников | +| `PERMIT_LIMIT` | Нет | `40` | код | Лимит запросов в окне rate limiter | +| `TIME_LIMIT` | Нет | `10` | код | Длина окна rate limiter в секундах | +| `TZ` | Нет | `Europe/Moscow` | код | Таймзона для запросов к`Modeus` и генерации `ICS` | +| `Sentry:Dsn` | Нет | пустая строка | код | DSN для Sentry | +| `SENTRY_TRACES_SAMPLE_RATE` | Нет | `1` | код | Доля трассировок Sentry от `0` до `1` | +| `SENTRY_PROFILES_SAMPLE_RATE` | Нет | `1` | код | Доля профилируемых трассировок от `0` до `1`; при `0` profiling-интеграция не запускается | ### Переменные для Microsoft / Azure AD @@ -200,9 +202,9 @@ MVC-контроллеры из плагинов тоже подключаютс ### Переменные из docker-compose -| Переменная | Обязательность | Значение по умолчанию | Назначение | -| --------------------------------------- | ------------------------------ | ------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- | -| `ASPNETCORE_FORWARDEDHEADERS_ENABLED` | Нет | нет | В compose выставляется в`true`, чтобы приложение корректнее работало за reverse proxy | +| Переменная | Обязательность | Значение по умолчанию | Назначение | +| ------------------------------------- | -------------- | --------------------- | ------------------------------------------------------------------------------------- | +| `ASPNETCORE_FORWARDEDHEADERS_ENABLED` | Нет | нет | В compose выставляется в`true`, чтобы приложение корректнее работало за reverse proxy | ### Что значит "условно обязательна" @@ -236,6 +238,8 @@ TG_CHAT_ID= TG_TOKEN= SENTRY_DSN= +SENTRY_TRACES_SAMPLE_RATE=0.1 +SENTRY_PROFILES_SAMPLE_RATE=0 AzureAd:Instance=https://login.microsoftonline.com/ AzureAd:TenantId=sfedu.ru diff --git a/SfeduSchedule/AppConsts.cs b/SfeduSchedule/AppConsts.cs index e1eca3a..5f5ebb3 100644 --- a/SfeduSchedule/AppConsts.cs +++ b/SfeduSchedule/AppConsts.cs @@ -13,7 +13,11 @@ public static class AppConsts // RateLimiter public const string PermitLimitEnv = "PERMIT_LIMIT"; - public const string TimeLimitEnv = "TIME_LIMIT"; + public const string TimeLimitEnv = "TIME_LIMIT"; + + // Sentry + public const string SentryTracesSampleRateEnv = "SENTRY_TRACES_SAMPLE_RATE"; + public const string SentryProfilesSampleRateEnv = "SENTRY_PROFILES_SAMPLE_RATE"; // MS Auth public const string AuthUrlEnv = "AUTH_URL"; @@ -23,4 +27,4 @@ public static class AppConsts public const string JwtFileName = "jwt.txt"; public const string EmployeesFileName = "employees.json"; public const string DataFolderName = "data"; -} \ No newline at end of file +} diff --git a/SfeduSchedule/Program.cs b/SfeduSchedule/Program.cs index 0c2b21e..c0062f1 100644 --- a/SfeduSchedule/Program.cs +++ b/SfeduSchedule/Program.cs @@ -1,6 +1,7 @@ using System.Net; using System.Reflection; using System.Threading.RateLimiting; +using System.Globalization; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.OpenIdConnect; using Microsoft.AspNetCore.DataProtection; @@ -33,6 +34,8 @@ configuration["TZ"] ??= "Europe/Moscow"; var permitLimit = int.TryParse(configuration[AppConsts.PermitLimitEnv], out var parsedPermitLimit) ? parsedPermitLimit : 40; var timeLimit = int.TryParse(configuration[AppConsts.TimeLimitEnv], out var parsedTimeLimit) ? parsedTimeLimit : 10; +var sentryTracesSampleRate = GetSampleRate(configuration, AppConsts.SentryTracesSampleRateEnv, 1.0); +var sentryProfilesSampleRate = GetSampleRate(configuration, AppConsts.SentryProfilesSampleRateEnv, 1.0); #endregion @@ -64,9 +67,11 @@ builder.WebHost.UseSentry(options => { options.Dsn = configuration["Sentry:Dsn"] ?? ""; options.EnableLogs = true; - options.TracesSampleRate = 1.0; - options.ProfilesSampleRate = 1.0; - options.AddProfilingIntegration(); + options.TracesSampleRate = sentryTracesSampleRate; + options.ProfilesSampleRate = sentryProfilesSampleRate; + + if (sentryProfilesSampleRate > 0) + options.AddProfilingIntegration(); }); // Включаем MVC контроллеры @@ -334,4 +339,18 @@ app.MapMetrics(); // Маршруты Minimal API из плагинов foreach (var p in loadedPlugins) p.Instance.MapEndpoints(app); -app.Run(); \ No newline at end of file +app.Run(); + +static double GetSampleRate(IConfiguration configuration, string key, double defaultValue) +{ + var rawValue = configuration[key]; + if (string.IsNullOrWhiteSpace(rawValue)) + return defaultValue; + + if (double.TryParse(rawValue, NumberStyles.Float, CultureInfo.InvariantCulture, out var sampleRate) && + sampleRate is >= 0 and <= 1) + return sampleRate; + + throw new InvalidOperationException( + $"Переменная окружения {key} должна быть числом от 0 до 1 (получено: '{rawValue}')."); +} diff --git a/docker-compose-prod.yml b/docker-compose-prod.yml index fb4e2d9..528ae81 100644 --- a/docker-compose-prod.yml +++ b/docker-compose-prod.yml @@ -14,12 +14,14 @@ services: - API_KEY=${API_KEY} # - TOKEN=${TOKEN} - AUTH_URL=${AUTH_URL} - - AUTH_API_KEY=${AUTH_API_KEY} - - Sentry:Dsn=${SENTRY_DSN:-} + - AUTH_API_KEY=${AUTH_API_KEY} + - Sentry:Dsn=${SENTRY_DSN:-} + - SENTRY_TRACES_SAMPLE_RATE=${SENTRY_TRACES_SAMPLE_RATE:-1} + - SENTRY_PROFILES_SAMPLE_RATE=${SENTRY_PROFILES_SAMPLE_RATE:-1} volumes: - data:/app/data restart: always image: git.zetcraft.ru/serega404/sfeduschedule:main volumes: - data: \ No newline at end of file + data: diff --git a/docker-compose-test.yml b/docker-compose-test.yml index 0c94d50..daa4f0c 100644 --- a/docker-compose-test.yml +++ b/docker-compose-test.yml @@ -13,11 +13,13 @@ services: - AzureAd:CallbackPath=/signin-oidc - API_KEY=${API_KEY} # - TOKEN=${TOKEN} - - AUTH_URL=${AUTH_URL} - - AUTH_API_KEY=${AUTH_API_KEY} + - AUTH_URL=${AUTH_URL} + - AUTH_API_KEY=${AUTH_API_KEY} + - SENTRY_TRACES_SAMPLE_RATE=${SENTRY_TRACES_SAMPLE_RATE:-1} + - SENTRY_PROFILES_SAMPLE_RATE=${SENTRY_PROFILES_SAMPLE_RATE:-1} volumes: - ./data:/app/data restart: unless-stopped build: context: ./SfeduSchedule - dockerfile: Dockerfile \ No newline at end of file + dockerfile: Dockerfile