Skip to content

Commit

Permalink
refactor: Add better extension methods for Diagnostics Error Reporting.
Browse files Browse the repository at this point in the history
- Make more of the old code obsolete.
- Delete in XML docs samples that quickly get outdated. We have snippets.
  • Loading branch information
amanda-tarafa committed Oct 11, 2021
1 parent e1080c9 commit 037af1a
Show file tree
Hide file tree
Showing 13 changed files with 229 additions and 124 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,9 @@
using Google.Cloud.Diagnostics.Common;
using Google.Cloud.Diagnostics.Common.IntegrationTests;
using Google.Cloud.Logging.V2;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
using System.Linq;
using System.Net;
Expand Down Expand Up @@ -151,14 +149,6 @@ private class ErrorReportingTestApplication : BaseStartup

public override void ConfigureServices(IServiceCollection services) =>
base.ConfigureServices(services
.AddGoogleExceptionLogging(options =>
{
options.ProjectId = ProjectId;
options.ServiceName = EntryData.Service;
options.Version = EntryData.Version;
// This is just so that our validator finds the log entries associated to errors.
options.Options = ErrorReportingOptions.Create(EventTarget.ForLogging(ProjectId, "aspnetcore"));
})
.AddGoogleTraceForAspNetCore(new AspNetCoreTraceOptions
{
ServiceOptions = new Common.TraceServiceOptions
Expand All @@ -167,10 +157,15 @@ private class ErrorReportingTestApplication : BaseStartup
Options = TraceOptions.Create(
double.PositiveInfinity, BufferOptions.NoBuffer(), RetryOptions.NoRetry(ExceptionHandling.Propagate))
}
})
.AddGoogleErrorReportingForAspNetCore(new Common.ErrorReportingServiceOptions
{
ProjectId = ProjectId,
ServiceName = EntryData.Service,
Version = EntryData.Version,
// This is just so that our validator finds the log entries associated to errors.
Options = ErrorReportingOptions.Create(EventTarget.ForLogging(ProjectId, "aspnetcore"))
}));

public override void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory) =>
base.Configure(app.UseGoogleExceptionLogging(), loggerFactory);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,9 @@

using Google.Cloud.ClientTesting;
using Google.Cloud.Diagnostics.Common.IntegrationTests;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
using System.Net;
using System.Net.Http;
Expand Down Expand Up @@ -115,25 +113,19 @@ public override void ConfigureServices(IServiceCollection services)
application.ConfigureServices(services);
base.ConfigureServices(services);
}

public override void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
application.Configure(app);
base.Configure(app, loggerFactory);
}
}

