訊息與日誌 (Messages and Logs)¶
一則訊息落在哪裡,決定了它能留多久、還有誰看得到,而這通常比它當時說了什麼更有用。快顯通知 (toast) 與頁尾屬於某一個瀏覽器,該瀏覽器下一次重新整理時它們就沒了;四份工作階段訊息清單與當天的日誌檔則由服務持有。挑對要讀的介面,是一個具體的問題與一個含糊的問題之間大半的差別。
訊息會落在哪裡¶
應用程式有好幾個放訊息的地方,而它們承載的東西並不相同。
- 快顯通知 — 右下角,停留幾秒鐘,然後消失。它是唯一會打斷操作的介面,也是唯一自己什麼都不保留的介面。
- 頁尾的最新一行,以及它背後的最近訊息清單 — 快顯通知在顯示之前就先被複製到這裡,所以這份清單就是快顯通知消失之後的去處。有兩類東西永遠不會到這裡來:既無訊息也無副標 (caption) 的快顯通知,以及刀具庫、主軸能力編輯器與各個控制器面板所發出的通知——它們只顯示一次,不予保留。少數狀態行走的是相反的方向——直接寫到這裡,從來不會以快顯通知出現。
- 頁尾的工作階段條 — 橫條的中段,執行產出了東西之後才畫出來,在那之前是空的。
- 頁尾的背景作業區 — 右端,只在「檔案」選單的某項操作進行中時才畫出——關閉專案也算——寫出該操作與它正在處理的路徑。
- 「工作階段訊息」面板 — 在執行頁上,由服務保存的四份清單。
- 日誌檢視器 — 在「說明」選單上,服務自己為當天寫下的檔案。
頁尾只做摘要,不做保存。執行所回報的每一樣東西也都會進入面板四份清單之一,而面板才是它們留下來的地方。
專案載入引發的訊息¶
開啟或重新讀取專案時,可能會回報其中的缺口——某個被參照的 STL 不在磁碟上、專案以參照指名的某個隨附檔案讀不到,或者某個執行器 (runner) 組態的內容載入不了,讓專案改用預設的那一個。這些都不會讓載入失敗。 專案照樣開啟,需要那個缺少 STL 的物體只是以沒有幾何的樣子開起來而已,動作仍然回報成功。那則訊息是唯一說出實情的東西。只有專案檔本身不一樣:讀不到的專案檔會讓動作失敗,之後沒有任何專案開著——開啟中的專案在讀檔之前就已經釋放了。
以參照指名的隨附檔案——機台、主軸能力、冷卻條件、材料、切削參數組、NC 執行器——若缺少、被鎖住或格式錯誤,會回報 XmlSource-Read--Failed,每個參照一則,並寫出解析後的路徑。它原本承載的物件保持空白,而不是換成預設值,它的面板會以紅字寫出檔名——參照的檔案讀不到:
有一個相鄰的情況走的是別的路。原始幾何所指名、卻不存在的網格幾何 .wct 檔,在這裡完全不會引發任何訊息,因為載入從不開啟它;關於它的第一句話要等到網格幾何下一次被需要時才出現,而那則訊息屬於執行,所以它像其他訊息一樣落在「工作階段訊息」面板。
接著這些訊息走的是一條自己的路,而這條路有一個後果,在倚賴它之前值得先知道。專案檔操作是在任何工作階段之外執行的,所以面板的四份清單——它們屬於服務,是執行所回報的一切留下來的地方——永遠看不到這些訊息。取而代之的是:前五則錯誤與警告以快顯通知顯示,超過的部分直接進入頁尾的最近訊息清單,再由另一則快顯通知說明有多少則沒有拿到自己的通知。比警告更輕微的訊息則完全不會在視窗裡浮現。
於是視窗裡唯一的一份副本就落在頁尾的最近訊息清單,而那份清單是瀏覽器的:重新整理就會把它清空。所以,當專案開啟時缺了東西,就當場把訊息讀一讀,或者去讀服務日誌——不論如何它都有這些訊息。「工作階段訊息」面板則不會有。
頁尾¶
左側區域是這個瀏覽器自己的紀錄,不屬於別的任何東西。最新一行背後的清單是最新的在前,上限一百則,由它的清除按鈕清空——最新一行也會跟著回到就緒——重新整理也會清空,而且它不會被寫到任何地方——關掉分頁之後什麼都不會留下。每一則都保留它發出時的措辭,所以切換語言會讓這份清單變成兩種語言的混合,而面板的清單則立刻重新呈現。框架頁描述這些區域本身:見應用程式視窗。
沒有任何東西會標示這份清單裡有新東西。 那個按鈕沒有標記也沒有圓點,這是刻意的,因為快顯通知已經吸引過一次注意。後果正是本頁存在所要防止的失誤:一則從未以快顯通知出現的訊息,或者它那幾秒鐘在視窗被別的東西遮住時就過去了的訊息,在有人親手打開那個選單之前都是看不見的。在某個動作看起來什麼也沒做之後把它打開,是最便宜的檢查方式。
中段的工作階段條則正好相反——它由服務推送,所以每個連線中的瀏覽器看到的是同樣的執行活動,而每個瀏覽器在它背後各自保留一小圈最近的項目。執行結束後,它最後顯示的內容仍留在橫條上;清空這一圈並把整條拿掉的是專案變更。游標行帶著 Sn 與它所在的語句索引;訊息行帶著訊息自己提供的錨點。有兩個限制值得知道:這條映照的是四份清單中三份裡的最新訊息——「NC 操作」的東西不會到達這裡——而且它是抽樣的,不是逐筆記錄的。沒有可調的更新間隔:服務送出最新的一則訊息,而在那次送出還在前往各瀏覽器的路上時,後面陸續到達的訊息它只留最新的一則,所以落在那個時間窗內的訊息在送出之前就被取代,永遠不會出現在這條上。快速執行時,游標行也以同樣的方式被稀釋。服務上的清單則一筆都不丟。
工作階段訊息面板¶
這個面板位於執行頁的中間欄、3D 渲染畫布之下。它的標題列寫著工作階段訊息,面板收合時仍然可見,所以一條帶著這個名稱的灰色橫條,就是關著的面板。
整個欄可以被關掉,而頁面上沒有任何東西會說明這一點。 選單列右端的欄快速切換鈕之中,有一個的工具提示讀作切換執行畫布與訊息欄;把它關掉之後,面板與它的標題列都不會畫出來,頁面看起來只是少了幾個部分。這個選擇屬於瀏覽器,重新整理之後仍然保留。面板本身展開或收合的狀態則不是:它由服務保存,因此之後打開這一頁的每個瀏覽器都看到相同的狀態。
四個分頁,各是一份獨立的清單:
| 分頁 | 承載的內容 |
|---|---|
| 工作階段 (Shell) | 工作階段自身的生命週期與流程進度——什麼開始了、什麼完成了、什麼被拒絕了。在工作階段之外它是空的,因為這份清單是隨工作階段建立的。 |
| NC 診斷 | 播放程式時 NC 管線所回報的內容。 |
| 工步診斷 | 針對加工步、而非程式文字所回報的內容。 |
| NC 操作 | 把播放過的程式轉換成 NC、或對其進行優化時所回報的內容。每一次這樣的執行都會先清空清單,再重新填入。 |
分頁只有在它的清單裡有東西時才顯示一個小小的計數標記,所以一份空的清單,看起來就是名稱旁邊什麼都沒有的分頁。
訊息帶有位置時,該列會在一個等寬字的錨點欄裡顯示它:工步診斷指名它的工步,有單節 (block) 時也指名單節;NC 診斷指名該單節在執行順序中的位置,而當診斷帶有來源檔與行號時,它的工具提示也會加上這兩者。並非每則 NC 診斷都有錨點——針對管線本身而非某個特定單節的抱怨沒有錨點可顯示,而「工作階段」分頁的訊息從來沒有錨點。連續一串相同的訊息送達時就已經摺疊成單獨一列,並帶著倍數標記。一行之外還有更多內容的列帶著一個展開箭號;點一下會打開訊息隨附的內容,並附有它自己的複製按鈕。
每個分頁各自獨立篩選:一個嚴重性清單、一個類別清單、一個篩選文字…方框,以及一個重置。該工具列右側的標記顯示以斜線隔開的兩個數字,它們數的是不同的東西——左邊是目前顯示的列數,右邊是原始訊息數,所以光是摺疊就會讓兩者不同;而在長時間的工作階段裡,左邊的數字停在最近的一千列,右邊則繼續累計。那個標記同時也是分頁的連線指示器:只有在該清單背後的連線通著時才以綠色描邊,它的工具提示會指出狀態。匯出會把該分頁篩選後的列寫成一個 CSV 檔。
兩個控制項都叫「重置」,只有一個標著這個名字(重要)
這個畫面上有兩個不同的控制項都叫重置,而只有其中一個標著這個字。標著字的那個位於每個分頁的篩選工具列,只清除該分頁的三個篩選條件,別的什麼都不動。另一個是傳輸列上的退出 (eject) 按鈕,它完全沒有文字,只在工具提示裡讀作重置;它會結束工作階段並清空四份清單中的三份——工作階段、NC 診斷與工步診斷。只有「NC 操作」留下來,專案變更也是如此:開啟、重新載入、建立或關閉專案都會清空同樣的三份,獨留那一份。要看上一次轉換或優化說了什麼,就讀這份清單——即使產出它的那次執行早已被重置掉。
這些清單是服務的,不是瀏覽器的。 重新整理、切到另一個畫面、在同一個服務上再開一個分頁,它們都撐得過去;而兩個看著同一次執行的瀏覽器讀到的是同樣的四份清單。
這也正是收合面板不會造成傷害的原因。收合是把面板整個拆掉,而不是隱藏它,四條連線也隨之斷開。什麼都不會丟失,因為這裡本來就沒有保存任何東西。回不來的是版面安排:重新展開會全新建立面板,停在第一個分頁,每個分頁的嚴重性、類別與文字篩選都回到預設值。
服務日誌¶
日誌檢視器在「說明」選單上,位於一道分隔線下方——是選單的最後一個項目,只有已安裝的 HiNC 會在它後面再加上檢查更新…——並在原處開啟,位於 /preference/log。這個項目讀作頁面自己的標題日誌檢視器。
檢視器只顯示一個檔案:這個服務執行個體正在為當天寫入的那一個。從這一頁無法讀到更早一天的檔案。
- 從標題列讀出畫面上的是什麼——檔案涵蓋的日期、上次擷取的時間,以及取回了多少行。窗格開啟時位於檔案末尾,也就是最新幾行所在之處,之後的每次擷取都會停留在末尾,除非它已被捲離底部。
- 按更新取得新的一份,或者把自動打開並選一個間隔——兩秒、五秒、十秒或三十秒——讓它自行重新擷取。
- 用複製取走文字,或用下載取走整個檔案。沒有載入任何內容時兩者都不可用。下載會把檔案存成
log-<date>.txt,不帶檔案在服務上所帶的執行個體名稱,所以從好幾個執行個體收集時要把它改名。
離開這一頁之前先把「自動」關掉。 切到另一個畫面並不會停止它:這一頁會在畫面上那一頁的背後保持存活,按它的間隔繼續重新擷取。重新整理瀏覽器會停止它,專案變更也會,因為兩者都會從頭重建頁面區。
空的檔案和不存在的檔案看起來幾乎一樣,卻不是同一回事。兩者都顯示今天尚無日誌檔。,也都把行數完全藏起來——根本不畫出計數,而不是畫出一個零,所以行數那段文字根本不在,這件事本身就是沒有東西回來的訊號。把兩者分開的是日期標記:檔案存在時,日期來自服務自己的時鐘;完全沒有檔案時,日期來自瀏覽器的 UTC 時鐘,而它未必指向同一天——在台北早上八點之前,它指的是前一天。服務自己從不會讓檔案空著:當天的檔案誕生時就已經帶著第一行,所以一個空檔案是被服務以外的東西清空的。
擷取失敗時,窗格會換成失敗的原因與一個重試按鈕,並以檢視器自己的名義把原因發到頁尾——這是少數不曾是快顯通知就到達頁尾的行之一。
下圖是位於 /preference/log 的日誌檢視器,服務已經執行了一段時間。標題列帶著頁面名稱日誌檢視器、檔案涵蓋的日期、上次載入的時間與行數,然後是自動切換鈕——這裡是關著的——與它旁邊的間隔,以及更新、複製與下載。窗格裡的每一行以它的時間與層級開頭,接著指出寫下它的是服務的哪個部分。

