2using System.Collections.Generic;
5using System.Threading.Tasks;
7using Microsoft.Extensions.Hosting;
8using Microsoft.Extensions.Logging;
9using Microsoft.Extensions.Options;
52 readonly ILogger<VersionReportingService>
logger;
78 IOptions<TelemetryConfiguration> telemetryConfigurationOptions,
79 ILogger<VersionReportingService>
logger)
85 telemetryConfiguration = telemetryConfigurationOptions?.Value ??
throw new ArgumentNullException(nameof(telemetryConfigurationOptions));
86 this.logger =
logger ??
throw new ArgumentNullException(nameof(
logger));
90 public override Task
StopAsync(CancellationToken cancellationToken)
93 return base.StopAsync(cancellationToken);
97 protected override async Task
ExecuteAsync(CancellationToken stoppingToken)
101 logger.LogDebug(
"Version telemetry disabled");
107 logger.LogError(
"Version reporting repository is misconfigured. Telemetry cannot be sent!");
112 if (attribute ==
null)
114 logger.LogDebug(
"TGS build configuration does not allow for version telemetry");
118 logger.LogDebug(
"Starting...");
125 telemetryIdDirectory,
131 telemetryId = Guid.NewGuid();
133 await
ioManager.
WriteAllBytes(telemetryIdFile, Encoding.UTF8.GetBytes(telemetryId.ToString()), stoppingToken);
134 logger.LogInformation(
"Generated telemetry ID {telemetryId} and wrote to {file}", telemetryId, telemetryIdFile);
143 guidStr = Encoding.UTF8.GetString(contents);
147 logger.LogError(ex,
"Cannot decode telemetry ID from installation file ({path}). Telemetry will not be sent!", telemetryIdFile);
151 if (!Guid.TryParse(guidStr, out telemetryId))
153 logger.LogError(
"Cannot parse telemetry ID from installation file ({path}). Telemetry will not be sent!", telemetryIdFile);
160 while (!stoppingToken.IsCancellationRequested)
164 attribute.SerializedKey,
171 logger.LogDebug(
"Next version report in {hours} hours", nextDelayHours);
175 catch (OperationCanceledException ex)
177 logger.LogTrace(ex,
"Inner cancellation");
182 logger.LogDebug(
"Sending shutdown telemetry");
185 attribute.SerializedKey,
190 catch (OperationCanceledException ex)
192 logger.LogTrace(ex,
"Exiting due to outer cancellation...");
196 logger.LogError(ex,
"Crashed!");
209 async ValueTask<bool>
TryReportVersion(Guid telemetryId,
string serializedPem,
long repositoryId,
bool shutdown, CancellationToken cancellationToken)
211 logger.LogDebug(
"Sending version telemetry...");
214 if (String.IsNullOrWhiteSpace(serverFriendlyName))
215 serverFriendlyName =
null;
218 "Repository ID: {repoId}, Server friendly name: {friendlyName}",
220 serverFriendlyName ==
null
222 : $
"\"{serverFriendlyName}\"");
230 if (gitHubClient ==
null)
232 logger.LogWarning(
"Could not create GitHub client to connect to repository ID {repoId}!", repositoryId);
237 var repository = await gitHubClient.Repository.Get(repositoryId);
239 logger.LogTrace(
"Repository ID {id} resolved to {owner}/{name}", repositoryId, repository.Owner.Name, repository.Name);
241 var inputs =
new Dictionary<string, object>
243 {
"telemetry_id", telemetryId.ToString() },
245 {
"shutdown", shutdown ?
"true" :
"false" },
248 if (serverFriendlyName !=
null)
249 inputs.Add(
"server_friendly_name", serverFriendlyName);
251 await gitHubClient.Actions.Workflows.CreateDispatch(
252 repository.Owner.Login,
254 ".github/workflows/tgs_deployments_telemetry.yml",
255 new CreateWorkflowDispatch(
"main")
260 logger.LogTrace(
"Telemetry sent successfully");
266 logger.LogWarning(ex,
"Failed to report version!");
Configuration options for telemetry.
string? ServerFriendlyName
The friendly name used on GitHub deployments for version reporting. If null only the server global::S...
long? VersionReportingRepositoryId
The GitHub repository ID used for version reporting.
bool DisableVersionReporting
If version reporting telemetry is disabled.
Handles TGS version reporting, if enabled.
readonly IAssemblyInformationProvider assemblyInformationProvider
The IAssemblyInformationProvider for the VersionReportingService.
async ValueTask< bool > TryReportVersion(Guid telemetryId, string serializedPem, long repositoryId, bool shutdown, CancellationToken cancellationToken)
Make an attempt to report the current IAssemblyInformationProvider.Version to the configured GitHub r...
readonly IIOManager ioManager
The IIOManager for the VersionReportingService.
readonly IAsyncDelayer asyncDelayer
The IAsyncDelayer for the VersionReportingService.
VersionReportingService(IGitHubClientFactory gitHubClientFactory, IIOManager ioManager, IAsyncDelayer asyncDelayer, IAssemblyInformationProvider assemblyInformationProvider, IOptions< TelemetryConfiguration > telemetryConfigurationOptions, ILogger< VersionReportingService > logger)
Initializes a new instance of the VersionReportingService class.
override async Task ExecuteAsync(CancellationToken stoppingToken)
readonly ILogger< VersionReportingService > logger
The ILogger for the VersionReportingService.
CancellationToken shutdownCancellationToken
The CancellationToken passed to StopAsync(CancellationToken).
override Task StopAsync(CancellationToken cancellationToken)
readonly IGitHubClientFactory gitHubClientFactory
The IGitHubClientFactory for the VersionReportingService.
readonly TelemetryConfiguration telemetryConfiguration
The TelemetryConfiguration for the VersionReportingService.
Attribute for bundling the GitHub App serialized private key used for version telemetry.
static ? TelemetryAppSerializedKeyAttribute Instance
Return the Assembly's instance of the TelemetryAppSerializedKeyAttribute.
Identifies a repository either by its RepositoryId or Owner and Name.
Interface for using filesystems.
string ResolvePath()
Retrieve the full path of the current working directory.
ValueTask< byte[]> ReadAllBytes(string path, CancellationToken cancellationToken)
Returns all the contents of a file at path as a byte array.
string ConcatPath(params string[] paths)
Combines an array of strings into a path.
Task CreateDirectory(string path, CancellationToken cancellationToken)
Create a directory at path .
ValueTask WriteAllBytes(string path, byte[] contents, CancellationToken cancellationToken)
Writes some contents to a file at path overwriting previous content.
Task< bool > FileExists(string path, CancellationToken cancellationToken)
Check that the file at path exists.
For creating IGitHubClients.
ValueTask< IGitHubClient?> CreateClientForRepository(string accessString, RepositoryIdentifier repositoryIdentifier, CancellationToken cancellationToken)
Creates a GitHub client that will only be used for a given repositoryIdentifier .
For waiting asynchronously.
ValueTask Delay(TimeSpan timeSpan, CancellationToken cancellationToken)
Create a Task that completes after a given timeSpan .