// Sample: ReportUnhandledExceptions
public void ConfigureServices(IServiceCollection services)
{
services.AddGoogleExceptionLogging(options =>
services.AddGoogleErrorReportingForAspNetCore(new Common.ErrorReportingServiceOptions
{
// Replace ProjectId with your Google Cloud Project ID.
options.ProjectId = ProjectId;
ProjectId = ProjectId,
// Replace Service with a name or identifier for the service.
options.ServiceName = Service;
ServiceName = Service,
// Replace Version with a version for the service.
options.Version = Version;
Version = Version
});

// Add any other services your application requires, for instance,
Expand All @@ -144,32 +136,6 @@ public void ConfigureServices(IServiceCollection services)

// services.AddControllersWithViews();
}

public void Configure(IApplicationBuilder app)
{
// Use before handling any requests to ensure all unhandled exceptions are reported.
app.UseGoogleExceptionLogging();

// Add any other configuration your application requires, for instance,
// depending on the verson of ASP.NET Core you are using, you may
// need one of the following:

//app.UseMvc(routes =>
//{
// routes.MapRoute(
// name: "default",
// template: "{controller=Home}/{action=Index}/{id?}");
//});

//app.UseRouting();
//app.UseEndpoints(endpoints =>
//{
// endpoints.MapControllerRoute(
// name: "default",
// pattern: "{controller=Home}/{action=Index}/{id?}");
// endpoints.MapRazorPages();
//});
}
// End sample
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using Google.Cloud.Diagnostics.Common;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using System;

#if NETCOREAPP3_1
namespace Google.Cloud.Diagnostics.AspNetCore3
#elif NETSTANDARD2_0
namespace Google.Cloud.Diagnostics.AspNetCore
#else
#error unknown target framework
#endif
{
/// <summary>
/// Extensions for configuring Google Cloud Error Reporting in ASP.NET Core applications.
/// </summary>
public static class AspNetCoreErrorReportingExtensions
{
/// <summary>
/// Configures Google Cloud Error Reporting for ASP .NET Core applications./>.
/// </summary>
public static IServiceCollection AddGoogleErrorReportingForAspNetCore(
this IServiceCollection services, Common.ErrorReportingServiceOptions options = null) =>
#pragma warning disable CS0618 // Type or member is obsolete
services.AddGoogleErrorReportingForAspNetCore(true, options);
#pragma warning restore CS0618 // Type or member is obsolete

[Obsolete("Added for avoiding code duplication while we made old methods obsolete and included substitutes")]
internal static IServiceCollection AddGoogleErrorReportingForAspNetCore(
this IServiceCollection services, bool registerMiddleware, Common.ErrorReportingServiceOptions options)
{
services.AddGoogleErrorReporting(options);
services.AddHttpContextAccessor();
services.AddSingleton<IExceptionLogger>(sp => new GoogleExceptionLogger(
sp.GetRequiredService<IContextExceptionLogger>(),
sp.GetRequiredService<IHttpContextAccessor>()));

if (registerMiddleware)
{
// This registers the trace middleware so users don't have to.
services.AddSingleton<IStartupFilter, AspNetCoreErrorReportingStartupFilter>();
}

return services;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using System;

#if NETCOREAPP3_1
namespace Google.Cloud.Diagnostics.AspNetCore3
#elif NETSTANDARD2_0
namespace Google.Cloud.Diagnostics.AspNetCore
#else
#error unknown target framework
#endif
{
internal class AspNetCoreErrorReportingStartupFilter : IStartupFilter
{
public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next) =>
app => next(app.UseMiddleware<ErrorReportingExceptionLoggerMiddleware>());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,42 +32,29 @@ namespace Google.Cloud.Diagnostics.AspNetCore
/// To ensure all unhandled exceptions are reported, this should be
/// the first piece of middleware used.
/// </summary>
///
/// <example>
/// <code>
/// public void ConfigureServices(IServiceCollection services)
/// {
/// string projectId = "[Google Cloud Platform project ID]";
/// string serviceName = "[Name of service]";
/// string version = "[Version of service]";
/// services.AddGoogleExceptionLogging(projectId, serviceName, version);
/// ...
/// }
/// </code>
/// </example>
///
/// <example>
/// <code>
/// public void Configure(IApplicationBuilder app)
/// {
/// // Use before handling any requests to ensure all unhandled exceptions are reported.
/// app.UseGoogleExceptionLogging();
/// ...
/// }
/// </code>
/// </example>
///
/// <remarks>
/// Reports unhandled exceptions to Google Cloud Error Reporting.
/// Docs: https://cloud.google.com/error-reporting/docs/
/// </remarks>
#if NETCOREAPP3_1
[Obsolete("Use Google.Cloud.Diagnostics.AspNetCore3.AspNetCoreErrorReportingExtensions instead.")]
#elif NETSTANDARD2_0
[Obsolete("Use Google.Cloud.Diagnostics.AspNetCore.AspNetCoreErrorReportingExtensions instead.")]
#else
#error unknown target framework
#endif
public static class ErrorReportingExceptionLoggerExtension
{
/// <summary>
/// Uses middleware that will report all uncaught exceptions to the Google Cloud
/// Error Reporting API.
/// </summary>
/// <param name="app">The application builder. Must not be null.</param>
#if NETCOREAPP3_1
[Obsolete("Use Google.Cloud.Diagnostics.AspNetCore3.AspNetCoreErrorReportingExtensions.AddGoogleErrorReportingForAspNetCore " +
"for configuring Google Cloud Error Reporting in ASP.NET Core applications. There's no need to explicitly register the middleware.")]
#elif NETSTANDARD2_0
[Obsolete("Use Google.Cloud.Diagnostics.AspNetCore.AspNetCoreErrorReportingExtensions.AddGoogleErrorReportingForAspNetCore " +
"for configuring Google Cloud Error Reporting in ASP.NET Core applications. There's no need to explicitly register the middleware.")]
#else
#error unknown target framework
#endif
public static IApplicationBuilder UseGoogleExceptionLogging(this IApplicationBuilder app)
{
GaxPreconditions.CheckNotNull(app, nameof(app));
Expand All @@ -92,29 +79,29 @@ public static IApplicationBuilder UseGoogleExceptionLogging(this IApplicationBui
/// with both exceptions will be thrown. Otherwise only the exception from the <see cref="RequestDelegate"/>
/// will be thrown.
/// </remarks>
public static IServiceCollection AddGoogleExceptionLogging(
#if NETCOREAPP3_1
[Obsolete("Use Google.Cloud.Diagnostics.AspNetCore3.AspNetCoreErrorReportingExtensions.AddGoogleErrorReportingForAspNetCore instead.")]
#elif NETSTANDARD2_0
[Obsolete("Use Google.Cloud.Diagnostics.AspNetCore.AspNetCoreErrorReportingExtensions.AddGoogleErrorReportingForAspNetCore instead.")]
#else
#error unknown target framework
#endif
public static IServiceCollection AddGoogleExceptionLogging(
this IServiceCollection services, Action<ErrorReportingServiceOptions> setupAction)
{
GaxPreconditions.CheckNotNull(services, nameof(services));
GaxPreconditions.CheckNotNull(setupAction, nameof(setupAction));

var serviceOptions = new ErrorReportingServiceOptions();
setupAction(serviceOptions);
services.AddHttpContextAccessor();
services.AddSingleton(ContextExceptionLogger.Create(
serviceOptions.ProjectId, serviceOptions.ServiceName, serviceOptions.Version, serviceOptions.Options));
return services.AddSingleton(CreateExceptionLogger);
}


/// <summary>
/// Creates an <see cref="IExceptionLogger"/>.
/// </summary>
private static IExceptionLogger CreateExceptionLogger(IServiceProvider provider)
{
var accessor = provider.GetRequiredService<IHttpContextAccessor>();
var contextLogger = provider.GetRequiredService<IContextExceptionLogger>();
return new GoogleExceptionLogger(contextLogger, accessor);
return services.AddGoogleErrorReportingForAspNetCore(registerMiddleware: false, new Common.ErrorReportingServiceOptions
{
ProjectId = serviceOptions.ProjectId,
ServiceName = serviceOptions.ServiceName,
Version = serviceOptions.Version,
Options = serviceOptions.Options
});
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
// limitations under the License.

using Google.Cloud.Diagnostics.Common;
using System;

#if NETCOREAPP3_1
namespace Google.Cloud.Diagnostics.AspNetCore3
Expand All @@ -25,6 +26,7 @@ namespace Google.Cloud.Diagnostics.AspNetCore
/// <summary>
/// Configuration for initializing error reporting.
/// </summary>
[Obsolete("Use Google.Cloud.Diagnostics.Common.ErrorReportingServiceOptions instead.")]
public sealed class ErrorReportingServiceOptions
{
/// <summary>
Expand All @@ -34,17 +36,17 @@ public sealed class ErrorReportingServiceOptions
public string ProjectId { get; set; }

/// <summary>
/// An identifier of the service, such as the name of the executable or job. Must not be null.
/// An identifier of the service, such as the name of the executable or job. May be null.
/// </summary>
public string ServiceName { get; set; }

/// <summary>
/// Represents the source code version that the developer provided. Must not be null.
/// Represents the source code version that the developer provided. May be null.
/// </summary>
public string Version { get; set; }

/// <summary>
/// Error reporting options for exception logging. Can be null.
/// Error reporting options for exception logging. May be null.
/// </summary>
public ErrorReportingOptions Options { get; set; }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,23 +30,6 @@ namespace Google.Cloud.Diagnostics.AspNetCore
/// <summary>
/// Google Cloud Error Reporting Logger. Reports exceptions to the Google Cloud Error Reporting API.
/// </summary>
///
/// <example>
/// <code>
/// public void ReadFile(IExceptionLogger exceptionLogger)
/// {
/// try
/// {
/// string scores = File.ReadAllText(@"C:\Scores.txt");
/// Console.WriteLine(scores);
/// }
/// catch (IOException e)
/// {
/// exceptionLogger.Log(e);
/// }
/// }
/// </code>
/// </example>
internal sealed class GoogleExceptionLogger : IExceptionLogger
{
private readonly IContextExceptionLogger _logger;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
{
var loggerFactory = app.ApplicationServices.GetRequiredService<ILoggerFactory>();
loggerFactory.AddGoogle(app.ApplicationServices, _projectId, _loggerOptions);
app.UseGoogleExceptionLogging();
next(app);
};
Expand Down
Loading

0 comments on commit 037af1a

Please sign in to comment.