@samitouri / QOSAMI-WSL / commits / 3b944063

Add --timestamps, --since, and --until flags to wslc container logs (#40645)

* Add --timestamps, --since, and --until flags to wslc container logs Wire up the existing WSLCLogsFlagsTimestamps flag and Since/Until parameters from the IWSLCContainer::Logs COM interface to the CLI. Previously these were hardcoded to 0/disabled despite the backend already supporting them. Changes: - Add Timestamps (flag, -t), Since (value), Until (value) argument types - Add ULONGLONG validation for --since and --until - Register new args on the container logs command - Pass timestamps flag and since/until values through to the COM call - Add localization strings with {Locked} comments for the new flags - Add 8 command-line parsing unit test cases - Add 6 end-to-end test methods covering timestamps, since, until, combined usage, and short flag (-t) Usage: wslc container logs --timestamps mycontainer wslc container logs --since 1700000000 mycontainer wslc container logs --until 1700001000 mycontainer wslc container logs -t -f --since 0 --tail 50 mycontainer Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add localization placeholders for new log flag strings Add WSLCCLI_TimestampsArgDescription, WSLCCLI_SinceArgDescription, and WSLCCLI_UntilArgDescription to all 21 non-en-US locale files with English placeholder values. These will be translated by the localization team. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Pooja Trivedi <trivedipooja@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Pooja Trivedi committed May 28, 2026 at 10:16 UTC 3b944063054e6e0bffb3ad86c60b91c5c0d4dc9d
30 files changed +349 -4
localization/strings/cs-CZ/Resources.resw
+9
@@ -2826,6 +2826,15 @@ Při prvním spuštění vytvoří soubor se všemi nastaveními okomentovanými
2826 <data name="WSLCCLI_TailArgDescription" xml:space="preserve">
2827 <value>Počet řádků, které se mají zobrazit od konce protokolů</value>
2828 </data>
2829 + <data name="WSLCCLI_TimestampsArgDescription" xml:space="preserve">
2830 + <value>Show timestamps in log output</value>
2831 + </data>
2832 + <data name="WSLCCLI_SinceArgDescription" xml:space="preserve">
2833 + <value>Show logs since timestamp (e.g. unix epoch seconds)</value>
2834 + </data>
2835 + <data name="WSLCCLI_UntilArgDescription" xml:space="preserve">
2836 + <value>Show logs before timestamp (e.g. unix epoch seconds)</value>
2837 + </data>
2838 <data name="WSLCCLI_TargetArgDescription" xml:space="preserve">
2839 <value>Nový odkaz na obrázek ve formátu image-name[:tag]</value>
2840 </data>
localization/strings/da-DK/Resources.resw
+9
@@ -2826,6 +2826,15 @@ Ved første kørsel oprettes filen med alle indstillinger kommenteret som standa
2826 <data name="WSLCCLI_TailArgDescription" xml:space="preserve">
2827 <value>Antal linjer, der skal vises fra slutningen af logfilerne</value>
2828 </data>
2829 + <data name="WSLCCLI_TimestampsArgDescription" xml:space="preserve">
2830 + <value>Show timestamps in log output</value>
2831 + </data>
2832 + <data name="WSLCCLI_SinceArgDescription" xml:space="preserve">
2833 + <value>Show logs since timestamp (e.g. unix epoch seconds)</value>
2834 + </data>
2835 + <data name="WSLCCLI_UntilArgDescription" xml:space="preserve">
2836 + <value>Show logs before timestamp (e.g. unix epoch seconds)</value>
2837 + </data>
2838 <data name="WSLCCLI_TargetArgDescription" xml:space="preserve">
2839 <value>Ny billedreference i formatet image-name[:tag]</value>
2840 </data>
localization/strings/de-DE/Resources.resw
+9
@@ -2832,6 +2832,15 @@ Erstellt bei der ersten Ausführung die Datei mit allen Einstellungen, die stand
2832 <data name="WSLCCLI_TailArgDescription" xml:space="preserve">
2833 <value>Anzahl der Zeilen, die vom Ende der Protokolle angezeigt werden sollen</value>
2834 </data>
2835 + <data name="WSLCCLI_TimestampsArgDescription" xml:space="preserve">
2836 + <value>Show timestamps in log output</value>
2837 + </data>
2838 + <data name="WSLCCLI_SinceArgDescription" xml:space="preserve">
2839 + <value>Show logs since timestamp (e.g. unix epoch seconds)</value>
2840 + </data>
2841 + <data name="WSLCCLI_UntilArgDescription" xml:space="preserve">
2842 + <value>Show logs before timestamp (e.g. unix epoch seconds)</value>
2843 + </data>
2844 <data name="WSLCCLI_TargetArgDescription" xml:space="preserve">
2845 <value>Neue Bildreferenz im Format image-name[:tag]</value>
2846 </data>
localization/strings/en-GB/Resources.resw
+9
@@ -2826,6 +2826,15 @@ On first run, creates the file with all settings commented out at their defaults
2826 <data name="WSLCCLI_TailArgDescription" xml:space="preserve">
2827 <value>Number of lines to show from the end of the logs</value>
2828 </data>
2829 + <data name="WSLCCLI_TimestampsArgDescription" xml:space="preserve">
2830 + <value>Show timestamps in log output</value>
2831 + </data>
2832 + <data name="WSLCCLI_SinceArgDescription" xml:space="preserve">
2833 + <value>Show logs since timestamp (e.g. unix epoch seconds)</value>
2834 + </data>
2835 + <data name="WSLCCLI_UntilArgDescription" xml:space="preserve">
2836 + <value>Show logs before timestamp (e.g. unix epoch seconds)</value>
2837 + </data>
2838 <data name="WSLCCLI_TargetArgDescription" xml:space="preserve">
2839 <value>New image reference in the image-name[:tag] format</value>
2840 </data>
localization/strings/en-US/Resources.resw
+9
@@ -2834,6 +2834,15 @@ On first run, creates the file with all settings commented out at their defaults
2834 <data name="WSLCCLI_TailArgDescription" xml:space="preserve">
2835 <value>Number of lines to show from the end of the logs</value>
2836 </data>
2837 + <data name="WSLCCLI_TimestampsArgDescription" xml:space="preserve">
2838 + <value>Show timestamps in log output</value>
2839 + </data>
2840 + <data name="WSLCCLI_SinceArgDescription" xml:space="preserve">
2841 + <value>Show logs since timestamp (e.g. unix epoch seconds)</value>
2842 + </data>
2843 + <data name="WSLCCLI_UntilArgDescription" xml:space="preserve">
2844 + <value>Show logs before timestamp (e.g. unix epoch seconds)</value>
2845 + </data>
2846 <data name="WSLCCLI_TargetArgDescription" xml:space="preserve">
2847 <value>New image reference in the image-name[:tag] format</value>
2848 </data>
localization/strings/es-ES/Resources.resw
+9
@@ -2832,6 +2832,15 @@ En la primera ejecución, crea el archivo con todas las configuraciones comentad
2832 <data name="WSLCCLI_TailArgDescription" xml:space="preserve">
2833 <value>Número de líneas que se mostrarán desde el final de los registros</value>
2834 </data>
2835 + <data name="WSLCCLI_TimestampsArgDescription" xml:space="preserve">
2836 + <value>Show timestamps in log output</value>
2837 + </data>
2838 + <data name="WSLCCLI_SinceArgDescription" xml:space="preserve">
2839 + <value>Show logs since timestamp (e.g. unix epoch seconds)</value>
2840 + </data>
2841 + <data name="WSLCCLI_UntilArgDescription" xml:space="preserve">
2842 + <value>Show logs before timestamp (e.g. unix epoch seconds)</value>
2843 + </data>
2844 <data name="WSLCCLI_TargetArgDescription" xml:space="preserve">
2845 <value>Nueva referencia de imagen en formato image-name[:tag]</value>
2846 </data>
localization/strings/fi-FI/Resources.resw
+9
@@ -2826,6 +2826,15 @@ Ensimmäisellä käynnistyskerralla luo tiedoston, jossa kaikki asetukset on kom
2826 <data name="WSLCCLI_TailArgDescription" xml:space="preserve">
2827 <value>Lokien lopusta näytettävien rivien määrä</value>
2828 </data>
2829 + <data name="WSLCCLI_TimestampsArgDescription" xml:space="preserve">
2830 + <value>Show timestamps in log output</value>
2831 + </data>
2832 + <data name="WSLCCLI_SinceArgDescription" xml:space="preserve">
2833 + <value>Show logs since timestamp (e.g. unix epoch seconds)</value>
2834 + </data>
2835 + <data name="WSLCCLI_UntilArgDescription" xml:space="preserve">
2836 + <value>Show logs before timestamp (e.g. unix epoch seconds)</value>
2837 + </data>
2838 <data name="WSLCCLI_TargetArgDescription" xml:space="preserve">
2839 <value>Uusi kuvaviittaus muodossa kuva-nimi[:tag]</value>
2840 </data>
localization/strings/fr-FR/Resources.resw
+9
@@ -2833,6 +2833,15 @@ Lors de la première exécution, crée le fichier avec tous les paramètres comm
2833 <data name="WSLCCLI_TailArgDescription" xml:space="preserve">
2834 <value>Nombre de lignes à afficher à partir de la fin des journaux</value>
2835 </data>
2836 + <data name="WSLCCLI_TimestampsArgDescription" xml:space="preserve">
2837 + <value>Show timestamps in log output</value>
2838 + </data>
2839 + <data name="WSLCCLI_SinceArgDescription" xml:space="preserve">
2840 + <value>Show logs since timestamp (e.g. unix epoch seconds)</value>
2841 + </data>
2842 + <data name="WSLCCLI_UntilArgDescription" xml:space="preserve">
2843 + <value>Show logs before timestamp (e.g. unix epoch seconds)</value>
2844 + </data>
2845 <data name="WSLCCLI_TargetArgDescription" xml:space="preserve">
2846 <value>Nouvelle référence d’image au format image-name[:tag]</value>
2847 </data>
localization/strings/hu-HU/Resources.resw
+9
@@ -2826,6 +2826,15 @@ Első futtatáskor a program létrehozza a fájlt, amelyben az összes beállít
2826 <data name="WSLCCLI_TailArgDescription" xml:space="preserve">
2827 <value>A naplók végéről megjelenítendő sorok száma</value>
2828 </data>
2829 + <data name="WSLCCLI_TimestampsArgDescription" xml:space="preserve">
2830 + <value>Show timestamps in log output</value>
2831 + </data>
2832 + <data name="WSLCCLI_SinceArgDescription" xml:space="preserve">
2833 + <value>Show logs since timestamp (e.g. unix epoch seconds)</value>
2834 + </data>
2835 + <data name="WSLCCLI_UntilArgDescription" xml:space="preserve">
2836 + <value>Show logs before timestamp (e.g. unix epoch seconds)</value>
2837 + </data>
2838 <data name="WSLCCLI_TargetArgDescription" xml:space="preserve">
2839 <value>Új képhivatkozás képnév[:címke] formátumban</value>
2840 </data>
localization/strings/it-IT/Resources.resw
+9
@@ -2832,6 +2832,15 @@ Alla prima esecuzione crea il file con tutte le impostazioni commentate come pre
2832 <data name="WSLCCLI_TailArgDescription" xml:space="preserve">
2833 <value>Numero di righe da visualizzare dalla fine dei log</value>
2834 </data>
2835 + <data name="WSLCCLI_TimestampsArgDescription" xml:space="preserve">
2836 + <value>Show timestamps in log output</value>
2837 + </data>
2838 + <data name="WSLCCLI_SinceArgDescription" xml:space="preserve">
2839 + <value>Show logs since timestamp (e.g. unix epoch seconds)</value>
2840 + </data>
2841 + <data name="WSLCCLI_UntilArgDescription" xml:space="preserve">
2842 + <value>Show logs before timestamp (e.g. unix epoch seconds)</value>
2843 + </data>
2844 <data name="WSLCCLI_TargetArgDescription" xml:space="preserve">
2845 <value>Nuovo riferimento immagine nel formato nome-immagine[:tag]</value>
2846 </data>
localization/strings/ja-JP/Resources.resw
+9
@@ -2832,6 +2832,15 @@ VS Code 自体のコマンド パレットから、より多くの VS Code リ
2832 <data name="WSLCCLI_TailArgDescription" xml:space="preserve">
2833 <value>ログの末尾から表示する行数</value>
2834 </data>
2835 + <data name="WSLCCLI_TimestampsArgDescription" xml:space="preserve">
2836 + <value>Show timestamps in log output</value>
2837 + </data>
2838 + <data name="WSLCCLI_SinceArgDescription" xml:space="preserve">
2839 + <value>Show logs since timestamp (e.g. unix epoch seconds)</value>
2840 + </data>
2841 + <data name="WSLCCLI_UntilArgDescription" xml:space="preserve">
2842 + <value>Show logs before timestamp (e.g. unix epoch seconds)</value>
2843 + </data>
2844 <data name="WSLCCLI_TargetArgDescription" xml:space="preserve">
2845 <value>image-name[:tag] 形式の新しいイメージ参照</value>
2846 </data>
localization/strings/ko-KR/Resources.resw
+9
@@ -2832,6 +2832,15 @@ VS Code 자체 내의 명령 팔레트를 통해 더 많은 VS Code 원격 옵
2832 <data name="WSLCCLI_TailArgDescription" xml:space="preserve">
2833 <value>로그의 끝에서 표시할 줄 수</value>
2834 </data>
2835 + <data name="WSLCCLI_TimestampsArgDescription" xml:space="preserve">
2836 + <value>Show timestamps in log output</value>
2837 + </data>
2838 + <data name="WSLCCLI_SinceArgDescription" xml:space="preserve">
2839 + <value>Show logs since timestamp (e.g. unix epoch seconds)</value>
2840 + </data>
2841 + <data name="WSLCCLI_UntilArgDescription" xml:space="preserve">
2842 + <value>Show logs before timestamp (e.g. unix epoch seconds)</value>
2843 + </data>
2844 <data name="WSLCCLI_TargetArgDescription" xml:space="preserve">
2845 <value>image-name[:tag] 형식의 새 이미지 참조</value>
2846 </data>
localization/strings/nb-NO/Resources.resw
+9
@@ -2826,6 +2826,15 @@ Ved første kjøring opprettes filen med alle innstillinger kommentert ut som st
2826 <data name="WSLCCLI_TailArgDescription" xml:space="preserve">
2827 <value>Antall linjer som skal vises fra slutten av loggene</value>
2828 </data>
2829 + <data name="WSLCCLI_TimestampsArgDescription" xml:space="preserve">
2830 + <value>Show timestamps in log output</value>
2831 + </data>
2832 + <data name="WSLCCLI_SinceArgDescription" xml:space="preserve">
2833 + <value>Show logs since timestamp (e.g. unix epoch seconds)</value>
2834 + </data>
2835 + <data name="WSLCCLI_UntilArgDescription" xml:space="preserve">
2836 + <value>Show logs before timestamp (e.g. unix epoch seconds)</value>
2837 + </data>
2838 <data name="WSLCCLI_TargetArgDescription" xml:space="preserve">
2839 <value>Ny bildereferanse i bilde-navn[:merke]-format</value>
2840 </data>
localization/strings/nl-NL/Resources.resw
+9
@@ -2826,6 +2826,15 @@ Bij de eerste uitvoering wordt het bestand aangemaakt met alle instellingen geco
2826 <data name="WSLCCLI_TailArgDescription" xml:space="preserve">
2827 <value>Aantal regels dat moet worden weergegeven vanaf het einde van de logboeken</value>
2828 </data>
2829 + <data name="WSLCCLI_TimestampsArgDescription" xml:space="preserve">
2830 + <value>Show timestamps in log output</value>
2831 + </data>
2832 + <data name="WSLCCLI_SinceArgDescription" xml:space="preserve">
2833 + <value>Show logs since timestamp (e.g. unix epoch seconds)</value>
2834 + </data>
2835 + <data name="WSLCCLI_UntilArgDescription" xml:space="preserve">
2836 + <value>Show logs before timestamp (e.g. unix epoch seconds)</value>
2837 + </data>
2838 <data name="WSLCCLI_TargetArgDescription" xml:space="preserve">
2839 <value>Nieuwe afbeeldingsverwijzing in de indeling image-name[:tag]</value>
2840 </data>
localization/strings/pl-PL/Resources.resw
+9
@@ -2826,6 +2826,15 @@ Przy pierwszym uruchomieniu tworzy plik ze wszystkimi ustawieniami ujętymi w ko
2826 <data name="WSLCCLI_TailArgDescription" xml:space="preserve">
2827 <value>Liczba wierszy do wyświetlenia od końca dzienników</value>
2828 </data>
2829 + <data name="WSLCCLI_TimestampsArgDescription" xml:space="preserve">
2830 + <value>Show timestamps in log output</value>
2831 + </data>
2832 + <data name="WSLCCLI_SinceArgDescription" xml:space="preserve">
2833 + <value>Show logs since timestamp (e.g. unix epoch seconds)</value>
2834 + </data>
2835 + <data name="WSLCCLI_UntilArgDescription" xml:space="preserve">
2836 + <value>Show logs before timestamp (e.g. unix epoch seconds)</value>
2837 + </data>
2838 <data name="WSLCCLI_TargetArgDescription" xml:space="preserve">
2839 <value>Nowe odwołanie do obrazu w formacie nazwa_obrazu[:tag]</value>
2840 </data>
localization/strings/pt-BR/Resources.resw
+9
@@ -2833,6 +2833,15 @@ Na primeira execução, cria o arquivo com todas as configurações comentadas n
2833 <data name="WSLCCLI_TailArgDescription" xml:space="preserve">
2834 <value>Número de linhas a serem mostradas a partir do final dos logs</value>
2835 </data>
2836 + <data name="WSLCCLI_TimestampsArgDescription" xml:space="preserve">
2837 + <value>Show timestamps in log output</value>
2838 + </data>
2839 + <data name="WSLCCLI_SinceArgDescription" xml:space="preserve">
2840 + <value>Show logs since timestamp (e.g. unix epoch seconds)</value>
2841 + </data>
2842 + <data name="WSLCCLI_UntilArgDescription" xml:space="preserve">
2843 + <value>Show logs before timestamp (e.g. unix epoch seconds)</value>
2844 + </data>
2845 <data name="WSLCCLI_TargetArgDescription" xml:space="preserve">
2846 <value>Nova referência de imagem no formato image-name[:tag]</value>
2847 </data>
localization/strings/pt-PT/Resources.resw
+9
@@ -2826,6 +2826,15 @@ Na primeira execução, cria o ficheiro com todas as definições comentadas nas
2826 <data name="WSLCCLI_TailArgDescription" xml:space="preserve">
2827 <value>Número de linhas a mostrar a partir do final dos registos</value>
2828 </data>
2829 + <data name="WSLCCLI_TimestampsArgDescription" xml:space="preserve">
2830 + <value>Show timestamps in log output</value>
2831 + </data>
2832 + <data name="WSLCCLI_SinceArgDescription" xml:space="preserve">
2833 + <value>Show logs since timestamp (e.g. unix epoch seconds)</value>
2834 + </data>
2835 + <data name="WSLCCLI_UntilArgDescription" xml:space="preserve">
2836 + <value>Show logs before timestamp (e.g. unix epoch seconds)</value>
2837 + </data>
2838 <data name="WSLCCLI_TargetArgDescription" xml:space="preserve">
2839 <value>Nova referência de imagem no formato image-name[:tag]</value>
2840 </data>
localization/strings/ru-RU/Resources.resw
+9
@@ -2833,6 +2833,15 @@ wsl.exe --manage &lt;DistributionName&gt; --set-sparse true --allow-unsafe</valu
2833 <data name="WSLCCLI_TailArgDescription" xml:space="preserve">
2834 <value>Число строк, отображаемых с конца журналов</value>
2835 </data>
2836 + <data name="WSLCCLI_TimestampsArgDescription" xml:space="preserve">
2837 + <value>Show timestamps in log output</value>
2838 + </data>
2839 + <data name="WSLCCLI_SinceArgDescription" xml:space="preserve">
2840 + <value>Show logs since timestamp (e.g. unix epoch seconds)</value>
2841 + </data>
2842 + <data name="WSLCCLI_UntilArgDescription" xml:space="preserve">
2843 + <value>Show logs before timestamp (e.g. unix epoch seconds)</value>
2844 + </data>
2845 <data name="WSLCCLI_TargetArgDescription" xml:space="preserve">
2846 <value>Новая ссылка на изображение в формате image-name[:tag]</value>
2847 </data>
localization/strings/sv-SE/Resources.resw
+9
@@ -2826,6 +2826,15 @@ Vid den första körningen skapas filen med alla inställningar kommenterade som
2826 <data name="WSLCCLI_TailArgDescription" xml:space="preserve">
2827 <value>Antal rader som visas från slutet av loggarna</value>
2828 </data>
2829 + <data name="WSLCCLI_TimestampsArgDescription" xml:space="preserve">
2830 + <value>Show timestamps in log output</value>
2831 + </data>
2832 + <data name="WSLCCLI_SinceArgDescription" xml:space="preserve">
2833 + <value>Show logs since timestamp (e.g. unix epoch seconds)</value>
2834 + </data>
2835 + <data name="WSLCCLI_UntilArgDescription" xml:space="preserve">
2836 + <value>Show logs before timestamp (e.g. unix epoch seconds)</value>
2837 + </data>
2838 <data name="WSLCCLI_TargetArgDescription" xml:space="preserve">
2839 <value>Ny bildreferens i formatet image-name[:tag]</value>
2840 </data>
localization/strings/tr-TR/Resources.resw
+9
@@ -2826,6 +2826,15 @@ Bu ürünle ilgili gizlilik bilgileri için lütfen https://aka.ms/privacy sayfa
2826 <data name="WSLCCLI_TailArgDescription" xml:space="preserve">
2827 <value>Günlüklerin sonundan itibaren gösterilecek satır sayısı</value>
2828 </data>
2829 + <data name="WSLCCLI_TimestampsArgDescription" xml:space="preserve">
2830 + <value>Show timestamps in log output</value>
2831 + </data>
2832 + <data name="WSLCCLI_SinceArgDescription" xml:space="preserve">
2833 + <value>Show logs since timestamp (e.g. unix epoch seconds)</value>
2834 + </data>
2835 + <data name="WSLCCLI_UntilArgDescription" xml:space="preserve">
2836 + <value>Show logs before timestamp (e.g. unix epoch seconds)</value>
2837 + </data>
2838 <data name="WSLCCLI_TargetArgDescription" xml:space="preserve">
2839 <value>image-name[:tag] biçiminde yeni resim referansı</value>
2840 </data>
localization/strings/zh-CN/Resources.resw
+9
@@ -2832,6 +2832,15 @@ wsl.exe --manage &lt;DistributionName&gt; --set-sparse true --allow-unsafe</valu
2832 <data name="WSLCCLI_TailArgDescription" xml:space="preserve">
2833 <value>从日志末尾显示的行数</value>
2834 </data>
2835 + <data name="WSLCCLI_TimestampsArgDescription" xml:space="preserve">
2836 + <value>Show timestamps in log output</value>
2837 + </data>
2838 + <data name="WSLCCLI_SinceArgDescription" xml:space="preserve">
2839 + <value>Show logs since timestamp (e.g. unix epoch seconds)</value>
2840 + </data>
2841 + <data name="WSLCCLI_UntilArgDescription" xml:space="preserve">
2842 + <value>Show logs before timestamp (e.g. unix epoch seconds)</value>
2843 + </data>
2844 <data name="WSLCCLI_TargetArgDescription" xml:space="preserve">
2845 <value>image-name[:tag] 格式的新图像引用</value>
2846 </data>
localization/strings/zh-TW/Resources.resw
+9
@@ -2832,6 +2832,15 @@ wsl.exe --manage &lt;DistributionName&gt; --set-sparse true --allow-unsafe</valu
2832 <data name="WSLCCLI_TailArgDescription" xml:space="preserve">
2833 <value>從記錄結尾所要顯示的行數</value>
2834 </data>
2835 + <data name="WSLCCLI_TimestampsArgDescription" xml:space="preserve">
2836 + <value>Show timestamps in log output</value>
2837 + </data>
2838 + <data name="WSLCCLI_SinceArgDescription" xml:space="preserve">
2839 + <value>Show logs since timestamp (e.g. unix epoch seconds)</value>
2840 + </data>
2841 + <data name="WSLCCLI_UntilArgDescription" xml:space="preserve">
2842 + <value>Show logs before timestamp (e.g. unix epoch seconds)</value>
2843 + </data>
2844 <data name="WSLCCLI_TargetArgDescription" xml:space="preserve">
2845 <value>影像名稱[:tag] 格式中的新影像參考</value>
2846 </data>
src/windows/wslc/arguments/ArgumentDefinitions.h
+3
@@ -55,6 +55,9 @@ _(EnvFile, "env-file", NO_ALIAS, Kind::Value, L
55 _(File, "file", L"f", Kind::Value, Localization::WSLCCLI_FileArgDescription()) \
56 _(Filter, "filter", L"f", Kind::Value, Localization::WSLCCLI_FilterArgDescription()) \
57 _(Follow, "follow", L"f", Kind::Flag, Localization::WSLCCLI_FollowArgDescription()) \
58 +_(Timestamps, "timestamps", L"t", Kind::Flag, Localization::WSLCCLI_TimestampsArgDescription()) \
59 +_(Since, "since", NO_ALIAS, Kind::Value, Localization::WSLCCLI_SinceArgDescription()) \
60 +_(Until, "until", NO_ALIAS, Kind::Value, Localization::WSLCCLI_UntilArgDescription()) \
61 _(Format, "format", NO_ALIAS, Kind::Value, Localization::WSLCCLI_FormatArgDescription()) \
62 _(ForwardArgs, "arguments", NO_ALIAS, Kind::Forward, Localization::WSLCCLI_ForwardArgsDescription()) \
63 _(Gpus, "gpus", NO_ALIAS, Kind::Value, Localization::WSLCCLI_GpusArgDescription()) \
src/windows/wslc/arguments/ArgumentValidation.cpp
+8
@@ -57,6 +57,14 @@ void Argument::Validate(const ArgMap& execArgs) const
57 validation::ValidateIntegerFromString<LONGLONG>(execArgs.GetAll<ArgType::Time>(), m_name);
58 break;
59
60 + case ArgType::Since:
61 + validation::ValidateIntegerFromString<ULONGLONG>(execArgs.GetAll<ArgType::Since>(), m_name);
62 + break;
63 +
64 + case ArgType::Until:
65 + validation::ValidateIntegerFromString<ULONGLONG>(execArgs.GetAll<ArgType::Until>(), m_name);
66 + break;
67 +
68 case ArgType::Last:
69 validation::ValidateIntegerFromString<int>(execArgs.GetAll<ArgType::Last>(), m_name);
70 break;
src/windows/wslc/commands/ContainerLogsCommand.cpp
+3
@@ -31,6 +31,9 @@ std::vector<Argument> ContainerLogsCommand::GetArguments() const
31 Argument::Create(ArgType::Session),
32 Argument::Create(ArgType::Follow),
33 Argument::Create(ArgType::Tail),
34 + Argument::Create(ArgType::Timestamps),
35 + Argument::Create(ArgType::Since),
36 + Argument::Create(ArgType::Until),
37 };
38 }
39
src/windows/wslc/services/ContainerService.cpp
+3 -2
@@ -509,7 +509,7 @@ InspectContainer ContainerService::Inspect(Session& session, const std::string&
509 return wsl::shared::FromJson<InspectContainer>(output.get());
510 }
511
512 -void ContainerService::Logs(Session& session, const std::string& id, bool follow, ULONGLONG tail)
512 +void ContainerService::Logs(Session& session, const std::string& id, bool follow, bool timestamps, ULONGLONG since, ULONGLONG until, ULONGLONG tail)
513 {
514 wil::com_ptr<IWSLCContainer> container;
515 THROW_IF_FAILED(session.Get()->OpenContainer(id.c_str(), &container));
@@ -518,8 +518,9 @@ void ContainerService::Logs(Session& session, const std::string& id, bool follow
518 COMOutputHandle stderrHandle;
519 WSLCLogsFlags flags = WSLCLogsFlagsNone;
520 WI_SetFlagIf(flags, WSLCLogsFlagsFollow, follow);
521 + WI_SetFlagIf(flags, WSLCLogsFlagsTimestamps, timestamps);
522
522 - THROW_IF_FAILED(container->Logs(flags, &stdoutHandle, &stderrHandle, 0, 0, tail));
523 + THROW_IF_FAILED(container->Logs(flags, &stdoutHandle, &stderrHandle, since, until, tail));
524
525 wsl::windows::common::io::MultiHandleWait io;
526 io.AddHandle(std::make_unique<wsl::windows::common::io::RelayHandle<wsl::windows::common::io::ReadHandle>>(
src/windows/wslc/services/ContainerService.h
+1 -1
@@ -35,7 +35,7 @@ struct ContainerService
35
36 static int Exec(models::Session& session, const std::string& id, models::ContainerOptions options);
37 static wsl::windows::common::wslc_schema::InspectContainer Inspect(models::Session& session, const std::string& id);
38 - static void Logs(models::Session& session, const std::string& id, bool follow, ULONGLONG tail = 0);
38 + static void Logs(models::Session& session, const std::string& id, bool follow, bool timestamps, ULONGLONG since, ULONGLONG until, ULONGLONG tail = 0);
39 static wsl::windows::common::docker_schema::ContainerStats Stats(models::Session& session, const std::string& id);
40 static models::PruneContainersResult Prune(models::Session& session);
41 };
src/windows/wslc/tasks/ContainerTasks.cpp
+14 -1
@@ -686,6 +686,7 @@ void ViewContainerLogs(CLIExecutionContext& context)
686 auto& session = context.Data.Get<Data::Session>();
687 auto containerId = context.Args.Get<ArgType::ContainerId>();
688 bool follow = context.Args.Contains(ArgType::Follow);
689 + bool timestamps = context.Args.Contains(ArgType::Timestamps);
690
691 ULONGLONG tail = 0;
692 if (context.Args.Contains(ArgType::Tail))
@@ -693,7 +694,19 @@ void ViewContainerLogs(CLIExecutionContext& context)
694 tail = validation::GetIntegerFromString<ULONGLONG>(context.Args.Get<ArgType::Tail>());
695 }
696
696 - ContainerService::Logs(session, WideToMultiByte(containerId), follow, tail);
697 + ULONGLONG since = 0;
698 + if (context.Args.Contains(ArgType::Since))
699 + {
700 + since = validation::GetIntegerFromString<ULONGLONG>(context.Args.Get<ArgType::Since>());
701 + }
702 +
703 + ULONGLONG until = 0;
704 + if (context.Args.Contains(ArgType::Until))
705 + {
706 + until = validation::GetIntegerFromString<ULONGLONG>(context.Args.Get<ArgType::Until>());
707 + }
708 +
709 + ContainerService::Logs(session, WideToMultiByte(containerId), follow, timestamps, since, until, tail);
710 }
711
712 void PruneContainers(CLIExecutionContext& context)
test/windows/wslc/CommandLineTestCases.h
+8
@@ -175,6 +175,14 @@ COMMAND_LINE_TEST_CASE(L"container logs -n abc cont1", L"logs", false)
175 COMMAND_LINE_TEST_CASE(L"container logs -n=abc cont1", L"logs", false)
176 COMMAND_LINE_TEST_CASE(L"container logs --tail", L"logs", false)
177 COMMAND_LINE_TEST_CASE(L"container logs -n", L"logs", false)
178 +COMMAND_LINE_TEST_CASE(L"container logs --timestamps cont1", L"logs", true)
179 +COMMAND_LINE_TEST_CASE(L"container logs -t cont1", L"logs", true)
180 +COMMAND_LINE_TEST_CASE(L"container logs --since 1700000000 cont1", L"logs", true)
181 +COMMAND_LINE_TEST_CASE(L"container logs --until 1700000000 cont1", L"logs", true)
182 +COMMAND_LINE_TEST_CASE(L"container logs --since 1700000000 --until 1700001000 cont1", L"logs", true)
183 +COMMAND_LINE_TEST_CASE(L"container logs --since abc cont1", L"logs", false)
184 +COMMAND_LINE_TEST_CASE(L"container logs --until abc cont1", L"logs", false)
185 +COMMAND_LINE_TEST_CASE(L"container logs --follow --timestamps --since 100 --tail 5 cont1", L"logs", true)
186
187 // Image command
188 COMMAND_LINE_TEST_CASE(L"image build C:\\context", L"build", true)
test/windows/wslc/e2e/WSLCE2EContainerLogsTests.cpp
+111
@@ -57,6 +57,117 @@ class WSLCE2EContainerLogsTests
57 result.Verify({.Stdout = L"line1\nline2\n", .Stderr = L"", .ExitCode = 0});
58 }
59
60 + WSLC_TEST_METHOD(WSLCE2E_Container_Logs_Timestamps)
61 + {
62 + // Run a container that outputs a line
63 + auto result =
64 + RunWslc(std::format(L"container run --name {} {} sh -c \"echo hello\"", WslcContainerName, DebianImage.NameAndTag()));
65 + result.Verify({.Stderr = L"", .ExitCode = 0});
66 +
67 + // Verify --timestamps adds timestamp prefix to log lines
68 + result = RunWslc(std::format(L"container logs --timestamps {}", WslcContainerName));
69 + result.Verify({.Stderr = L"", .ExitCode = 0});
70 +
71 + // Timestamps should be in RFC3339 format (e.g. "2024-01-01T00:00:00.000000000Z hello")
72 + // Verify output contains a timestamp-like prefix followed by the message
73 + VERIFY_IS_TRUE(result.StdoutContainsSubstring(L"hello"));
74 + auto lines = result.GetStdoutLines();
75 + VERIFY_IS_TRUE(!lines.empty());
76 + // A timestamp line should have at least a 'T' character (ISO 8601 separator)
77 + VERIFY_IS_TRUE(lines[0].find(L'T') != std::wstring::npos);
78 + }
79 +
80 + WSLC_TEST_METHOD(WSLCE2E_Container_Logs_TimestampsShortFlag)
81 + {
82 + // Run a container that outputs a line
83 + auto result =
84 + RunWslc(std::format(L"container run --name {} {} sh -c \"echo world\"", WslcContainerName, DebianImage.NameAndTag()));
85 + result.Verify({.Stderr = L"", .ExitCode = 0});
86 +
87 + // Verify -t (short for --timestamps) works the same way
88 + result = RunWslc(std::format(L"container logs -t {}", WslcContainerName));
89 + result.Verify({.Stderr = L"", .ExitCode = 0});
90 +
91 + VERIFY_IS_TRUE(result.StdoutContainsSubstring(L"world"));
92 + auto lines = result.GetStdoutLines();
93 + VERIFY_IS_TRUE(!lines.empty());
94 + VERIFY_IS_TRUE(lines[0].find(L'T') != std::wstring::npos);
95 + }
96 +
97 + WSLC_TEST_METHOD(WSLCE2E_Container_Logs_Since)
98 + {
99 + // Run a container that outputs a line
100 + auto result =
101 + RunWslc(std::format(L"container run --name {} {} sh -c \"echo before\"", WslcContainerName, DebianImage.NameAndTag()));
102 + result.Verify({.Stderr = L"", .ExitCode = 0});
103 +
104 + // Using --since 0 should return all logs (epoch start)
105 + result = RunWslc(std::format(L"container logs --since 0 {}", WslcContainerName));
106 + result.Verify({.Stderr = L"", .ExitCode = 0});
107 + VERIFY_IS_TRUE(result.StdoutContainsSubstring(L"before"));
108 +
109 + // Using --since with a far-future timestamp should return no logs
110 + result = RunWslc(std::format(L"container logs --since 9999999999 {}", WslcContainerName));
111 + result.Verify({.Stdout = L"", .Stderr = L"", .ExitCode = 0});
112 + }
113 +
114 + WSLC_TEST_METHOD(WSLCE2E_Container_Logs_Until)
115 + {
116 + // Run a container that outputs a line
117 + auto result =
118 + RunWslc(std::format(L"container run --name {} {} sh -c \"echo test_until\"", WslcContainerName, DebianImage.NameAndTag()));
119 + result.Verify({.Stderr = L"", .ExitCode = 0});
120 +
121 + // Using --until with a far-future timestamp should return all logs
122 + result = RunWslc(std::format(L"container logs --until 9999999999 {}", WslcContainerName));
123 + result.Verify({.Stderr = L"", .ExitCode = 0});
124 + VERIFY_IS_TRUE(result.StdoutContainsSubstring(L"test_until"));
125 +
126 + // Using --until 1 (epoch + 1 second) should return no logs since container was created much later
127 + result = RunWslc(std::format(L"container logs --until 1 {}", WslcContainerName));
128 + result.Verify({.Stdout = L"", .Stderr = L"", .ExitCode = 0});
129 + }
130 +
131 + WSLC_TEST_METHOD(WSLCE2E_Container_Logs_SinceAndUntilCombined)
132 + {
133 + // Run a container that outputs a line
134 + auto result =
135 + RunWslc(std::format(L"container run --name {} {} sh -c \"echo combined\"", WslcContainerName, DebianImage.NameAndTag()));
136 + result.Verify({.Stderr = L"", .ExitCode = 0});
137 +
138 + // Using --since 0 --until far-future should return all logs
139 + result = RunWslc(std::format(L"container logs --since 0 --until 9999999999 {}", WslcContainerName));
140 + result.Verify({.Stderr = L"", .ExitCode = 0});
141 + VERIFY_IS_TRUE(result.StdoutContainsSubstring(L"combined"));
142 +
143 + // Using --since far-future --until far-future should return no logs
144 + result = RunWslc(std::format(L"container logs --since 9999999999 --until 9999999999 {}", WslcContainerName));
145 + result.Verify({.Stdout = L"", .Stderr = L"", .ExitCode = 0});
146 + }
147 +
148 + WSLC_TEST_METHOD(WSLCE2E_Container_Logs_AllOptionsCombined)
149 + {
150 + // Run a container that outputs multiple lines
151 + auto result = RunWslc(std::format(
152 + L"container run --name {} {} sh -c \"echo a && echo b && echo c\"", WslcContainerName, DebianImage.NameAndTag()));
153 + result.Verify({.Stderr = L"", .ExitCode = 0});
154 +
155 + // Combine --timestamps --since 0 --tail 2
156 + result = RunWslc(std::format(L"container logs --timestamps --since 0 --tail 2 {}", WslcContainerName));
157 + result.Verify({.Stderr = L"", .ExitCode = 0});
158 +
159 + // Should have at most 2 lines (from --tail 2) and each should have a timestamp
160 + auto lines = result.GetStdoutLines();
161 + VERIFY_IS_TRUE(lines.size() <= 2);
162 + for (const auto& line : lines)
163 + {
164 + if (!line.empty())
165 + {
166 + VERIFY_IS_TRUE(line.find(L'T') != std::wstring::npos);
167 + }
168 + }
169 + }
170 +
171 private:
172 const std::wstring WslcContainerName = L"wslc-test-logs";
173 const TestImage& DebianImage = DebianTestImage();