Add telemetry event on container creation (#40704)

* Add telemetry event on container creation * Apply PR feedback * Update test

Blue committed Jun 7, 2026 at 21:44 UTC 6f8d2e439bf6f9ffd4ce9e15d3016c91998a4c28
6 files changed +37 -20
src/windows/service/exe/WSLCSessionManager.cpp
+3 -3
@@ -270,7 +270,7 @@ void WSLCSessionManagerImpl::CreateSession(
270 auto factory = wslutil::CreateComServerAsUser<IWSLCSessionFactory>(__uuidof(WSLCSessionFactory), userToken.get());
271 AddSessionProcessToJobObject(factory.get());
272
273 - const auto sessionSettings = CreateSessionSettings(sessionId, creatorPid, Settings, resolvedDisplayName.c_str());
273 + const auto sessionSettings = CreateSessionSettings(sessionId, callerFileName.c_str(), Settings, resolvedDisplayName.c_str());
274 wil::com_ptr<IWSLCSession> session;
275 wil::com_ptr<IWSLCSessionReference> serviceRef;
276 THROW_IF_FAILED(factory->CreateSession(&sessionSettings, vm.Get(), notifier.Get(), WarningCallback, &session, &serviceRef));
@@ -415,11 +415,11 @@ void WSLCSessionManagerImpl::EnterSession(
415 }
416
417 WSLCSessionInitSettings WSLCSessionManagerImpl::CreateSessionSettings(
418 - _In_ ULONG SessionId, _In_ DWORD CreatorPid, _In_ const WSLCSessionSettings* Settings, _In_ LPCWSTR ResolvedDisplayName)
418 + _In_ ULONG SessionId, _In_ LPCWSTR CreatorProcessName, _In_ const WSLCSessionSettings* Settings, _In_ LPCWSTR ResolvedDisplayName)
419 {
420 WSLCSessionInitSettings sessionSettings{};
421 sessionSettings.SessionId = SessionId;
422 - sessionSettings.CreatorPid = CreatorPid;
422 + sessionSettings.CreatorProcessName = CreatorProcessName;
423 sessionSettings.DisplayName = ResolvedDisplayName;
424 sessionSettings.StoragePath = Settings->StoragePath;
425 sessionSettings.MaximumStorageSizeMb = Settings->MaximumStorageSizeMb;
src/windows/service/exe/WSLCSessionManager.h
+1 -1
@@ -165,7 +165,7 @@ private:
165
166 void AddSessionProcessToJobObject(_In_ IWSLCSessionFactory* Factory);
167 WSLCSessionInitSettings CreateSessionSettings(
168 - _In_ ULONG SessionId, _In_ DWORD CreatorPid, _In_ const WSLCSessionSettings* Settings, _In_ LPCWSTR ResolvedDisplayName);
168 + _In_ ULONG SessionId, _In_ LPCWSTR CreatorProcessName, _In_ const WSLCSessionSettings* Settings, _In_ LPCWSTR ResolvedDisplayName);
169 void EnsureJobObjectCreated();
170 static CallingProcessTokenInfo GetCallingProcessTokenInfo();
171 static HRESULT CheckTokenAccess(const SessionEntry& Entry, const CallingProcessTokenInfo& TokenInfo);
src/windows/service/inc/wslc.idl
+1 -1
@@ -713,7 +713,7 @@ typedef enum _WSLCSessionState
713 typedef struct _WSLCSessionInitSettings
714 {
715 ULONG SessionId;
716 - ULONG CreatorPid;
716 + [unique] LPCWSTR CreatorProcessName;
717 LPCWSTR DisplayName;
718 LPCWSTR StoragePath;
719 WSLCSessionStorageFlags StorageFlags;
src/windows/wslcsession/WSLCSession.cpp
+26 -14
@@ -273,6 +273,7 @@ try
273 // N.B. No locking is required because Initialize() is always called before the session is returned to the caller.
274 m_id = Settings->SessionId;
275 m_displayName = Settings->DisplayName ? Settings->DisplayName : L"";
276 + m_creatorProcessName = Settings->CreatorProcessName ? Settings->CreatorProcessName : L"";
277 m_featureFlags = Settings->FeatureFlags;
278 m_pluginNotifier = PluginNotifier;
279
@@ -283,7 +284,7 @@ try
284 "SessionInitialized",
285 TraceLoggingValue(m_id, "SessionId"),
286 TraceLoggingValue(m_displayName.c_str(), "DisplayName"),
286 - TraceLoggingValue(Settings->CreatorPid, "CreatorPid"));
287 + TraceLoggingValue(m_creatorProcessName.c_str(), "CreatorProcess"));
288
289 // Create the VM.
290 m_virtualMachine.emplace(Vm, Settings, m_sessionTerminatingEvent.get());
@@ -1669,17 +1670,33 @@ HRESULT WSLCSession::CreateContainer(const WSLCContainerOptions* containerOption
1670 try
1671 {
1672 WSLCExecutionContext context(this, WarningCallback);
1673 + THROW_HR_IF_NULL(E_POINTER, containerOptions);
1674 + THROW_HR_IF_NULL(E_POINTER, Container);
1675 + THROW_HR_IF(E_POINTER, containerOptions->Image == nullptr);
1676
1673 - RETURN_HR_IF_NULL(E_POINTER, containerOptions);
1677 + auto lock = m_lock.lock_shared();
1678
1675 - // Validate that Image is not null.
1676 - RETURN_HR_IF(E_INVALIDARG, containerOptions->Image == nullptr);
1679 + auto result = wil::ResultFromException([&]() { CreateContainerImpl(containerOptions, Container); });
1680
1678 - auto lock = m_lock.lock_shared();
1681 + // This telemetry event is used to keep track of the container creation failure rate and surface unexpected errors.
1682 + WSL_LOG_TELEMETRY(
1683 + "WSLCCreateContainer",
1684 + PDT_ProductAndServicePerformance,
1685 + TraceLoggingKeyword(MICROSOFT_KEYWORD_CRITICAL_DATA),
1686 + TraceLoggingValue(result, "Result"),
1687 + TraceLoggingValue(containerOptions->Image, "Image"),
1688 + TraceLoggingValue(m_displayName.c_str(), "SessionName"),
1689 + TraceLoggingValue(m_creatorProcessName.c_str(), "CreatorProcess"));
1690 +
1691 + return result;
1692 +}
1693 +CATCH_RETURN();
1694
1680 - RETURN_HR_IF(HRESULT_FROM_WIN32(ERROR_INVALID_STATE), !m_virtualMachine);
1681 - RETURN_HR_IF(HRESULT_FROM_WIN32(ERROR_INVALID_STATE), !m_eventTracker);
1682 - RETURN_HR_IF(HRESULT_FROM_WIN32(ERROR_INVALID_STATE), !m_dockerClient);
1695 +void WSLCSession::CreateContainerImpl(const WSLCContainerOptions* containerOptions, IWSLCContainer** Container)
1696 +{
1697 + THROW_HR_IF(HRESULT_FROM_WIN32(ERROR_INVALID_STATE), !m_virtualMachine);
1698 + THROW_HR_IF(HRESULT_FROM_WIN32(ERROR_INVALID_STATE), !m_eventTracker);
1699 + THROW_HR_IF(HRESULT_FROM_WIN32(ERROR_INVALID_STATE), !m_dockerClient);
1700
1701 // Validate that name & images are valid.
1702 if (containerOptions->Name != nullptr && containerOptions->Name[0] != '\0')
@@ -1687,9 +1704,7 @@ try
1704 ValidateName(containerOptions->Name, WSLC_MAX_CONTAINER_NAME_LENGTH);
1705 }
1706
1690 - RETURN_HR_IF(E_INVALIDARG, strlen(containerOptions->Image) > WSLC_MAX_IMAGE_NAME_LENGTH);
1691 -
1692 - // TODO: Log entrance into the function.
1707 + THROW_HR_IF(E_INVALIDARG, strlen(containerOptions->Image) > WSLC_MAX_IMAGE_NAME_LENGTH);
1708
1709 try
1710 {
@@ -1741,8 +1756,6 @@ try
1756 WI_ASSERT(inserted);
1757
1758 it->second->CopyTo(Container);
1744 -
1745 - return S_OK;
1759 }
1760 catch (const DockerHTTPException& e)
1761 {
@@ -1757,7 +1770,6 @@ try
1770 THROW_HR_WITH_USER_ERROR(E_FAIL, errorMessage);
1771 }
1772 }
1760 -CATCH_RETURN();
1773
1774 HRESULT WSLCSession::OpenContainer(LPCSTR Id, IWSLCContainer** Container)
1775 try
src/windows/wslcsession/WSLCSession.h
+5
@@ -202,6 +202,10 @@ private:
202
203 __requires_lock_held(m_userHandlesLock) void CancelUserHandleIO();
204 __requires_lock_held(m_userCOMCallbacksLock) void CancelUserCOMCallbacks();
205 +
206 + _Requires_shared_lock_held_(m_lock)
207 + void CreateContainerImpl(const WSLCContainerOptions* Options, IWSLCContainer** Container);
208 +
209 void ConfigureStorage(const WSLCSessionInitSettings& Settings, PSID UserSid);
210 void Ext4Format(const std::string& Device);
211 _Requires_shared_lock_held_(m_lock)
@@ -235,6 +239,7 @@ private:
239 std::optional<DockerEventTracker> m_eventTracker;
240 wil::unique_event m_dockerdReadyEvent{wil::EventOptions::ManualReset};
241 std::wstring m_displayName;
242 + std::wstring m_creatorProcessName;
243 std::filesystem::path m_storageVhdPath;
244 std::filesystem::path m_swapVhdPath;
245
test/windows/WSLCTests.cpp
+1 -1
@@ -5436,7 +5436,7 @@ class WSLCTests
5436
5437 wil::com_ptr<IWSLCContainer> container;
5438 auto hr = m_defaultSession->CreateContainer(&options, nullptr, &container);
5439 - VERIFY_ARE_EQUAL(hr, E_INVALIDARG);
5439 + VERIFY_ARE_EQUAL(hr, E_POINTER);
5440 }
5441
5442 // Test null container name