Skip to content

Commit

Permalink
Keep some of the previous API surface area to minimize breaks. Add do…
Browse files Browse the repository at this point in the history
…cumentation comments to clarify intended usage of members.
  • Loading branch information
baronfel committed Mar 1, 2025
1 parent aa37566 commit 649d0fc
Showing 3 changed files with 47 additions and 11 deletions.
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@
using Microsoft.Extensions.Logging;
using Microsoft.Sbom.Api;
using Microsoft.Sbom.Api.Config;
using Microsoft.Sbom.Api.Config.Extensions;
using Microsoft.Sbom.Api.Converters;
using Microsoft.Sbom.Api.Convertors;
using Microsoft.Sbom.Api.Entities.Output;
@@ -45,11 +46,38 @@ namespace Microsoft.Sbom.Extensions.DependencyInjection;

public static class ServiceCollectionExtensions
{
public static IServiceCollection AddSbomTool(this IServiceCollection services)
/// <summary>
/// Initializes the services required to use the SBOM Tool using a default <see cref="InputConfiguration"/> and <see cref="LogEventLevel"/>.
/// </summary>
/// <param name="services">The services to which registrations are added.</param>
/// <param name="inputConfiguration">The default configuration to use, which will be registered as a singleton and will overwrite the currently-set <see cref="Configuration"/>.</param>
/// <param name="logLevel">The log verbosity level with which to use for the minimal logger used for internal services. These services require an <see cref="ILogger"/> but may themselves be used to <strong>initialize</strong> an <see cref="ILogger"/>, so need separate configuration.</param>
/// <remarks>The <see cref="InputConfiguration"/> is registered as a singleton in the container, and the <paramref name="logLevel"/> is used to create a default logger for internal utility classes, irrespective of any other <see cref="ILogger"/> registered in the container. This method does not register an instance of <see cref="ILogger"/>, however one is required for the system to function. Callers need to provide their own implementation.</remarks>
/// <returns></returns>
public static IServiceCollection AddSbomConfiguration(this IServiceCollection services, InputConfiguration inputConfiguration, LogEventLevel logLevel = LogEventLevel.Information)
{
ArgumentNullException.ThrowIfNull(inputConfiguration);
services
.AddSingleton(_ =>
{
inputConfiguration.ToConfiguration();
return inputConfiguration;
})
.AddSbomTool(logLevel);
return services;
}

/// <summary>
/// Initializes the services required to use the SBOM Tool using a default <see cref="LogEventLevel"/>.
/// </summary>
/// <param name="services">The services to which registrations are added.</param>
/// <param name="logLevel">The log verbosity level with which to use for the minimal logger used for internal services. These services require an <see cref="ILogger"/> but may themselves be used to <strong>initialize</strong> an <see cref="ILogger"/>, so need separate configuration.</param>
/// <remarks>This method does not register an instance of <see cref="ILogger"/>, however one is required for the system to function. Callers need to provide their own implementation.</remarks>
public static IServiceCollection AddSbomTool(this IServiceCollection services, LogEventLevel logLevel = LogEventLevel.Information)
{
services
.AddSingleton<IConfiguration, Configuration>()
.AddTransient(x => FileSystemUtilsProvider.CreateInstance(CreateDefaultLogger()))
.AddTransient(x => FileSystemUtilsProvider.CreateInstance(CreateLogger(logLevel)))
.AddTransient<IWorkflow<SbomParserBasedValidationWorkflow>, SbomParserBasedValidationWorkflow>()
.AddTransient<IWorkflow<SbomGenerationWorkflow>, SbomGenerationWorkflow>()
.AddTransient<IWorkflow<SbomRedactionWorkflow>, SbomRedactionWorkflow>()
@@ -162,6 +190,11 @@ public static IServiceCollection AddSbomTool(this IServiceCollection services)
return services;
}

/// <summary>
/// This method integrates Serilog into the <see cref="Microsoft.Extensions.Logging"/> infrastructure.
/// </summary>
/// <param name="services"></param>
/// <returns></returns>
public static IServiceCollection ConfigureLoggingProviders(this IServiceCollection services)
{
var providers = new LoggerProviderCollection();
@@ -182,7 +215,13 @@ public static IServiceCollection ConfigureLoggingProviders(this IServiceCollecti
return services;
}

public static ILogger CreateDefaultLogger(LogEventLevel logLevel = LogEventLevel.Information)
/// <summary>
/// Creates a logger with the specified <paramref name="logLevel"/> that writes to a file and optionally to stderr.
/// This logger converts all errors from ComponentDetection assemblies to warnings, and does not write tabular output to stdout/stderr, only the configured file.
/// </summary>
/// <param name="logLevel"></param>
/// <returns></returns>
public static ILogger CreateLogger(LogEventLevel logLevel = LogEventLevel.Information)
{
return new RemapComponentDetectionErrorsToWarningsLogger(
new LoggerConfiguration()
11 changes: 4 additions & 7 deletions src/Microsoft.Sbom.Targets/GenerateSbomTask.cs
Original file line number Diff line number Diff line change
@@ -9,7 +9,6 @@ namespace Microsoft.Sbom.Targets;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Sbom.Api.Manifest.ManifestConfigHandlers;
using Microsoft.Sbom.Api.Metadata;
using Microsoft.Sbom.Api.Providers;
@@ -58,9 +57,7 @@ public override bool Execute()
NoComponentGovernanceSummary = true
};

var taskHost = Host.CreateDefaultBuilder()
.ConfigureServices((host, services) =>
services
using var services = new ServiceCollection()
.AddSingleton<IConfiguration, Configuration>()
.AddSingleton(runtimeConfiguration)
.AddSingleton<Serilog.ILogger>(msbuildLogger)
@@ -85,10 +82,10 @@ public override bool Execute()
.AddSingleton<IManifestInterface, SPDX22.Validator>()
.AddSingleton<IManifestInterface, SPDX30.Validator>()
.AddSingleton<IManifestConfigHandler, SPDX22ManifestConfigHandler>()
.AddSingleton<IManifestConfigHandler, SPDX30ManifestConfigHandler>())
.Build();
.AddSingleton<IManifestConfigHandler, SPDX30ManifestConfigHandler>()
.BuildServiceProvider();

var generator = taskHost.Services.GetRequiredService<ISbomGenerator>();
var generator = services.GetRequiredService<ISbomGenerator>();

// Set other configurations. The GenerateSBOMAsync() already sanitizes and checks for
// a valid namespace URI and generates a random guid for NamespaceUriUniquePart if
2 changes: 1 addition & 1 deletion src/Microsoft.Sbom.Tool/Program.cs
Original file line number Diff line number Diff line change
@@ -79,7 +79,7 @@ await Host.CreateDefaultBuilder(args)
.AddSingleton(x =>
{
var level = x.GetService<Common.Config.InputConfiguration>()?.Verbosity?.Value ?? Serilog.Events.LogEventLevel.Information;
var defaultLogger = Extensions.DependencyInjection.ServiceCollectionExtensions.CreateDefaultLogger(level);
var defaultLogger = Extensions.DependencyInjection.ServiceCollectionExtensions.CreateLogger(level);
Serilog.Log.Logger = defaultLogger;
return defaultLogger;
})

0 comments on commit 649d0fc

Please sign in to comment.