返回列表

AWS帳號購買優惠 AWS CloudWatch Logs Insights 查詢語法寫錯導致日誌搜尋不到排查

亞馬遜雲AWS / 2026-08-04 15:42:36

先確認不是「沒有日誌」,而是「查詢沒查到」

在 AWS CloudWatch Logs Insights 裡,最讓人頭痛的不是查詢慢,而是明明服務有打 log,卻怎麼搜都空白。很多人第一時間會懷疑程式沒寫入、Lambda 沒執行、EC2 沒送出,但實際上更常見的原因,是查詢語法、時間範圍、Log Group 或欄位名寫錯,導致結果被過濾掉了。

Logs Insights 的特性是很靈活,也因此很容易因為一個小地方出錯就查不到資料。你可能以為是在「找不到日誌」,其實只是查詢條件太窄,或是把欄位當成原始字串在搜,結果根本沒有命中。排查這類問題,重點不是一直換關鍵字,而是先把查詢拆開,從最粗的條件開始,一層一層縮小範圍。

排查順序:先看資料面,再看語法面

遇到查不到資料時,不要急著改 query。先確認這幾件事:

  1. 時間範圍是否正確。很多日誌其實在幾分鐘前或幾小時前,但查詢區間只設了最近 5 分鐘,當然看不到。
  2. Log Group 是否選對。測試環境、正式環境、不同帳號、不同區域,常常只有一個地方有資料。
  3. 日誌是否真的有送進 CloudWatch。應用程式有印出來,不代表已經成功上傳。
  4. 查詢是否先用最基本的條件驗證過。先看原始 @message,再逐步加上 filter、parse、stats。

這個順序很重要,因為如果資料本身就不在,怎麼改語法都沒用;反過來說,如果資料明明在,只是欄位名或條件寫錯,換再多關鍵字也只是在原地打轉。

最容易寫錯的幾個點

欄位名寫錯,查的是空欄位

Logs Insights 很多時候不是搜全文,而是在搜欄位。你如果把欄位名寫錯,查詢看起來沒問題,結果卻永遠是空的。例如系統欄位通常是 @message@timestamp@logStream,不是 messagetimestamp 這種裸欄位。除非你的 log 本來就是 JSON,而且真的有這些欄位,否則直接寫錯就會查不到。

常見情況是:日誌內容其實長這樣:

{'level':'ERROR','requestId':'abc-123','msg':'timeout while calling service'}

AWS帳號購買優惠 但查詢時卻寫成:

fields timestamp, message
| filter message like /timeout/

這樣就很危險。因為真正存在的可能是 @timestamp@message,或者是 JSON 裡的 msg,不是你腦中預設的欄位名稱。

把 like、=、regex 混為一談

AWS帳號購買優惠 另一個常見錯誤,是把查字串、查完全相等、查正則混著用。Logs Insights 裡,like 通常搭配正則式使用,不是拿來放一般字串比較的。很多人會寫成:

filter @message like 'timeout'

這種寫法很容易出問題,因為你以為是在搜尋包含 timeout 的字串,但實際上 query 可能根本沒有按照你想的方式執行。更穩妥的做法是:

filter @message like /timeout/

如果你要做精確比對,像是狀態值、等級、代碼,就直接用相等比較。例如:

filter level = 'ERROR'

不要把「找文字」和「比對欄位值」混在一起。前者適合用正則或包含關鍵字的方式,後者適合用等號。這兩種方式看起來很像,實際用途完全不同。

引號、斜線與特殊字元沒有處理好

Logs Insights 的字串和正則都有自己的寫法,少一個符號就可能整段失效。像是你要找含有斜線、括號、加號、問號這類特殊字元時,如果直接塞進正則,可能會被當成語法而不是文字。這時候不是單純多打幾個字就能解決,而是要先判斷你到底是在做文字搜尋,還是在做模式比對。

例如你想找 URL 路徑中的 /api/v1/login,卻直接寫成:

filter @message like //api/v1/login/

這就很容易出錯。因為斜線本身在正則裡有特殊意義。比較安全的做法,是先用最簡單的關鍵字驗證有沒有資料,再逐步加入特殊字元的限制。當你確認資料存在後,再去處理轉義問題,會比一開始就寫複雜正則有效得多。

parse 沒成功,後面的 filter 全失效

