Java에서 추적 이벤트 내보내기

Snowflake Telemetry API 라이브러리의 com.snowflake.telemetry.Telemetry 클래스를 사용하여 Java로 작성된 함수 또는 프로시저 처리기에서 추적 이벤트를 내보낼 수 있습니다. Telemetry 클래스는 Snowflake에 포함되어 있습니다.

참고

Snowflake 원격 분석 라이브러리를 사용하면 함수 또는 프로시저의 실행 환경에 다른 라이브러리가 추가됩니다. 자세한 내용은 Snowflake 원격 분석 패키지 종속성 섹션을 참조하십시오.

Maven으로 코드를 패키징할 때 Telemetry 라이브러리를 포함하는 방법에 대한 자세한 내용은 원격 분석 클래스를 사용하도록 Java 및 Scala 환경 설정하기 섹션을 참조하십시오.

이벤트 테이블에서 SELECT 명령을 실행하여 저장된 추적 이벤트 데이터에 액세스할 수 있습니다. 자세한 내용은 추적 데이터 보기 섹션을 참조하십시오.

참고

추적 이벤트를 추가할 때 염두에 두어야 할 지침은 추적 이벤트를 추가하는 일반 지침 섹션을 참조하십시오.

Snowflake에서 로깅 설정 및 메시지 검색에 대한 일반적인 정보는 함수 및 프로시저의 메시지 로깅하기 섹션을 참조하십시오.

코드에서 로깅하기 전에 다음을 수행해야 합니다.

원격 분석 API에 대한 지원 추가하기

Telemetry 메서드를 사용하려면 Snowflake에 포함된 Snowflake 원격 분석 라이브러리를 처리기 코드에서 사용 가능하도록 만들어야 합니다.

  • CREATE PROCEDURE 또는 CREATE FUNCTION 문의 PACKAGES 절에 com.snowflake:telemetry 패키지를 포함합니다. PACKAGES 절은 포함된 Snowflake 원격 분석 API를 코드에 사용할 수 있도록 합니다.

    다음 예제의 코드에서는 PACKAGES 절을 사용하여 원격 분석 라이브러리와 Snowpark 라이브러리(Java로 작성된 저장 프로시저에 필요함 – 자세한 내용은 Java로 저장 프로시저 작성하기 참조)를 참조하십시오.

    CREATE OR REPLACE PROCEDURE MYPROC(...)
      RETURNS ...
      LANGUAGE JAVA
      ...
      PACKAGES = ('com.snowflake:snowpark:latest', 'com.snowflake:telemetry:latest')
      ...
    
    Copy
  • Java 처리기 코드에서 com.snowflake.telemetry 패키지를 가져옵니다.

    import com.snowflake.telemetry.Telemetry;
    
    Copy

추적 이벤트 추가하기

Telemetry.addEvent 메서드를 호출하고 이벤트 이름을 전달하여 추적 이벤트를 추가할 수 있습니다. 선택적으로 특성(키-값 페어)을 이벤트와 연결할 수도 있습니다.

addEvent 메서드에는 다음 서명이 있습니다.

public static void addEvent(String name)
public static void addEvent(String name, Attributes attributes)
Copy

다음 예제의 코드는 testEvent 라는 이벤트를 추가하여 이벤트에 keyresult 라는 두 가지 특성과 연결합니다.

// Adding an event without attributes.
Telemetry.addEvent("testEvent");

// Adding an event with attributes.
Attributes eventAttributes = Attributes.of(
  AttributeKey.stringKey("key"), "run",
  AttributeKey.longKey("result"), Long.valueOf(123));
Telemetry.addEvent("testEventWithAttributes", eventAttributes);
Copy

이러한 이벤트를 추가하면 이벤트 테이블에 두 개의 행이 생기는데, RECORD 열의 값이 각각 다릅니다.

{
  "name": "testEvent"
}
Copy
{
  "name": "testEventWithAttributes"
}
Copy

testEventWithAttributes 이벤트 행의 RECORD_ATTRIBUTES 열에 다음 특성을 포함합니다.

{
  "key": "run",
  "result": 123
}
Copy

범위 특성 추가하기

Telemetry.setSpanAttribute 메서드를 호출하여 범위와 연결된 특성(키-값 페어)을 설정할 수 있습니다.

setSpanAttribute 메서드에는 다음 서명이 있습니다.

public static void setSpanAttribute(String key, boolean value)
public static void setSpanAttribute(String key, long value)
public static void setSpanAttribute(String key, double value)
public static void setSpanAttribute(String key, String value)
Copy

범위에 대한 자세한 내용은 Snowflake가 추적 이벤트를 표시하는 방법 섹션을 참조하십시오.

다음 예제의 코드는 4가지 특성을 만들고 해당 값을 설정합니다.

// Setting span attributes.
Telemetry.setSpanAttribute("example.boolean", true);
Telemetry.setSpanAttribute("example.long", 2L);
Telemetry.setSpanAttribute("example.double", 2.5);
Telemetry.setSpanAttribute("example.string", "testAttribute");
Copy

이러한 특성을 설정하면 이벤트 테이블의 RECORD_ATTRIBUTES 열에 다음 내용이 표시됩니다.

{
  "example.boolean": true,
  "example.long": 2,
  "example.double": 2.5,
  "example.string": "testAttribute"
}
Copy

사용자 지정 범위 추가하기

참고

사용자 지정 범위에 대한 지원은 모든 계정에서 사용할 수 있는 미리 보기 기능입니다.

Snowflake에서 생성된 기본 범위와 별도로 사용자 지정 범위를 추가할 수 있습니다. 사용자 지정 범위에 대한 자세한 내용은 추적에 사용자 지정 범위 추가하기 섹션을 참조하십시오.

다음 예제의 코드는 OpenTelemetry APIOpenTelemetry context propagation API 를 사용하여 새 my.span 범위를 생성합니다. 그런 다음 특성이 포함된 이벤트를 새 범위에 추가합니다. 마지막으로, 이 코드는 범위를 종료하여 이벤트 테이블에 해당 범위의 이벤트 데이터가 캡처되도록 합니다. 코드에서 Span.end 메서드를 호출하지 않으면 이벤트 테이블에 데이터가 캡처되지 않습니다.

CREATE OR REPLACE FUNCTION customSpansJavaExample() RETURNS STRING
LANGUAGE JAVA
PACKAGES = ('com.snowflake:telemetry:latest')
HANDLER = 'MyJavaClass.run'
as
$$
  import com.snowflake.telemetry.Telemetry;
  import io.opentelemetry.api.common.AttributeKey;
  import io.opentelemetry.api.common.Attributes;
  import io.opentelemetry.api.GlobalOpenTelemetry;
  import io.opentelemetry.api.trace.Tracer;
  import io.opentelemetry.api.trace.Span;
  import io.opentelemetry.context.Scope;

  class MyJavaClass {
    public static String run() {
      Tracer tracer = GlobalOpenTelemetry.getTracerProvider().get("my.tracer");
      Span span = tracer.spanBuilder("my.span").startSpan();
      try (Scope scope = span.makeCurrent()) {
        // Do processing, adding events that will be captured in a my.span.

        // Add an event with attributes.
        Attributes eventAttributes = Attributes.of(
          AttributeKey.stringKey("key"), "run",
          AttributeKey.longKey("result"), Long.valueOf(123));

        span.addEvent("testEventWithAttributes", eventAttributes);
        span.setAttribute("testAttribute", "value");

      } finally {
        span.end();
      }
      return "success";
    }
  }
$$;
Copy

Java의 예

저장 프로시저 예제

CREATE OR REPLACE PROCEDURE do_tracing()
RETURNS STRING
LANGUAGE JAVA
RUNTIME_VERSION = '11'
PACKAGES=('com.snowflake:snowpark:latest', 'com.snowflake:telemetry:latest')
HANDLER = 'ProcedureHandler.run'
AS
$$
import com.snowflake.snowpark_java.Session;
import com.snowflake.telemetry.Telemetry;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;

public class ProcedureHandler {

  public String run(Session session) {

    // Set span attribute.
    Telemetry.setSpanAttribute("example.proc.do_tracing", "begin");

    // Add an event without attributes.
    Telemetry.addEvent("run_method_start");

    // Add an event with attributes.
    Attributes eventAttributes = Attributes.of(
      AttributeKey.stringKey("example.method.name"), "run",
      AttributeKey.longKey("example.long"), Long.valueOf(123));
    Telemetry.addEvent("event_with_attributes", eventAttributes);

    // Set span attribute.
    Telemetry.setSpanAttribute("example.proc.do_tracing", "complete");

    return "SUCCESS";
  }
}
$$;
Copy

UDF 예제

CREATE OR REPLACE FUNCTION add_two_numbers(A FLOAT, B FLOAT) RETURNS FLOAT
LANGUAGE JAVA
PACKAGES=('com.snowflake:telemetry:latest')
HANDLER = 'ScalarFunctionHandler.run'
AS
$$
import com.snowflake.telemetry.Telemetry;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.common.AttributesBuilder;

class ScalarFunctionHandler {

  public static Double run(Double d0, Double d1) {

    // Set span attribute.
    Telemetry.setSpanAttribute("example.func.add_two_numbers", "begin");

    // Add an event without attributes.
    Telemetry.addEvent("run_method_start");

    // Add an event with attributes.
    Attributes eventAttributes = Attributes.of(
      AttributeKey.stringKey("example.method.name"), "run",
      AttributeKey.longKey("example.long"), Long.valueOf(123));
    Telemetry.addEvent("event_with_attributes", eventAttributes);

    Double response = d0 == null || d1 == null ? null : (d0 + d1);

    // Set span attribute.
    Telemetry.setSpanAttribute("example.func.add_two_numbers.response", response);
    Telemetry.setSpanAttribute("example.func.add_two_numbers", "complete");

    return response;
  }
}
$$;
Copy

UDTF 예제

CREATE OR REPLACE FUNCTION digits_of_number(x int)
RETURNS TABLE(result int)
LANGUAGE JAVA
PACKAGES=('com.snowflake:telemetry:latest')
HANDLER = 'TableFunctionHandler'
AS
$$
import com.snowflake.telemetry.Telemetry;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.common.AttributesBuilder;
import java.util.stream.Stream;

public class TableFunctionHandler {

  public TableFunctionHandler() {
    // Set span attribute.
    Telemetry.setSpanAttribute("example.func.digits_of_number", "begin");
  }

  static class OutputRow {
    public int result;

    public OutputRow(int result) {
      this.result = result;
    }
  }

  public static Class getOutputClass() {
    return OutputRow.class;
  }

  public Stream<OutputRow> process(int input) {

    // Add an event with attributes.
    Attributes eventAttributes = Attributes.of(
      AttributeKey.longKey("example.received.value"), Long.valueOf(input));
    Telemetry.addEvent("digits_of_number", eventAttributes);

    Stream.Builder<OutputRow> stream = Stream.builder();
    while (input > 0) {

      stream.add(new OutputRow(input %10));
      input /= 10;
    }

    // Set span attribute.
    Telemetry.setSpanAttribute("example.func.digits_of_number", "complete");

    return stream.build();
  }
}
$$;
Copy