콘텐츠로 이동

외부 데이터 소스


DataFlux Func를 통해 MySQL, Prometheus 등 다양한 유형의 외부 데이터 소스를 Guance에 연결할 수 있습니다. 또한 TiDB Cloud Lake에 직접 연결하여 데이터의 통합 조회 및 시각화를 지원합니다.

기능

  • 네이티브 쿼리: 차트에서 데이터 소스의 네이티브 쿼리 문을 직접 사용하며, 별도의 변환이 필요하지 않습니다.
  • 데이터 보호: Func 데이터 소스의 연결 정보는 로컬 Func에 저장됩니다. TiDB Cloud Lake의 Lake DSN은 플랫폼에서 암호화되어 저장되며, 비밀번호와 전체 DSN은 목록, 상세 정보 및 조회에 표시되지 않습니다.
  • 사용자 정의 관리: 실제 필요에 따라 다양한 외부 데이터 소스를 쉽게 추가하고 관리할 수 있습니다.
  • 실시간 데이터: 외부 데이터 소스에 직접 연결하여 실시간으로 데이터를 가져오고, 즉시 응답하여 의사 결정을 내릴 수 있습니다.

연결 방식

연결 방식 적용 가능한 데이터 소스 설명
DataFlux Func를 통한 연결 MySQL, Prometheus 등 이미 배포된 DataFlux Func 및 Connector를 재사용하며, ID 등 기존 구성은 변경하지 않고 유지해야 합니다.
TiDB Cloud Lake 직접 연결 TiDB Cloud Lake Guance 서버가 TiDB Cloud Lake Driver를 통해 연결하며, DataFlux Func에 의존하지 않고 데이터 소스 ID를 입력할 필요도 없습니다.

TiDB Cloud Lake에 직접 연결해야 하는 경우 TiDB Cloud Lake 연결 및 쿼리를 참조하세요.

DataFlux Func를 통한 연결

Guance 측에서 데이터 소스 추가

확장에서 직접 연결된 DataFlux Func를 추가하거나 확인하여 모든 연결된 외부 데이터 소스를 더 관리할 수 있습니다.

참고

이 방식은 두 번째 방법보다 초보자에게 친숙하므로 권장합니다.

  1. 드롭다운에서 DataFlux Func를 선택합니다.
  2. 지원하는 데이터 소스 유형을 선택합니다.
  3. 연결 속성을 정의합니다. ID, 데이터 소스 제목, 연결된 호스트, 포트, 데이터베이스, 사용자, 비밀번호를 포함합니다.
  4. 필요에 따라 연결을 테스트합니다.
  5. 저장합니다.

Func를 사용하여 외부 데이터 소스 쿼리

참고

여기서 말하는 "외부 데이터 소스"는 광범위한 정의를 가지며, 일반적인 외부 데이터 저장 시스템(MySQL, Redis 등 데이터베이스)뿐만 아니라 타사 시스템(예: Guance 콘솔)도 포함합니다.

전제 조건

해당 설치 패키지를 다운로드하고 빠른 시작에 따라 Func 플랫폼을 배포해야 합니다.

배포가 완료되면 초기화가 완료될 때까지 기다렸다가 플랫폼에 로그인합니다.

Func와 Guance 연결

커넥터를 통해 개발자는 Guance 시스템에 연결할 수 있습니다.

개발 > 커넥터 > 커넥터 추가 페이지로 이동합니다:

  1. 커넥터 유형을 선택합니다.
  2. 이 커넥터의 ID를 사용자 정의합니다.
  3. 제목을 추가합니다. 이 제목은 Guance 워크스페이스에 동기화되어 표시됩니다.
  4. 필요에 따라 이 커넥터에 대한 설명을 입력합니다.
  5. Guance 노드를 선택합니다.
  6. API Key ID 및 API Key를 추가합니다.
  7. 필요에 따라 연결 가능성을 테스트합니다.
  8. 저장합니다.

연결이 완료되면 Func 플랫폼에서 다음 두 가지 방식으로 데이터 소스를 쿼리할 수 있습니다:

API Key를 가져오는 방법
  1. Guance 워크스페이스 > 관리 > API Key 관리로 이동합니다.
  2. 페이지 오른쪽의 Key 생성을 클릭합니다.
  3. 이름을 입력합니다.
  4. 확인을 클릭합니다. 시스템이 자동으로 API Key를 생성하며, API Key에서 확인할 수 있습니다.

자세한 내용은 API Key 관리를 참조하세요.

커넥터 사용

커넥터를 정상적으로 추가한 후에는 스크립트에서 커넥터 ID를 사용하여 해당 커넥터의 작업 객체를 가져올 수 있습니다.

