Ok this has been brought up before (Here), but I don’t think enough is known about it so here is an expansion on the topic.
This thing is awesome. I will cover 3 different scenarios from the example.
Create a default log
Create a specific log
Create an Application Insights Log (Yes you read that right, it logs to Azure…)
From the help →
You can create custom loggers in both Business Process Management (BPM) directives and Epicor Functions. Typically you create the logger in a functions library that you then call from a BPM directive. The logger generates the application logs. Application logging captures errors and tracks specific Kinetic activity. You define what an application log captures and tracks by creating a custom logger. You can then better locate the causes of issues or capture process calls.
You can find the help from the client by searching like so:
//refs:
//Microsoft.Extensions.Logging.Abstractions.dll
//Microsoft.Extensions.Logging.dll
//using Microsoft.Extensions.Logging;
//using Ice.Logging;
/* Example uses C# 8, so this is wrong for us.
using logger = Ice.Logging.ApplicationLoggerBuilder.CreateDefaultBuilder(this.Session, "LogId")
.Build();
logger.LogInformation("Log message");
*/
//This is based on the session, so this will write a file called "HelloWorld.log" to the 'EpicorData/Users/UserName/Log/' folder.
//In my case -> 'EpicorData/Users/KLINCECUM/Log/HelloWorld.log'
//In the default logger, this will add '.log' to the name.
string fileName = "HelloWorld";
using (var logger = Ice.Logging.ApplicationLoggerBuilder.CreateDefaultBuilder(this.Session, fileName).Build())
{
logger.LogInformation("Hello World!");
}
//Pudding ->
var file = new FilePath(ServerFolder.UserData, $"Log/{fileName}.log");
output = Sandbox.IO.File.ReadAllText(file, System.Text.Encoding.UTF8);
//refs:
//Microsoft.Extensions.Logging.Abstractions.dll
//Microsoft.Extensions.Logging.dll
//using Microsoft.Extensions.Logging;
//using Ice.Logging;
//This is based on the session, so this will write a file called "SpecificLog.txt" to the 'epicordata/Companies/YOURCOMPANY/Log' folder. (path is not exact)
//In my case -> 'epicordata/SITEID/Companies/YOURCOMPANY/Log/SpecificLog.txt'
//We can use an arbitrary name and extension here.
string fileName = "SpecificLog.txt";
var logger = ApplicationLoggerBuilder.CreateBuilder()
.SetMinimumLevel(LogLevel.Information)
.AddFile(
options =>
{
options.Session = this.Session;
options.FileName = fileName;
options.Folder = LogFolder.Company;
options.MessageOptions.QuoteValues = false;
options.MessageOptions.ShowLogLevel = true;
options.MessageOptions.TimestampFormat = TimestampFormat.Time;
})
.Build();
using (logger)
{
logger.LogInformation("This is a test: {Value}", "test");
logger.LogError("This is a error test: {Value}", "error");
}
//Pudding ->
var file = new FilePath(ServerFolder.CompanyData, $"Log/{fileName}");
output = Sandbox.IO.File.ReadAllText(file, System.Text.Encoding.UTF8);
Yes, you can log to Azure, right from inside Epicor.
I’ll come back and add some instructions for setting that up in Azure.
Code
//refs:
//Microsoft.Extensions.Logging.Abstractions.dll
//Microsoft.Extensions.Logging.dll
//Microsoft.ApplicationInsights.dll <- For Going Further
//using Microsoft.Extensions.Logging;
//using Ice.Logging;
//Going Further...
//using Microsoft.ApplicationInsights;
//using Microsoft.ApplicationInsights.Extensibility;
/*
From the example ->
const string connectionString = "InstrumentationKey=aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa;IngestionEndpoint=https://centralus-0.in.applicationinsights.azure.com/;LiveEndpoint=https://centralus.livediagnostics.monitor.azure.com/";
using var logger = ApplicationLoggerBuilder.CreateBuilder()
.AddApplicationInsights(
options =>
{
options.ConnectionString = connectionString;
})
.Build();
*/
//See this beauty... Yep, we can log straight to Azure.
string connectionString = "Put your own key here, looks similar to below.";
//string connectionString = "InstrumentationKey=aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa;IngestionEndpoint=https://centralus-0.in.applicationinsights.azure.com/;LiveEndpoint=https://centralus.livediagnostics.monitor.azure.com/";
var logger = ApplicationLoggerBuilder.CreateBuilder()
.AddApplicationInsights(
options =>
{
options.ConnectionString = connectionString;
})
.Build();
using (logger)
{
for(int x = 0; x < 10; x++ )
{
logger.LogInformation("Azure Logging test: {Value}", x.ToString());
}
}
//Or you can go further down the rabbit hole...
using (var config = TelemetryConfiguration.CreateDefault())
{
config.ConnectionString = connectionString;
var telemetryClient = new TelemetryClient(config);
telemetryClient.TrackEvent("ThisIsMyCustomEvent");
telemetryClient.TrackTrace("ThisIsMyCustomTraceLog");
telemetryClient.TrackException(new Exception("YouSuckException!!!"));
}
Where did Sandbox.IO come from? Is that only in cloud or newer than 2024.2?
I get warnings about writing directly to a file using System.IO stuff - I guess there has been other chatter about Epicor removing these at some point (although I can ignore the warnings it does currently work on 2024.2.10):
I saw your code and thought maybe there is a correct way to write to a log file and avoid these warnings, but I tried the ApplicationLogger stuff and wasn’t happy that I couldn’t get it to write to:
\\server\KineticData\EfxLogs\logname.log
Seems like you have to pass in an object of type LogFolder to the options.Folder and not sure if I can get my own arbitrary folder a few levels up to be part of that path.
My “problem” with LogFolder.Company (e.g. \\server\KineticData\Companies\MYCOMPANY\Log\) is that it is already full of ImportEDI logs, and other noise.