Azure 串流分析中的 JavaScript 使用者定義函式

Azure 串流分析支援以 JavaScript 撰寫的使用者定義函式。 透過使用 JavaScript 提供的豐富字 RegExp數學陣列日期 方法,您可以在 Stream Analytics 工作中創造複雜的資料轉換。 JavaScript 使用者定義的函式支援無狀態且只做為計算用途的純量函式,而且不需要外部連線能力。 函數的傳回值只能是純量 (單一) 值。 將 JavaScript 使用者定義函式新增至作業之後,您可以在查詢中的任何位置使用函式,就像是內建的純量函式。

本文說明何時使用 JavaScript 使用者自訂函式,以及如何在你的串流分析工作中定義和呼叫它們。

何時使用 JavaScript 使用者自訂函式

從以下的一些案例可以看出 JavaScript 使用者定義函式很實用:

  • 利用正則表達式函式(例如 Regexp_Replace()Regexp_Extract() 來解析與操作字串
  • 資料的解碼與編碼,例如二進位轉十六進位
  • 使用 JavaScript 數學函數 進行數學計算
  • 進行陣列作業,例如,排序、連結、尋找及填入

以下是使用 Stream Analytics 中 JavaScript 使用者定義函式無法做到的一些功能:

  • 例如呼叫外部 REST 端點,進行反向 IP 查詢或從外部來源拉取參考資料
  • 對輸入或輸出執行自訂事件格式序列化或反序列化
  • 建立自訂聚合

雖然像 Date.GetDate()Math.random() 這類函式不會被函式定義阻擋,但請避免使用它們。 這些函式不會在每次呼叫時都傳回同樣的結果,且「串流分析」服務不會記錄函式叫用和傳回值的日誌。 如果函式在相同事件中回傳不同結果,當你或 Stream Analytics 服務重新啟動工作時,重複性就無法保證。

在 Azure portal 中定義 JavaScript 用戶自定義函式

對於在雲端執行的 Stream Analytics 工作,請從工作拓撲下的函數頁面新增一個 JavaScript 使用者自訂函式,該頁面的 +Add 選單包含 JavaScript UDF 選項。

注意

這種經驗適用於設定為雲端執行的串流分析工作。 如果您的串流分析作業設定為在 Azure IoT Edge 上執行,請改為使用 Visual Studio 並使用C# 撰寫使用者定義的函式

Azure 入口網站功能頁面的截圖,顯示新增選單與 JavaScript UDF 選項。

函數定義包含以下性質:

屬性 說明
函式別名 就是你查詢中會呼叫該函數的名稱。
輸出類型 JavaScript 使用者定義函數傳回給您的串流分析查詢的類型。
函式定義 每次從查詢叫用 UDF 時執行的 JavaScript 函式實作。

測試與故障排除 JavaScript UDF 邏輯

由於 Stream Analytics 入口網站不支援除錯與測試這些使用者自訂函式的邏輯,你可以在任何瀏覽器中測試和除錯 JavaScript 的 UDF 邏輯。 當函式如預期運作時,即可將其新增至 Stream Analytics 作業,並直接從查詢中呼叫。 你也可以使用 Visual Studio 的 Stream Analytics 工具,用 JavaScript UDF 測試查詢邏輯。

Stream Analytics 將 JavaScript 執行時錯誤視為致命,並透過活動日誌呈現。 該日誌可在 Azure 入口網站的職務活動日誌頁面取得。

在查詢中呼叫 JavaScript 使用者定義函式

要在查詢中調用 JavaScript 函式,請使用帶有 udf 的函式別名。 以下範例展示了一個 JavaScript UDF,在 Stream Analytics 查詢中將十六進位數值轉換為整數。

    SELECT
        time,
        UDF.hex2Int(offset) AS IntOffset
    INTO
        output
    FROM
        InputStream

支援的 JavaScript 物件

Azure 串流分析 JavaScript 的使用者定義函式支援標準內建的 JavaScript 物件。 這些物件讓你的函式能存取常見的字串、數學運算、陣列和日期運算,且無需額外設定。 欲了解完整可用物件清單,請參見 全域物件。 由於 Stream Analytics 查詢語言和 JavaScript 不共享相同的型別系統,Stream Analytics 會在兩者之間傳遞的值轉換。

串流分析與 JavaScript 類型轉換

Stream Analytics 查詢語言與 JavaScript 支援不同類型。 此表列出兩者之間的轉換對應:

串流分析 JavaScript
Bigint Number (JavaScript 只能準確地表示最高到 2^53 的整數)
日期時間 Date (JavaScript 只支援毫秒)
double 數值
nvarchar(MAX) 字串
錄製 物件
陣列 陣列
NULL Null

以下是 JavaScript 至串流分析的轉換:

JavaScript 串流分析
數值 Bigint (若數字為整數且介於 long.MinValue 和 long.MaxValue 之間,否則為 double)
日期 日期時間
字串 nvarchar(MAX)
物件 錄製
陣列 陣列
Null、未定義 NULL
任何其他類型 (例如,函式或錯誤) 不支援 (產生執行階段錯誤)

JavaScript 會區分大小寫,而 JavaScript 程式碼中物件欄位的大小寫必須與傳入資料中的欄位大小寫一致。 相容性等級 1.0 的工作會將欄位從 SQL SELECT 陳述式轉換為小寫。 在相容性等級 1.1 及以上,SELECT 語句中的欄位與 SQL 查詢中指定的格式相同。

常見的功能模式

以下模式展示了使用 JavaScript 使用者定義函式來轉換 Stream Analytics 查詢資料的常見方法。 每個模式都包含一個函式定義及一個用於調用的範例查詢。

將巢狀 JSON 寫入至輸出

如果您的後續處理步驟使用串流分析作業輸出做為輸入,且其需要 JSON 格式,您可以將 JSON 字串寫入至輸出。 以下函式定義呼叫 JSON.stringify() 函式,將輸入的所有名稱/值對打包,然後將它們寫成單一字串值在輸出中。

function main(x) {
return JSON.stringify(x);
}

串流分析查詢會呼叫以下範例所示的函式。

SELECT
    DataString,
    DataValue,
    HexValue,
    UDF.jsonstringify(input) As InputEvent
INTO
    output
FROM
    input PARTITION BY PARTITIONID

將字串轉換成 JSON 物件以供處理

如果你有一個字串欄位是 JSON,想把它轉換成 JSON 物件,然後用 JavaScript UDF 處理,你可以用 JSON.parse() 函式建立一個 JSON 物件,然後再用來使用。 以下函式定義解析該字串,並從所得物件回傳一個屬性。

function main(x) {
var person = JSON.parse(x);  
return person.name;
}

串流分析查詢會呼叫以下範例所示的函式。

SELECT
    UDF.getName(input) AS Name
INTO
    output
FROM
    input

使用 try/catch 進行錯誤處理

try/catch 區塊可協助你找出傳入 JavaScript UDF 的格式錯誤輸入資料所造成的問題。 以下函式定義使用嘗試/捕捉區塊來處理解析錯誤。

function main(input, x) {
    var obj = null;

    try{
        obj = JSON.parse(x);
    }catch(error){
        throw input;
    }
    
    return obj.Value;
}

在接下來的範例查詢中,你會把整個紀錄作為第一個參數傳遞,這樣如果有錯誤,函式就能回傳。

SELECT
    A.context.company AS Company,
    udf.getValue(A, A.context.value) as Value
INTO
    output
FROM
    input A

toLocaleString()

JavaScript 中的 toLocaleString 方法會回傳一個語言敏感的字串,代表你呼叫該方法的日期-時間資料。 雖然 Azure 串流分析 只接受 UTC 日期時間作為系統時間戳,但你可以用這個方法將系統時間戳轉換為另一個地點和時區。 此方法的實作行為與 Internet Explorer 所提供的相同。 以下函式定義將輸入日期時間轉換為 de-DE 地點。

function main(datetime){
    const options = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' };
    return datetime.toLocaleDateString('de-DE', options);
}

在以下範例查詢中,輸入值是 datetime。

SELECT
    udf.toLocaleString(input.datetime) as localeString
INTO
    output
FROM
    input

此查詢的輸出結果,會依據所提供的選項,以 de-DE 格式顯示輸入的日期時間。

Samstag, 28. December 2019

使用者日誌

日誌是 Azure 串流分析 用來在工作執行時,從 JavaScript 使用者定義函式擷取自訂資訊的機制。 由於執行中的作業本身是不透明的,日誌資料能讓你即時看到自訂程式碼的行為與正確性。 每個日誌訊息都帶有一個事件等級,指示訊息的重要性以及該工作是否能繼續執行。

資訊訊息來自 console.info() 方法,例如 console.info('my info message');。 此層級在執行過程中記錄一般資訊,且不會中斷計算。 警告訊息來自 console.warn() 方法,例如 console.warn('my warning message');. 此層級會記錄可能出乎預期但仍可用於運算的資料,因此作業會繼續執行。 錯誤訊息來自 console.error()console.log() 方法,例如 console.error('my error message');。 這些方法僅適用於程式碼無法繼續執行的情況,因此會使用所提供的錯誤資訊擲回例外,並停止作業。

您可以透過 診斷記錄存取記錄訊息。

atob() 和 btoa()

Stream Analytics 支援兩種 Base64 轉換方法,這是將二進位資料編碼成文字的常見方式。 btoa() 方法將 ASCII 字串編碼為 Base64,而 atob() 方法則將 Base64 編碼的資料字串解碼回 ASCII 字串。 以下範例中,先 btoa() 編碼一個 ASCII 字串,然後 atob() 將結果解碼回原始字串。

var myAsciiString = 'ascii string';
var encodedString = btoa(myAsciiString);
var decodedString = atob(encodedString);