위의 커넥터를 예로 들어, 이 커넥터의 작업 객체를 가져오는 코드는 다음과 같습니다:

mysql = DFF.CONN('mysql')

직접 스크립트 작성

커넥터를 사용하는 것 외에도, 직접 함수를 작성하여 데이터를 쿼리할 수 있습니다.

사용자가 MySQL 커넥터(정의 ID가 mysql임)를 올바르게 생성했고, 이 MySQL에 my_table이라는 테이블이 있으며 다음과 같은 데이터가 포함되어 있다고 가정합니다:

id userId username reqMethod reqRoute reqCost createTime
1 u-001 admin POST /api/v1/scripts/:id/do/modify 23 1730840906
2 u-002 admin POST /api/v1/scripts/:id/do/publish 99 1730840906
3 u-003 zhang3 POST /api/v1/scripts/:id/do/publish 3941 1730863223
4 u-004 zhang3 POST /api/v1/scripts/:id/do/publish 159 1730863244
5 u-005 li4 POST /api/v1/scripts/:id/do/publish 44 1730863335
...

이때 데이터 쿼리 함수를 사용하여 이 테이블의 데이터를 쿼리해야 하며, 필드 추출 규칙은 다음과 같다고 가정합니다:

원본 필드 추출 대상
createTime 시간 time
reqCost req_cost
reqMethod req_method
reqRoute req_route
userId 태그 user_id
username 태그 username

이 경우 전체 참조 코드는 다음과 같습니다:

  • 데이터 쿼리 함수 예시
import json

@DFF.API('my_table 데이터 쿼리', category='dataPlatform.dataQueryFunc')
def query_from_my_table(time_range):
    # 커넥터 작업 객체 가져오기
    mysql = DFF.CONN('mysql')

    # MySQL 쿼리문
    sql = '''
      SELECT
        createTime, userId, username, reqMethod, reqRoute, reqCost
      FROM
        my_table
      WHERE
        createTime     > ?
        AND createTime < ?
      LIMIT 5
    '''

    # 전달된 time_range의 단위는 밀리초(ms)
    # MySQL의 createTime 필드 단위는 초(s)이므로 변환 필요
    sql_params = [
      int(time_range[0] / 1000),
      int(time_range[1] / 1000),
    ]

    # 쿼리 실행
    db_res = mysql.query(sql, sql_params)

    # DQL과 유사한 반환 결과로 변환

    # 태그에 따라 여러 데이터 시계열을 생성해야 할 수 있음
    # 데이터 시계열 태그를 Key로 사용하여 매핑 테이블 생성
    series_map = {}

    # 원본 데이터를 순회하며 구조를 변환하여 매핑 테이블에 저장
    for d in db_res:
        # 태그 수집
        tags = {
            'user_id' : d.get('userId'),
            'username': d.get('username'),
        }

        # 태그 직렬화 (tag key 정렬 필요, 출력 일관성 보장)
        tags_dump = json.dumps(tags, sort_keys=True, ensure_ascii=True)

        # 이 태그의 데이터 시리즈가 아직 생성되지 않은 경우 생성
        if tags_dump not in series_map:
            # 데이터 시리즈 series 기본 구조
            series_map[tags_dump] = {
                'columns': [ 'time', 'req_cost', 'req_method', 'req_route' ], # 열 (첫 번째 열은 항상 time)
                'tags'   : tags,                                              # 태그
                'values' : [],                                                # 값 목록
            }

        # 시간, 열 추출 후 value에 추가
        series = series_map[tags_dump]
        value = [
            d.get('createTime') * 1000, # 시간 time (출력 단위는 밀리초(ms), 실제에 따라 변환 필요)
            d.get('reqCost'),           # 열 req_cost
            d.get('reqMethod'),         # 열 req_method
            d.get('reqRoute'),          # 열 req_route
        ]
        series['values'].append(value)

    # DQL 외부 구조 추가
    dql_like_res = {
        # 데이터 시리즈
        'series': [ list(series_map.values()) ] # 배열을 한 번 더 감싸는 것에 주의
    }
    return dql_like_res

데이터 변환 처리에만 관심이 있고 쿼리 과정은 중요하지 않다면(또는 실제 데이터베이스가 없어도 되는 경우), 다음 코드를 참조할 수 있습니다:

  • 데이터 쿼리 함수 예시 (MySQL 쿼리 부분 제외)
import json

