Google.Cloud.Diagnostics.AspNetCore3 debug level not working

Viewed 398

Consider a wizard generated ASP.NET Core project (NET 6). Add a Google.Cloud.Diagnostics.AspNetCore3 NuGet package and services.AddGoogleDiagnosticsForAspNetCore() to Startup.cs. Let GOOGLE_APPLICATION_CREDENTIALS environment variable point to a path to your service account JSON.

Somewhere in the app (e.g. a controller) add the following:

_logger.LogDebug("Nope");
_logger.LogInformation("Yeah");

Google Cloud Logs Explorer shows only the "Yeah" (no specific filters). My appsettings.json looks like:

"Logging": {
  "LogLevel": {
    "Default": "Debug",
    "System": "Information",
    "Microsoft": "Information"
  }
}

As far as I understand the "Default": "Debug" should work everywhere where a more specific config is missing.

Why am I not seeing the "Nope" being logged? Anything obvious that I'm missing? It's worth mentioning that both Visual Studio Debug Output as well as the Console output show both Nope/Yeah as expected.

2 Answers

Short Answer: Google.Cloud.Diagnostics.AspNetCore3 does not use appsettings.json (at least for now) and one must explicitly set log levels.

Now to the long answer and working code after that.

To add Google Diagnostics to our project we have 3 overloads of ...AddGoogleDiagnosticsForAspNetCore(...) available, and also ...AddGoogle(...) just to use a service we need, such as logging service. (... at the beginning changes depending on dotnet version, examples at the end).

1- In a GCP environment, ...AddGoogleDiagnosticsForAspNetCore() signature is used to set defaults for the Diagnostics. Service details are fetched from GCP.

2- In a GCP environment, ...AddGoogleDiagnosticsForAspNetCore( AspNetCoreTraceOptions, LoggingServiceOptions, ErrorReportingServiceOptions ) signature we can set 3 types of options: AspNet Tracing, Logging Service and Error Reporting Service.

  • For this use case, if we want only logging services, we can either use positional arguments (null,new LoggingServiceOptions{...},null) (last null is not required) or named arguments (loggingOptions: new LoggingServiceOptions{...})
  • There are many to be set in LoggingServicesOptions{...} but just for log level purpose the following will suffice: new LoggingServiceOptions{ Options = LoggingOptions.Create(logLevel: LogLevel.Debug) }.

Now we have come to the important one. Although documentation covers enough of it implicitly, it is not made explicitly clear that this use case will directly set options, not services.

3- Although not explicitly clear, this use is for cases outside GCP or when GCP cannot be set properly(not sure how!?) AddGoogleDiagnosticsForAspNetCore( projectId, serviceName, serviceVersion, TraceOptions, LoggingOptions, ErrorReportingOptions ). This may seem similar to the 2nd signature at first, but it does not set options for services.

  • When one sees Project ID was not provided and could not be autodetected message for 1st or 2nd signature, they have to provide it as a parameter which immediately switches the function to use this 3rd signature.
  • In this case, if we want only logging services, it has to be used in the form of (projectId,null,null,null,LoggingOptions...,null) for positional arguments (last null is not required) or (projectId:"some ID",loggingOptions: LoggingOptions...) for named arguments
  • LoggingOptions... is simply be LoggingOptions.Create(logLevel: LogLevel.Debug) to set log level.

4- Apart from adding these details while adding Google Diagnostics to the services, we can instead add logging options when we set configurations: ...AddGoogle( LoggingServiceOptions{...} ). But in this use, we need to provide a project Id in it; new LoggingServiceOptions{ ProjectId = "some ID", Options = LoggingOptions.Create(logLevel: LogLevel.Debug) }


fill in the ...

dotnet 6 started using new top level statements. so we have following steps to follow.

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddGoogleDiagnosticsForAspNetCore(
 projectId: "some ID",
 loggingOptions:  LoggingOptions.Create(logLevel: LogLevel.Debug)
);

// or
var builder = WebApplication.CreateBuilder(args);
builder.Logging.AddGoogle(
  new LoggingServiceOptions { 
    ProjectId = "some ID",
    Options=LoggingOptions.Create(logLevel:LogLevel.Debug)
  }
);

Since the OP mentions the use of Startup.cs, the project uses the old style so these are the required parts for that.

// inside ConfigureServices
services.AddGoogleDiagnosticsForAspNetCore(
 projectId: "some ID",
 loggingOptions:  LoggingOptions.Create(logLevel: LogLevel.Debug)
);

// or
// before using "UseStartup"
.ConfigureLogging(
  builder => builder.AddGoogle(
    new LoggingServiceOptions { 
      ProjectId = "some ID",
      Options=LoggingOptions.Create(logLevel:LogLevel.Debug)
    }
  )
)

Extra

We can read from the configuration file (top-level format)

var builder = WebApplication.CreateBuilder(args);
var config = builder.Configuration;
builder.Services.AddGoogleDiagnosticsForAspNetCore(
  projectId:config["GCP:ID"],
  loggingOptions:  LoggingOptions.Create(
     logLevel: Enum.Parse<LogLevel>(config["GCP:Logging:LogLevel:Default"]
)));

and add a GCP section in appsettings.json

  "GCP":{
    "ID":"some ID",
    "Logging":{
      "LogLevel":{
        "Default":"Debug"
      }
    }
  }

I've downloaded the mentioned package (it's open-source) and checked default logging-options creation:

enter image description here

As you may see the default logLevel is Information.

And as you go through the implementation there's no sign of reading the level from the config - it's simply passed from the options you may specify in the code:

Initial invocation: enter image description here

Service provider registration: enter image description here

Creation of logging provider and options: enter image description here

Creation of options (1st picture) enter image description here

And creation of logger (probably invoked somewhere internally by ASP.NET) enter image description here

The simple answer is Google package doesn't read anything from the appsettings.json by default.

You can set the logging level by using the LoggingOptions:
(Other options omitted for brevity)

builder.Services.AddGoogleDiagnosticsForAspNetCore(loggingOptions: new Google.Cloud.Diagnostics.Common.LoggingServiceOptions
{
    // ... Other required options, e.g. projectId
    Options = Google.Cloud.Diagnostics.Common
        .LoggingOptions.Create(logLevel: LogLevel.Debug
        // ... Other necessary options 
        ),
});
Related