很多人會把 parse 當成魔法工具,以為只要寫了就能把欄位抓出來。但事實上,parse 只要模式沒對上,後面的欄位就會是空值。這時候你再拿那個欄位去 filter,自然查不到任何結果。

例如你想從字串中抽出 requestId:

fields @message
| parse @message 'requestId=* ' as requestId
| filter requestId = 'abc-123'

如果實際 log 格式不是你想的那樣,或者空白、標點、順序不一致,parse 就會失敗。很多人只看到最後一段 filter 沒結果,卻沒想到前面的 parse 早就沒抓到值。遇到這種情況,最好先把 parse 拿掉,直接看原始訊息,再回頭調整模式。

stats 和 limit 讓你誤以為沒有結果

有些查詢其實有資料,但被你自己的聚合方式藏起來了。像 stats count() 會把多筆事件彙總成少數結果,如果分組條件不對,看起來就像沒東西。再加上 limit 設太小,可能只顯示最前面幾筆,讓你誤判為查不到。

這類問題最好的檢查方式,是先拿掉 statssortlimit,只保留最基礎的查詢,確認原始日誌真的能出現,再慢慢加回分析條件。不要一開始就寫得很完整,結果自己把自己過濾掉。

一個實際排查案例

假設你要找的是 API timeout 的 log,原本查詢寫成這樣:

fields timestamp, message
| filter message like 'timeout'
| limit 20

這個查詢看起來很正常,但實際上可能有三個問題:第一,欄位名不是 timestampmessage,而是 @timestamp@message;第二,like 後面放的是字串,不是正則;第三,沒有先確認時間範圍和 Log Group 是否正確。

修正後可以改成:

fields @timestamp, @message
| filter @message like /timeout/i
| sort @timestamp desc
| limit 50

這樣先用最基本的全文檢查,確認 timeout 相關訊息是否存在。若有資料,再進一步縮小條件,例如只看特定服務、特定 requestId、特定 statusCode。

如果你的日誌是 JSON,效果會更好。比如:

fields @timestamp, requestId, statusCode, level
| filter level = 'ERROR' and statusCode >= 500
| sort @timestamp desc
| limit 50

這種寫法比一直從 @message 字串裡硬找更穩定,因為它直接使用結構化欄位,少了很多誤判和轉義問題。

真正好用的排查方式,是先粗後細

CloudWatch Logs Insights 最怕的不是資料太少,而是條件太早寫死。實務上,排查順序可以這樣走:

先只選對 Log Group 和時間範圍,跑最簡單的查詢:

fields @timestamp, @message
| sort @timestamp desc
| limit 20

如果這一步看得到資料,代表日誌已經進來了。接著再加關鍵字:

fields @timestamp, @message
| filter @message like /error/

有結果之後,再加條件:

fields @timestamp, @message, requestId
| filter @message like /error/ and requestId = 'abc-123'

最後才考慮 parsestatsdedup 這些進階處理。這種做法雖然慢一點,但很容易知道是哪一層出問題,不會把時間浪費在猜測上。

如果還是查不到,該檢查什麼

有時候 query 沒錯,問題卻還是存在。這時候就要看資料流本身:

  • 應用程式有沒有真的寫到 CloudWatch。
  • 是否有延遲,日誌晚幾分鐘才到。
  • AWS帳號購買優惠 帳號、區域、環境是否一致。
  • Log Group 是否被錯誤地分流到別的命名規則。
  • 是否被權限限制,導致你看不到某些群組或事件。

尤其在多環境部署時,最容易發生的不是語法錯,而是人在 prod 查 dev,或在 ap-northeast-1 查 us-east-1。畫面上看起來像是「搜尋不到」,其實根本是在錯的地方找東西。

結語:先讓查詢回到可驗證狀態

CloudWatch Logs Insights 查詢寫錯,最怕的是把問題看成「搜尋關鍵字沒命中」,其實真正原因可能是欄位名、語法、時間範圍、Log Group、正則轉義,甚至是聚合條件把結果蓋掉了。只要記住一個原則:先確認資料存在,再確認欄位對不對,最後才是精修查詢。

下次遇到查不到日誌,不要急著重寫一大段 query。先用最簡單的方式把原始 log 拉出來,再逐步加條件。能先看到資料,後面的分析才有意義。這不只是排錯技巧,也是寫 Logs Insights 查詢最省時間的方式。

Telegram售前客服
客服ID
@cloudcup
联系
Telegram售后客服
客服ID
@yanhuacloud
联系