Skip to content

Add CCM (CMTrace) log file format option#6284

Open
pl4nty wants to merge 1 commit into
microsoft:masterfrom
devicie:ccm-log-format
Open

Add CCM (CMTrace) log file format option#6284
pl4nty wants to merge 1 commit into
microsoft:masterfrom
devicie:ccm-log-format

Conversation

@pl4nty

@pl4nty pl4nty commented Jun 13, 2026

Copy link
Copy Markdown

📖 Description

Add a logging.format user setting that selects the format used when writing log entries to a file. The default winget value preserves the existing format, while ccm writes CCM-compatible lines so WinGet logs can be viewed with common IT admin tools (particularly CMTrace and OneTrace).

🔗 References

No issue for this one, but credit to @mjr4077au for the idea while we were chatting with chtulip.

🔍 Validation

Set logging.format to ccm, then opened some WinGetDev.exe logs with OneTrace and CMTrace

image image

Open Questions

  • Is this desirable? I wasn't able to find an open issue, but I've heard a few IT admins mention it
  • Would this change need a release note?
  • I suspect a Group Policy setting for this would be very useful, but maybe it should support the other logging options too

✅ Checklist

📋 Issue Type

  • Bug fix
  • Feature
  • Task
Microsoft Reviewers: Open in CodeFlow

Assisted-by: Claude:claude-4.8-opus
Signed-off-by: Tom Plant <tom.plant@devicie.com>
@pl4nty pl4nty requested a review from a team as a code owner June 13, 2026 12:00
FileLogger_MaximumSize_Test(tagState, sizeState);
}

TEST_CASE("FileLogger_CCMFormat", "[logging]")

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure this test and the new imports are necessary, since there isn't one for the existing format. Figured I'd submit just in case

@florelis

Copy link
Copy Markdown
Member

I like the idea. I would want to see it in the release notes if we take the change.
I wonder if this could be an "in addition to" instead of "instead of" option.

Do you have any documentation about the format that we could include in the code? I could only find general details about the viewer and an implementation of how to write the logs. Maybe we could have a comment like "The format is ...; see for reference"

"@JohnMcPMS" also wrote a custom log viewer exclusively for winget logs that you could use.

@pl4nty

pl4nty commented Jun 17, 2026

Copy link
Copy Markdown
Author

Thanks, I'm glad you like it. OneTrace has a useful feature to open a folder and show all the merged logs in one page, which would be confusing if there were multiple copies of the same log. I guess we could log to a subfolder? I took this logging.format approach in case other log formats might be added later, but I can't think of any.

I spent a while looking and couldn't find any documentation for the format. Ended up decompiling OneTrace to find this:

// ConfigMgrSupportCenter.Common, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
// Microsoft.ConfigurationManagement.SupportCenter.Common.LogMessage
using System;
using System.Diagnostics;
using System.Globalization;
using System.Threading;
using Microsoft.ConfigurationManagement.SupportCenter.Common;

internal sealed class LogMessage
{
	private const string LogLine = "<![LOG[{0}]LOG]!><time=\"{1:HH:mm:ss}.000+000\" date=\"{1:MM-dd-yyyy}\" component=\"{2}\" context=\"{3}\" type=\"{4}\" thread=\"{5}\" file=\"{6}\">";

	public int ContextId { get; }

	public string Message { get; }

	public LogLevel Severity { get; }

	public string SourceFile { get; }

	public string SourceName { get; }

	public int ThreadId { get; }

	public DateTime Time { get; }

	public LogMessage(string message, LogLevel severity)
	{
		Message = message;
		Severity = severity;
		SourceName = null;
		Time = DateTime.Now;
		StackTrace stackTrace = new StackTrace();
		ThreadId = Thread.CurrentThread.ManagedThreadId;
		ContextId = Thread.CurrentContext.ContextID;
		if (stackTrace.FrameCount > 2)
		{
			StackFrame frame = stackTrace.GetFrame(2);
			if (!string.IsNullOrEmpty(frame.GetFileName()))
			{
				SourceFile = string.Format(CultureInfo.InvariantCulture, "{0}:{1}", frame.GetFileName(), frame.GetFileLineNumber());
			}
		}
		else
		{
			StackFrame frame2 = stackTrace.GetFrame(1);
			if (!string.IsNullOrEmpty(frame2.GetFileName()))
			{
				SourceFile = string.Format(CultureInfo.InvariantCulture, "{0}:{1}", frame2.GetFileName(), frame2.GetFileLineNumber());
			}
		}
	}

	public override string ToString()
	{
		return string.Format(CultureInfo.InvariantCulture, "<![LOG[{0}]LOG]!><time=\"{1:HH:mm:ss}.000+000\" date=\"{1:MM-dd-yyyy}\" component=\"{2}\" context=\"{3}\" type=\"{4}\" thread=\"{5}\" file=\"{6}\">", Message, Time, SourceName, ContextId, (int)Severity, ThreadId, SourceFile);
	}
}

I saw John's viewer and it looked really useful to me as a dev, but IT admins are usually familiar with CMTrace/OneTrace and may not even have VSCode installed (besides figuring out how to sideload an extension). So I don't think it would help them unfortunately.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants