Azure Stream Analytics에서 JavaScript 사용자 정의 함수

Azure Stream Analytics에서는 JavaScript로 작성된 사용자 정의 함수를 지원합니다. JavaScript가 제공하는 String, RegExp, Math, Array, Date 메서드 등 풍부한 집합을 사용하여 Stream Analytics 작업에서 복잡한 데이터 변환을 만들 수 있습니다. JavaScript 사용자 정의 함수는 외부 연결이 필요 없는 상태 비저장, 컴퓨팅 전용 스칼라 함수를 지원합니다. 함수의 반환 값은 스칼라(단일) 값만 될 수 있습니다. JavaScript 사용자 정의 함수를 작업에 추가한 후 기본 제공 스칼라 함수처럼 쿼리의 아무 곳에서나 함수를 사용할 수 있습니다.

이 글에서는 자바스크립트 사용자 정의 함수를 언제 사용해야 하는지, 그리고 스트림 애널리틱스 직무에서 이를 정의하고 호출하는 방법을 설명합니다.

JavaScript 사용자 정의 함수를 사용할 때는

다음은 JavaScript 사용자 정의 함수가 유용할 수 있는 몇 가지 시나리오입니다.

  • 정규 표현식 함수(예: Regexp_Replace()Regexp_Extract()를 사용하여 문자열을 파싱하고 조작하는 방법
  • 데이터 디코딩 및 인코딩(예: 2진을 16진으로 변환)
  • JavaScript 수 함수를 이용한 수학 계산 수행
  • 정렬, 조인, 찾기 및 채우기 등의 배열 작업 수행

다음은 Stream Analytics에서 JavaScript 사용자 정의 함수를 사용해서 할 수 없는 몇 가지 사항입니다:

  • 예를 들어, 외부 REST 엔드포인트를 호출하여 역IP 조회를 하거나 외부 소스에서 참조 데이터를 가져오는 식입니다
  • 입력 또는 출력에 대해 맞춤형 이벤트 형식 직렬화 또는 디직렬라이즈를 수행합니다
  • 사용자 지정 집계 만들기

Date.GetDate()Math.random() 같은 함수는 함수 정의에서 차단되지 않지만, 사용하지 마세요. 이러한 함수는 호출할 때마다 다른 결과를 반환하며 Azure Stream Analytics 서비스에서 함수 호출 및 반환된 결과 저널을 유지하지 않습니다. 함수가 같은 이벤트에서 다른 결과를 반환하면, 당신이나 스트림 분석 서비스가 작업을 재시작했을 때 반복성이 보장되지 않습니다.

Azure 포털에서 JavaScript 사용자 정의 함수를 정의하세요

클라우드에서 실행되는 스트림 분석 작업의 경우, 작업 토폴로지함수 페이지에서 자바스크립트 사용자 정의 함수를 추가하세요. +Add 메뉴에 자바스크립트 UDF 옵션이 포함되어 있습니다.

참고

이 경험은 클라우드에서 실행되도록 설정된 스트림 분석 작업에도 적용됩니다. Stream Analytics 작업을 Azure IoT Edge에서 실행되도록 구성한 경우, Visual Studio를 대신 사용하고 C#을 사용하여 사용자 정의 함수를 작성합니다.

Azure 포털 기능 페이지의 스크린샷으로, 자바스크립트 UDF 옵션이 포함된 추가 메뉴가 보입니다.

함수 정의는 다음과 같은 성질로 구성됩니다:

속성 설명
함수 별칭 쿼리에서 해당 기능을 호출하는 이름입니다.
출력 형식 자바스크립트 사용자 정의 함수가 스트림 분석 쿼리에 반환하는 타입입니다.
함수 정의 쿼리에서 UDF가 호출될 때마다 실행되는 자바스크립트 함수의 구현입니다.

JavaScript UDF 로직 테스트 및 문제 해결

Stream Analytics 포털은 사용자 정의 함수들의 디버깅 및 테스트를 지원하지 않기 때문에, 어떤 브라우저에서든 JavaScript UDF 로직을 테스트하고 디버깅할 수 있습니다. 함수가 기대대로 작동하면, Stream Analytics 작업에 추가하고 쿼리에서 직접 호출할 준비가 되어 있습니다. 또한 Visual Studio의 Stream Analytics 도구를 사용해 JavaScript UDF로 쿼리 로직을 테스트할 수도 있습니다.

Stream Analytics는 자바스크립트 런타임 오류를 치명적인 것으로 간주하고 Activity 로그를 통해 이를 드러냅니다. 로그는 Azure 포털의 작업 활동 로그 페이지에서 확인할 수 있습니다.

쿼리에서 JavaScript 사용자 정의 함수 호출

쿼리에서 JavaScript 함수를 호출하려면 udf가 붙은 함수 alias를 사용하세요. 다음 예시는 스트림 애널리틱스 쿼리에서 16진수 값을 정수로 변환하는 JavaScript UDF를 보여줍니다.

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

지원되는 JavaScript 개체

Azure Stream Analytics 자바스크립트 사용자 정의 함수는 표준에 내장된 자바스크립트 객체를 지원합니다. 이 객체들은 추가 설정 없이 함수들이 일반적인 문자열, 수학, 배열, 날짜 연산에 접근할 수 있게 해줍니다. 사용 가능한 객체의 전체 목록은 글로벌 객체를 참조하세요. Stream Analytics 쿼리 언어와 JavaScript가 동일한 타입 시스템을 공유하지 않기 때문에, Stream Analytics는 두 언어 간에 값을 변환합니다.

Stream Analytics 및 JavaScript 형식 변환

Stream Analytics 쿼리 언어와 JavaScript는 서로 다른 유형의 쿼리를 지원합니다. 이 테이블에는 둘 간의 변환 매핑 목록이 나열되어 있습니다.

Stream Analytics JavaScript
bigint Number(JavaScript에서는 정확히 최대 2^53의 정수만 표현할 수 있음)
날짜 및 시간 Date(JavaScript에서는 밀리초만 지원)
double 숫자
nvarchar(MAX) 문자열
녹음 Object
배열 배열
NULL Null

다음은 JavaScript-Stream Analytics 변환입니다.

JavaScript Stream Analytics
숫자 Bigint(숫자가 정수이고 long.MinValue와 long.MaxValue 사이에 있는 경우, 그렇지 않으면 double)
날짜 날짜 및 시간
문자열 nvarchar(MAX)
Object 녹음
배열 배열
널, 언디파인드 NULL
기타 다른 형식(예: 함수 또는 오류) 지원되지 않음(런타임 오류 발생)

자바스크립트는 대소문자 구분이 가능하며, 자바스크립트 코드에서 객체 필드의 케이싱은 들어오는 데이터의 필드 케이싱과 일치해야 합니다. 호환성 레벨 1.0을 가진 작업은 SQL SELECT 문에서 소문자로 필드를 변환합니다. 호환성 레벨 1.1 이상에서는 SELECT 문에서 나오는 필드들이 SQL 쿼리에서 지정한 것과 동일한 케이스를 가집니다.

일반적인 기능 패턴

다음 패턴들은 자바스크립트 사용자 정의 함수를 활용해 스트림 분석 쿼리의 데이터를 변환하는 일반적인 방법을 보여줍니다. 각 패턴에는 함수 정의와 이를 호출하는 샘플 쿼리가 포함되어 있습니다.

중첩된 JSON을 출력에 작성

Stream Analytics 작업 출력을 입력으로 사용하는 후속 처리 단계가 있고 이것이 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 형식의 문자열 필드가 있고 이를 JavaScript UDF에서 처리할 JSON 객체로 변환하고 싶다면, 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에 전달하는 입력 데이터가 잘못 형성된 문제를 식별하는 데 도움을 줍니다. 다음 함수 정의는 파싱 오류를 처리하기 위해 try/catch 블록을 사용합니다.

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 Stream Analytics는 시스템 타임스탬프로 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 형식의 입력된 datetime 값입니다.

Samstag, 28. December 2019

사용자 로깅

로깅은 Azure Stream Analytics가 작업이 실행되는 동안 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()

스트림 애널리틱스는 이진 데이터를 텍스트로 인코딩하는 일반적인 방법인 Base64 변환 두 가지 방식을 지원합니다. btoa() 방식은 ASCII 문자열을 Base64로 인코딩하고, atob() 메서드는 Base64로 인코딩된 문자열을 다시 ASCII 문자열로 디코딩합니다. 다음 예 btoa() 시에서는 ASCII 문자열을 인코딩한 후 atob() 결과를 원래 문자열로 다시 디코딩합니다.

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