A Server-side Logging Guide for Aras Developers
If you've done any debugging in Aras Innovator®, you've probably used CCO.Utilities.WriteDebug() to write messages to a log file. It's been a staple for Aras developers for years - quick, easy, and gets the job done. But if you've recently upgraded to Release 14 or later, you might have noticed something new: a warning message telling you that WriteDebug is obsolete.
Don't worry - your logging code isn't broken (yet). But Aras has introduced a new, more powerful logging system based on Serilog, and it's worth taking the time to understand how it works. In this post, we'll walk through how to configure logging in Aras Innovator 14+, how to write to logs from your server methods, and where those logs can go.
Who is this for?
This guide is aimed at Aras Innovator developers who are comfortable writing server-side methods in C# and want to understand the logging options available in Release 14 and later. We'll assume you're familiar with basic Innovator concepts like AML, the IOM, and the method editor.
Why the change?
Starting in Release 14, Aras Innovator adopted Serilog as its logging framework. Serilog is a popular, structured logging library for .NET that offers a lot more flexibility than the old WriteDebug approach. With Serilog, you get:
- Multiple output destinations (called "sinks") - files, Windows Event Viewer, console, and more
- Configurable log levels so you can control how much detail gets logged
- Structured log messages with parameters
- Rolling log files with customizable naming
There's a small learning curve upfront, but the new logging approach is pretty powerful once you understand how to configure the settings and write the output. Let's look at a concrete example and see how we can tailor the output through configuration.
Quick start
At the most basic level, logging is just writing a little code to record output and then interpreting it after the code executes. We'll use this simple code snippet as we walk through the configuration settings, and then we'll look at some more code samples in a later section.
To follow along with this post, just add this code snippet to a server method in the Aras Innovator method editor and save the method.
// explicitly log a static string with CCO.Logger
CCO.Logger.Log(LogLevel.None, "Hello world!");
return this;
With this method, we can see the default logging behavior in action by using the "Run Server Method" action in the method editor.
After running the server method, we can find the log file in the server logs folder in our installation directory: {install_path}\Innovator\Server\logs\InnovatorServer_{YYYYMMDD}.log
2026-02-03T12:07:59.546 [FATL] Aras.Server.Core.CallContext | TraceId: | SpanId: | Hello world! | SessionId: 89b6d585-3aa8-35db-a6c6-e7fcac2ce8b9
Pretty easy, right? This simple example doesn't really show off the new logging capabilities, though. We'll need to review two important concepts to unlock the full power of Innovator's server logs – log levels and sinks.
Understanding log levels
Log levels determine which messages are actually included in the logged output. We can use the MinimumLevel setting to control the verbosity of our logs with a simple configuration, kind of like a filter. Only messages at or above the minimum level will be recorded, even if we have method code writing output at lower levels.
Aras Innovator supports six log levels, from most to least critical:
- Fatal - The most critical level. Use for events that demand immediate attention.
- Error – Use to record when functionality is unavailable or not working as expected.
- Warning – Use to indicate when service is degraded or behaving outside expected parameters.
- Information – Use to log actions we want to observe as the system operates.
- Debug – Use to log actions or information not provided by the higher log levels when investigating issues.
- Verbose – Use to log extra details that aren't necessary for typical logging but may be helpful for understanding system behavior. It's the noisiest level, so it's not recommended for production use.
The default log level for Aras Innovator applications is Fatal, meaning only the most critical errors are logged. For debugging, we'll typically want to lower this to Debug or Verbose.
You can view and manage your logging level with the "LoggerConfiguration" object in your {install_path}\Innovator\Server\appsettings.json file. These are the default settings in R35:
{
...
"LoggerConfiguration": {
"MinimumLevel": "Fatal",
"WriteTo": [
{ "Name": "Console" },
{ "Name": "File" },
{ "Name": "EventLog" }
]
},
...
}
Given all this information, you may be wondering why the log level list didn't include a "None" option, or why our sample code logged our "Hello world!" message even though it didn't have a "Fatal" log level.
LogLevel.None is a special value that forces the message to be logged regardless of the configured minimum level. This is useful for debugging when we absolutely need to see a message. It's not ideal to use for every message, though, because we won't be able to filter them out later, which can clutter our logs.
Let's update our sample method to use LogLevel.Debug:
// explicitly log a static string with CCO.Logger
CCO.Logger.Log(LogLevel.Debug, "Hello world!");
return this;
Now, when we run the method, we won't see a new "Hello world!" message logged because the MinimumLevel is set to "Fatal", which filters out all lower-priority messages.
Let's update our appsettings.json file to allow us to log debug messages:
"LoggerConfiguration": {
"MinimumLevel": "Debug",
"WriteTo": [
{ "Name": "Console" },
{ "Name": "File" },
{ "Name": "EventLog" }
]
}
After restarting IIS, we can rerun our updated server method and see that a new "Hello world!" message is logged as a DBUG line:
2026-02-03T13:40:04.386 [DBUG] Aras.Server.Core.CallContext | TraceId: | SpanId: | Hello world! | SessionId: b9dfa635-ad1d-e627-4d06-492a4032067f
We'll also see a bunch of messages from other server operations that we hadn't seen before. If we don't want to see them, we could set a higher level for our message, such as Warning or Error, and adjust our MinimumLevel accordingly. However, since this message isn't really a warning or an error, I personally prefer to use a searchable prefix or string to make my debug messages easier to find in the log file (in this case, "Hello world").
So now that we've discussed log levels, we're ready to look at sinks!
Where logs are written - understanding sinks
Serilog uses the concept of "sinks" to determine where log messages go. Aras Innovator supports three sinks out of the box: file, event log, and console.
File sink
The File sink is exactly what it sounds like - it writes logs to files on the server. As we saw with our previous samples, the default configuration creates log files in the {install_path}\Innovator\Server\logs folder, with names following the format {Server_name}_{date}.log.
Working with Aras Innovator hosted via SaaS? You won't have direct access to the server files, so your logs will be available in Grafana.
By updating the File sink settings in our appsettings.json file, we can tailor the location and output format to make our log files easier to read. Here are the options available to us:
- path – Where log files will be saved and how they'll be named
- default: logs/InnovatorServer_.log
- rollingInterval – How often to create a new log file
- default: Day
- shared – Whether multiple processes can write to the same file
- default: True
- outputTemplate – The format of each log message
- default: {Timestamp:yyyy-MM-ddTHH:mm:ss.fff} [{Level:u4}] {SourceContext} | TraceId: {TraceId} | SpanId: {SpanId} | {Message:l} | SessionId: {SessionId}{NewLine}{Exception}
Let's update our File sink configuration to give the log files a new naming convention and use a more skimmable format for each message. Be sure to restart IIS after updating your appsettings.config file.
"LoggerConfiguration": {
"MinimumLevel": "Debug",
"WriteTo": [
{ "Name": "Console" },
{
"Name": "File",
"Args": {
"path": "logs/MyLog_.log",
"outputTemplate": "{Timestamp:yy-MM-ddTHH:mm:ss.fff} [{Level:u4}] {SourceContext} | {Message:l}{NewLine}{Exception}"
}
},
{ "Name": "EventLog" }
]
}
Now our log files will have the MyLog_ prefix and a lighter template that excludes TraceId, SpanId, and SessionId.
Before:
2026-02-03T13:40:04.386 [DBUG] Aras.Server.Core.CallContext | TraceId: | SpanId: | Hello world! | SessionId: b9dfa635-ad1d-e627-4d06-492a4032067f
After:
26-02-03T16:50:42.632 [DBUG] Aras.Server.Core.CallContext | Hello world!
EventLog sink
The EventLog sink writes log entries to the Windows Event Viewer. This is useful if your IT team monitors the Event Viewer for application issues.
And just like the File sink, we have some configuration options:
- logName - Which log to write to (Application, System, or a custom log)
- default: Application
- source - The source name that identifies your application
- default: Aras Innovator
- manageEventSource - Whether to automatically create the event source if it doesn't exist
- default: false
There can be A LOT of events in the Application log even after filtering by source name "Aras Innovator". To find a specific message, we can use the "Find" action in the Windows Event Viewer to locate messages by keyword.
Console sink
The Console sink writes to the Windows Console or terminal via standard output. This is mainly useful if you're running Innovator from the console for testing - console logs won't appear in typical IIS-hosted deployments.
Console logging will likely be the least common approach, so we won't dive into the details in this blog post. Let us know in the comments if you're interested in learning more about console logging, and we'll help you find the resources you need.
Writing to logs from server methods
So far, our method code for writing log output has been pretty simple – just a static "hello world" message. However, we'll typically need to log more complex data, such as dynamic messages, items, or structured objects.
Check out this extended example to see how we can easily handle all of these cases with the same CCO.Logger.Log function.
// explicitly log a static string with CCO.Logger
CCO.Logger.Log(LogLevel.None, "Hello world!");
CCO.Logger.Log(LogLevel.None, "I can even use emojis in my logs 😊");
// I can log an Item
Innovator inn = this.getInnovator();
Item part = inn.getItemById("Part", "26F38DC1A0ED450DB32344905D4BCAB5");
CCO.Logger.Log(LogLevel.None, "Here's a Part: \r\n{part}", part);
// I can log a structured object too
var position = new { Latitude = 25, Longitude = 134 };
var elapsedMs = 34;
CCO.Logger.Log(LogLevel.None, "📍Processed {@Position} in {Elapsed:000} ms.", position, elapsedMs);
return this;
Troubleshooting
My log messages aren't appearing
First, verify that your minimum level is set correctly. If you're using LogLevel.Debug in your code, but the configuration is set to Fatal, your messages won't appear.
I can't control the log file name
One limitation of CCO.Logger.Log() compared to the old WriteDebug method is that you don't have direct control over the log file name - it's determined by the configuration. If you need custom file names, you have two options:
- Modify the path setting in your File sink configuration
- Create a custom logging method using Serilog directly that supports filename specification
Log messages aren't appearing in Windows Event Viewer
Make sure the EventLog sink is configured and that the source is properly registered. You may need to run Innovator with elevated permissions the first time to create the event source, or set manageEventSource to true in your configuration.
Wrapping up
The new Serilog-based logging in Innovator 14+ is more powerful than the old WriteDebug approach, even if it takes a bit more configuration to get started. Here's a quick summary:
- Replace CCO.Utilities.WriteDebug() with CCO.Logger.Log().
- Set the MinimumLevel in appsettings.json to determine which messages are logged.
- Configure the sinks in appsettings.json to control where messages are logged.
- Check your log files in {install_path}\Innovator\Server\logs.
- Always restart IIS after changing the logging configuration.
For more details on Serilog configuration options, check out the official documentation:
Have questions about logging in Innovator? Drop them in the Aras Community Forums - we're always happy to help!