這是服務的日誌,不是瀏覽器的。在頁尾看到的訊息,只有服務也記錄了它才會到達這裡;而它所保存的大部分內容,從未在應用程式的任何地方顯示過。
檔案裡有什麼¶
值得事後讀回的每個事件各一行:
- 啟動 — 一行寫出執行個體、它的建置與 API 版本、工作資料夾、管理者目錄 (admin directory) 以及登入是否開著,接著是服務所聆聽的位址。
- 專案操作 — 每一次載入、重新載入、新增、儲存、另存新檔與關閉各一行,寫出專案檔以及它花了多少毫秒。載入或重新載入還會計數它的載入錯誤與警告,有錯誤時整行記成警告;那次載入所引發的訊息也都在檔案裡。
- 執行 — 執行開始時一行,完成、被停止或結束時再一行,寫出花費的時間、專案、步數,以及 NC、工步與工作階段 (shell) 分開計數的錯誤與警告。執行有錯誤時,收尾那一行記成警告。沒有東西在播放時重新計算的單一步不算一次執行,兩行都不寫。
- 引擎警告過的事 — 四份訊息清單裡的每一則警告與錯誤,帶著它的訊息 id,有錨點時也帶著錨點(
Sn與語句索引,或者工步)。同一個訊息 id 在一次執行中最多寫二十次;執行的收尾那一行會說明有多少則重複沒有寫入。 - 登入 — 登入、登出,以及被拒絕的登入;被拒絕的登入記成警告,帶著試過的名稱與它來自的位址。
- 失敗 — 服務沒有處理到的任何東西,以及原生核心自己的行:授權失敗記為嚴重 (critical),繪圖失敗記為錯誤,軟體渲染記為警告。
- 畫面連線 — 畫布的建立與拆除、它畫出的第一個畫格、執行頁初始化完成。
逐畫格與逐輸入的瑣碎紀錄、每個訊息集線器 (hub) 的連上、可見性變化、畫格壓縮與狀態廣播,都以 Debug 層級寫出,而除非把檔案的層級調低,否則檔案不收這些。
檔案在哪裡¶
檔案是服務工作資料夾底下 logs 資料夾裡的 log-<instance>-<yyyy-MM-dd>.txt。執行個體 (instance) 名稱就是服務啟動時所用的環境名稱——也就是 appsettings.<組態名稱>.json 的那個組態名稱,沒有別的東西另外指定時是 Production——所以共用同一個工作資料夾的幾個執行個體各自保有自己的檔案,每一個的日誌檢視器也只顯示自己的那一份。以同一個名稱在同一個資料夾裡啟動的第二份複本,改寫 log-<instance>-<process id>-<yyyy-MM-dd>.txt,並在它的第一行說明這一點。服務無法建立或寫入的資料夾,會改用工作資料夾底下的 logs,同樣在第一行附上說明。
在 HiNC 安裝程式所安裝的副本上,工作資料夾就是它的資料目錄 %LocalAppData%\HiNC\webservice——可攜式副本則是它自己資料夾裡的 data 資料夾——所以檔案就在那裡的 logs 資料夾中,更新碰不到它們;見在 Windows 上安裝 HiNC。不論是哪一種副本,服務都會在啟動時,於主控台輸出的 Data and logs 那一行印出它的工作資料夾。
超過三十天的檔案,會在服務啟動時以及每次換日時刪除——這個執行個體自己的檔案,以及任何完全不帶執行個體名稱的 log-<yyyy-MM-dd>.txt,那是每個執行個體各有一個檔案之前的檔名。其他執行個體的檔案由它們自己刪除。
改變哪些內容進入檔案¶
檔案有它自己的層級,設定在服務設定的 Logging:File 底下,並且與主控台顯示什麼無關。用 HiNC 安裝程式裝好的副本,這些設定寫在它資料目錄裡的 appsettings.local.json,只給一個執行個體用的則寫在 appsettings.local.<instance>.json——見在 Windows 上安裝 HiNC;程式旁邊的 appsettings.json 每次更新都會被換掉。直接複製到位的副本則從它的 appsettings.json 讀取,或從它旁邊的 appsettings.<instance>.json 讀取,後者逐鍵覆蓋前者。出廠時,它收服務本身 Information 以上的內容,以及服務底下的框架 Warning 以上的內容,框架的啟動行則保留;請求因為用了服務不接受的名稱而被拒絕時,框架記下的那一行也保留。每個鍵指名每一行上印出的類別的開頭,而 Default 涵蓋其他鍵都沒有指名的每個類別。
{
"Logging": {
"File": {
"LogLevel": {
"Default": "Warning",
"Hi.Engine": "Error"
},
"Directory": "../HiNC-Logs",
"RetainDays": 90
}
}
}
這樣只保留警告與更嚴重的內容——框架那幾行啟動行與被拒絕的名稱除外,它們保有自己的 Microsoft.Hosting.Lifetime 與 Microsoft.AspNetCore.HostFiltering 鍵,直到這兩個鍵也被設定為止——而引擎的訊息清單只保留錯誤;檔案寫到另一個資料夾,相對路徑從工作資料夾算起;並保留九十天——0 會保留每一個檔案。同樣的鍵也可以改由環境變數提供,例如 Logging__File__LogLevel__Default=Warning。改完之後重新啟動服務。要找回預設省略的細節,把某個類別——或 Default——設成 Debug。
哪個介面回答哪個問題¶
| 想知道 | 就讀 |
|---|---|
| 上一個動作回報了什麼 | 頁尾的最新一行 |
| 另一個畫面開著時回報了什麼 | 它背後的最近訊息清單——視窗保留的唯一一份 |
| 執行進行到哪裡了 | 頁尾的工作階段條 |
| 「檔案」選單的某項操作是否還在跑 | 頁尾的背景作業區 |
| 工作階段自己開始、完成或拒絕了什麼 | 「工作階段」分頁 (Shell) |
| 程式為什麼沒有照它的文字去做 | 「NC 診斷」分頁 |
| 某個移動為什麼會那樣表現 | 「工步診斷」分頁 |
| 上一次轉換或優化回報了什麼 | 「NC 操作」分頁——重置不會清掉它 |
| 專案為什麼開啟時缺了東西 | 頁尾的最近訊息清單,或日誌檢視器——不是「工作階段訊息」面板 |
| 服務記錄了什麼,不論顯示過與否 | 日誌檢視器 |