@DFF.API('어딘가의 데이터 쿼리', category='dataPlatform.dataQueryFunc')
def query_from_somewhere(time_range):
    # 어떤 방식으로든 원본 데이터를 가져왔다고 가정
    db_res = [
        {'createTime': 1730840906, 'reqCost': 23,   'reqMethod': 'POST', 'reqRoute': '/api/v1/scripts/:id/do/modify',  'username': 'admin',  'userId': 'u-001'},
        {'createTime': 1730840906, 'reqCost': 99,   'reqMethod': 'POST', 'reqRoute': '/api/v1/scripts/:id/do/publish', 'username': 'admin',  'userId': 'u-001'},
        {'createTime': 1730863223, 'reqCost': 3941, 'reqMethod': 'POST', 'reqRoute': '/api/v1/scripts/:id/do/publish', 'username': 'zhang3', 'userId': 'u-002'},
        {'createTime': 1730863244, 'reqCost': 159,  'reqMethod': 'POST', 'reqRoute': '/api/v1/scripts/:id/do/publish', 'username': 'zhang3', 'userId': 'u-002'},
        {'createTime': 1730863335, 'reqCost': 44,   'reqMethod': 'POST', 'reqRoute': '/api/v1/scripts/:id/do/publish', 'username': 'li4',    'userId': 'u-003'}
    ]

    # DQL과 유사한 반환 결과로 변환

    # 태그에 따라 여러 데이터 시계열을 생성해야 할 수 있음
    # 데이터 시계열 태그를 Key로 사용하여 매핑 테이블 생성
    series_map = {}

    # 원본 데이터를 순회하며 구조를 변환하여 매핑 테이블에 저장
    for d in db_res:
        # 태그 수집
        tags = {
            'user_id' : d.get('userId'),
            'username': d.get('username'),
        }

        # 태그 직렬화 (tag key 정렬 필요, 출력 일관성 보장)
        tags_dump = json.dumps(tags, sort_keys=True, ensure_ascii=True)

        # 이 태그의 데이터 시리즈가 아직 생성되지 않은 경우 생성
        if tags_dump not in series_map:
            # 데이터 시리즈 series 기본 구조
            series_map[tags_dump] = {
                'columns': [ 'time', 'req_cost', 'req_method', 'req_route' ], # 열 (첫 번째 열은 항상 time)
                'tags'   : tags,                                              # 태그
                'values' : [],                                                # 값 목록
            }

        # 시간, 열 추출 후 value에 추가
        series = series_map[tags_dump]
        value = [
            d.get('createTime') * 1000, # 시간 time (출력 단위는 밀리초(ms), 실제에 따라 변환 필요)
            d.get('reqCost'),           # 열 req_cost
            d.get('reqMethod'),         # 열 req_method
            d.get('reqRoute'),          # 열 req_route
        ]
        series['values'].append(value)

    # DQL 외부 구조 추가
    dql_like_res = {
        # 데이터 시리즈
        'series': [ list(series_map.values()) ] # 배열을 한 번 더 감싸는 것에 주의
    }
    return dql_like_res
  • 반환 결과 예시
{
  "series": [
    [
      {
        "columns": ["time", "req_cost", "req_method", "req_route"],
        "tags": {"user_id": "u-001", "username": "admin"},
        "values": [
          [1730840906000, 23, "POST", "/api/v1/scripts/:id/do/modify" ],
          [1730840906000, 99, "POST", "/api/v1/scripts/:id/do/publish"]
        ]
      },
      {
        "columns": ["time", "req_cost", "req_method", "req_route"],
        "tags": {"user_id": "u-002", "username": "zhang3"},
        "values": [
          [1730863223000, 3941, "POST", "/api/v1/scripts/:id/do/publish"],
          [1730863244000,  159, "POST", "/api/v1/scripts/:id/do/publish"]
        ]
      },
      {
        "columns": ["time", "req_cost", "req_method", "req_route"],
        "tags": {"user_id": "u-003", "username": "li4"},
        "values": [
          [1730863335000, 44, "POST", "/api/v1/scripts/:id/do/publish"]
        ]
      }
    ]
  ]
}

관리 목록

연결된 모든 데이터 소스는 통합 > 외부 데이터 소스 > 연결된 데이터 소스에서 확인할 수 있습니다.

목록에서 다음 작업을 수행할 수 있습니다:

  • 데이터 소스 유형, ID, 상태, 생성 정보 및 업데이트 정보 등을 확인합니다.
  • 특정 데이터 소스를 편집합니다. DataFlux Func, 데이터 소스 유형 및 ID를 제외한 구성을 수정할 수 있습니다.
  • 특정 데이터 소스를 삭제합니다.

사용 사례

Guance에서 외부 데이터 소스를 사용하여 쿼리하는 일반적인 시나리오 중 하나는 차트 > 차트 쿼리입니다.

서로 다른 차트의 데이터 반환
꺾은선형 차트 원형 차트 테이블 차트

문서 평가

이 페이지가 도움이 되었나요?