Tuesday, August 15, 2023

Azure @ Enterprise - Configuring PnP.Framework SDK logs to trace file

Context

Environment - Microsoft Azure Virtual Machines

Technology - .Net Framework 4.8, SharePoint Online

Functionality - Interacting with SharePoint Online via Graph SDK and PnP.Framework, Mainly uploading a large number of files.

Requirement - Trying to collect the logs emitted by PnP.Framework especially the HTTP calls.

Solution

The PnP.Framework emits the traces by default using the standard .Net Trace class. Note it is not the ILogger that is now the standard after .Net Framework. Refer to the source code to ensure they change in the future. There is an ILogger class involved but that is not the same .Net Core uses
  • .Net Core programming model - Microsoft.Extensions.Logging.ILogger & Microsoft.Extensions.Logging.ILogger<TCategoryName>
  • PnP.Framework - PnP.Framework.Diagnostics.ILogger
The default implementation of PnP.Framework is using TraceLogger class which is implemented by the same SDK. It uses the Trace class as mentioned above. So if we don't configure anything else, we can collect the logs to a file using the below configuration changes in app.config or web.config.
<system.diagnostics>
    <trace autoflush="true" indentsize="1">
      <listeners>
        <add name="Listener1" type="System.Diagnostics.TextWriterTraceListener" initializeData="path\to\file.ext" />
        <remove name="Default" />
      </listeners>
    </trace>
... 
</system.diagnostics>

Here ends the basic solution to the problem. Anytime PnP.Framework SDK logs it will be saved to the file mentioned in the <listeners> section.

Log Level

By default the PnP.Framework logs at 'debug' which is strange.
But that can be changed with some adjustments. Config changes goes below
<configSections>
    <sectionGroup name="pnp">
      <section name="tracing" type="PnP.Framework.Diagnostics.LogConfigurationTracingSection,PnP.Framework"/>
    </sectionGroup>
  </configSections>
  <pnp>
    <tracing logLevel="Debug">
    </tracing>
  </pnp>Basically this is adding a new section group and section that is read by the PnP.Framework. The logLevel attribute can be adjusted to control the logging level.

Enhancements

Route the Traces to Azure Application Insights or any other telemetry collection system is recommended for production. There are already many ways to do the same as Trace was a standard way to log in class .Net Framework.

If we need to customize the logging destination, we can even implement our own the PnP.Framework.Diagnostics.ILogger passes it via configuration. It is as follows
<pnp>
    <tracing logLevel="Debug">
      <logger type="MyAssembly.MyPnPFwkLogger,MyAssembly"></logger>
    </tracing>
  </pnp>

Obviously, we need to code MyPnPFwkLogger class by implementing the ILogger interface. A sample implementation is below.

    class MyPnPFwkLogger : ILogger
   {
        void ILogger.Debug(LogEntry entry)
        {
            Console.WriteLine(entry);
        }
        void ILogger.Error(LogEntry entry)
        {
            Console.WriteLine(entry);
        }
        void ILogger.Info(LogEntry entry)
        {
            Console.WriteLine(entry);
        }
        void ILogger.Warning(LogEntry entry)
        {
            Console.WriteLine(entry);
        }
    }

This looks obvious, but it is very useful if we are seriously interacting with SharePoint Online via APIs.  Many times the request-id is not present in other logs. Without request-id Microsoft support cannot locate the logs and solve problems.

Happy coding...

No comments: