日誌服務提供一站式的日誌採集、存儲、查詢、計算功能。互動式的日誌採集體驗,釋放用戶的運維壓力,解放用戶的雙手; 互動式的查詢分析體驗,讓用戶自由的構建數據模型、探索式分析挖掘數據深層。
用戶使用日誌服務的查詢分析能力,不僅可以在控制台互動式查詢,也可以使用SDK,在程序中使用查詢分析。 當計算結果比較大時,怎麼把全量結果讀取到本地,是一個比較比較頭疼的問題。幸好,日誌服務提供了翻頁的功能,不僅可以翻頁讀取原始日誌內容,也可以把SQL的計算結果翻頁讀取到本地。開發者可以通過日誌服務提供的SDK,或者Cli,通過讀數據介面翻頁讀取日誌。
日誌服務提供一個統一的查詢日誌入口:GetLogstoreLogs,既可以根據關鍵字查詢日誌原始內容,也可以提交SQL計算,獲取計算結果。
在翻頁讀取時,不停的增大offset,知道讀取到某個offset後,獲取的結果行數為0,並且結果的progress為complete狀態,則認為讀取到了全部數據,可以結束了。
offset = 0 // 從第0行開始讀取 lines = 100 //每次讀取100行 query = "status:200" //查詢status欄位包含200的所有日誌 while True: response = get_logstore_logs(query, offset, lines) // 執行讀取請求 process (response) //調用自定義邏輯,處理返回的結果 如果 response.get_count() == 0 && response.is_complete() 則讀取結束,跳出當前循環 否則 offset += 100 offset增加100,讀取下一個100行
更詳細案例參考文檔:
endpoint = # 選擇與上面步驟創建Project所屬區域匹配的Endpoint accessKeyId = # 使用您的阿里雲訪問密鑰AccessKeyId accessKey = # 使用您的阿里雲訪問密鑰AccessKeySecret project = # 上面步驟創建的項目名稱 logstore = # 上面步驟創建的日誌庫名稱 client = LogClient(endpoint, accessKeyId, accessKey) topic = "" query = "index" From = int(time.time()) - 600 To = int(time.time()) log_line = 100 offset = 0 while True: res4 = None for retry_time in range(0, 3): req4 = GetLogsRequest(project, logstore, From, To, topic, query, log_line, offset, False) res4 = client.get_logs(req4) if res4 is not None and res4.is_completed(): break time.sleep(1) offset += 100 if res4.is_completed() && res4.get_count() == 0: break; if res4 is not None: res4.log_print() # 這裡處理結果
更詳細的案例參考文檔
int log_offset = 0; int log_line = 100;//log_line 最大值為100,每次獲取100行數據。若需要讀取更多數據,請使用offset翻頁。offset和lines只對關鍵字查詢有效,若使用SQL查詢,則無效。在SQL查詢中返回更多數據,請使用limit語法。 while (true) { GetLogsResponse res4 = null; // 對於每個 log offset,一次讀取 10 行 log,如果讀取失敗,最多重複讀取 3 次。 for (int retry_time = 0; retry_time < 3; retry_time++) { GetLogsRequest req4 = new GetLogsRequest(project, logstore, from, to, topic, query, log_offset, log_line, false); res4 = client.GetLogs(req4);
if (res4 != null && res4.IsCompleted()) { break; } Thread.sleep(200); } System.out.println("Read log count:" + String.valueOf(res4.GetCount())); log_offset += log_line; if (res4.IsCompleted() && res4.GetCount() == 0) { break; }
}
在SQL分析中,GetLogStoreLogs API 參數中的offset 和lines是無效的,填寫。也就是說,如果按照上文翻頁讀取原始內容的方式,遍歷offset翻頁,那麼每次SQL執行的結果都是一樣的。理論上,我們可以在一次調用中,獲取全部的計算結果,但是如果結果集太大,可能會產生以下問題:
limit Offset, Line
* | select count(1) , url group by url
那麼可以翻頁,每次讀取500行,共4次讀取完成:
* | select count(1) , url group by url limit 0, 500 * | select count(1) , url group by url limit 500, 500 * | select count(1) , url group by url limit 1000, 500 * | select count(1) , url group by url limit 1500, 500
offset = 0 // 從第0行開始讀取 lines = 500 //每次讀取500行 query = "* | select count(1) , url group by url limit " while True: real_query = query + offset + "," + lines response = get_logstore_logs(real_query) // 執行讀取請求 process (response) //調用自定義邏輯,處理返回的結果 如果 response.get_count() == 0 則讀取結束,跳出當前循環 否則 offset += 500 offset增加100,讀取下一個500行
endpoint = # 選擇與上面步驟創建Project所屬區域匹配的Endpoint accessKeyId = # 使用您的阿里雲訪問密鑰AccessKeyId accessKey = # 使用您的阿里雲訪問密鑰AccessKeySecret project = # 上面步驟創建的項目名稱 logstore = # 上面步驟創建的日誌庫名稱 client = LogClient(endpoint, accessKeyId, accessKey) topic = "" origin_query = "* | select count(1) , url group by url limit " From = int(time.time()) - 600 To = int(time.time()) log_line = 100 offset = 0 while True: res4 = None query = origin_query + str(offset) + " , " + str(log_line) for retry_time in range(0, 3): req4 = GetLogsRequest(project, logstore, From, To, topic, query) res4 = client.get_logs(req4) if res4 is not None and res4.is_completed(): break time.sleep(1) offset += 100 if res4.is_completed() && res4.get_count() == 0: break; if res4 is not None: res4.log_print() # 這裡處理結果
int log_offset = 0; int log_line = 500; String origin_query = "* | select count(1) , url group by url limit " while (true) { GetLogsResponse res4 = null; // 對於每個 log offset,一次讀取 500 行 log,如果讀取失敗,最多重複讀取 3 次。 query = origin_query + log_offset + "," + log_line; for (int retry_time = 0; retry_time < 3; retry_time++) { GetLogsRequest req4 = new GetLogsRequest(project, logstore, from, to, topic, query); res4 = client.GetLogs(req4);
if (res4 != null && res4.IsCompleted()) { break; } Thread.sleep(200); } System.out.println("Read log count:" + String.valueOf(res4.GetCount())); log_offset += log_line; if (res4.GetCount() == 0) { break; }
本文作者:雲雷
原文鏈接
更多技術乾貨敬請關注云棲社區知乎機構號:阿里云云棲社區 - 知乎
本文為雲棲社區原創內容,未經允許不得轉載。