# `IssueDataLakeQuery`는 해당 작업의 별칭입니다
mutation IssueDataLakeQuery {
executeDataLakeQuery(input: {
sql: "select * from panther_logs.public.aws_alb limit 50"
}) {
id # 쿼리의 고유 ID
}
}
# `IssueIndicatorSearchQuery`는 해당 작업의 별칭입니다
mutation IssueIndicatorSearchQuery {
executeIndicatorSearchQuery(input: {
indicators: ["286103014039", "126103014049"]
startTime: "2022-04-01T00:00:00.000Z",
endTime: "2022-04-30T23:59:59.000Z"
indicatorName: p_any_aws_account_ids # 또는 자동 감지를 위해 비워 두세요
}) {
id # 쿼리의 고유 ID
}
}
# `QueryResults`는 해당 작업의 별칭입니다
query QueryResults {
dataLakeQuery(id: "1234-1234-1234-1234") { # 쿼리의 고유 ID
message
status
results {
edges {
node
}
}
}
}
# `QueryResults`는 해당 작업의 별칭입니다
query QueryResults {
dataLakeQuery(id: "1234-1234-1234-1234") { # 쿼리의 고유 ID
message
status
results(input: { cursor: "5678-5678-5678-5678" }) { # `endCursor`의 값
edges {
node
}
pageInfo
endCursor
hasNextPage
}
}
}
# `QueryMetadata`는 해당 작업의 별칭입니다
query QueryMetadata {
dataLakeQuery(id: "1234-1234-1234-1234") { # 쿼리의 고유 ID
name
isScheduled
issuedBy {
... on User {
email
}
... on APIToken {
name
}
}
sql
message
status
startedAt
completedAt
results {
edges {
node
}
}
}
}
# `ListDataLakeQueries`는 해당 작업의 별칭입니다
query ListDataLakeQueries {
dataLakeQueries {
name
isScheduled
issuedBy {
... on User {
email
}
... on APIToken {
name
}
}
sql
message
status
startedAt
completedAt
results { # 각 쿼리의 결과 첫 페이지만 가져옵니다
edges {
node
}
}
}
# `ListDataLakeQueries`는 해당 작업의 별칭입니다
query ListDataLakeQueries {
dataLakeQueries(input: { cursor: "5678-5678-5678-5678" }) { # `endCursor`의 값
name
isScheduled
issuedBy {
... on User {
email
}
... on APIToken {
name
}
}
sql
message
status
startedAt
completedAt
results { # 각 쿼리의 결과 첫 페이지만 가져옵니다
edges {
node
}
}
pageInfo {
endCursor
hasNextPage
}
}
# `ListDataLakeQueries`는 해당 작업의 별칭입니다
query ListDataLakeQueries {
dataLakeQueries(input: { contains: "aws_alb", isScheduled: true }) {
name
isScheduled
issuedBy {
... on User {
email
}
... on APIToken {
name
}
}
sql
message
status
startedAt
completedAt
results { # 각 쿼리의 결과 첫 페이지만 가져옵니다
edges {
node
}
}
}
// npm install graphql graphql-request
import { GraphQLClient, gql } from 'graphql-request';
const client = new GraphQLClient(
'YOUR_PANTHER_API_URL',
{ headers: { 'X-API-Key': 'YOUR_API_KEY' }
});
// `IssueQuery`는 쿼리의 별칭입니다. 완전히 생략할 수 있습니다.
const issueQuery = gql`
mutation IssueQuery($sql: String!) {
executeDataLakeQuery(input: { sql: $sql }) {
id
}
}
`;
// `GetQueryResults`는 쿼리의 별칭입니다. 완전히 생략할 수 있습니다.
const getQueryResults = gql`
query GetQueryResults($id: ID!, $cursor: String) {
dataLakeQuery(id: $id) {
message
status
results(input: { cursor: $cursor }) {
edges {
node
}
pageInfo {
endCursor
hasNextPage
}
}
}
}
`;
(async () => {
try {
// 가져오는 모든 결과 노드를 보관하는 누산기
let allResults = [];
// 루프를 언제 종료할지 알기 위한 헬퍼
let hasMore = true;
// 페이지네이션 커서
let cursor = null;
// 쿼리 실행
const mutationData = await client.request(issueQuery, {
sql: 'select * from panther_logs.public.aws_alb limit 5',
});
// 쿼리가 결과를 반환할 때까지 폴링을 시작합니다. 그다음,
// 더 이상 남은 페이지가 없을 때까지 계속 가져옵니다
do {
const queryData = await client.request(getQueryResults, {
id: mutationData.executeDataLakeQuery.id,
cursor,
});
// 아직 실행 중이면 메시지를 출력하고 폴링을 계속합니다
if (queryData.dataLakeQuery.status === 'running') {
console.log(queryData.dataLakeQuery.message);
continue;
}
// 실행 중도 아니고 완료도 아니라면,
// 취소되었거나 오류가 발생한 것입니다. 이 경우,
// 예외를 발생시킵니다
if (queryData.dataLakeQuery.status !== 'succeeded') {
throw new Error(queryData.dataLakeQuery.message);
}
allResults = [...allResults, ...queryData.dataLakeQuery.results.edges.map(edge => edge.node)ាស់];
hasMore = queryData.dataLakeQuery.results.pageInfo.hasNextPage;
cursor = queryData.dataLakeQuery.results.pageInfo.endCursor;
} while (hasMore);
console.log(`쿼리에서 ${allResults.length}개의 결과가 반환되었습니다!`);
} catch (err) {
console.error(err.response);
}
})();
# pip install gql aiohttp
from gql import gql, Client
from gql.transport.aiohttp import AIOHTTPTransport
transport = AIOHTTPTransport(
url="YOUR_PANTHER_API_URL",
headers={"X-API-Key": "YOUR_API_KEY"}
)
client = Client(transport=transport, fetch_schema_from_transport=True)
# `IssueQuery`는 쿼리의 별칭입니다. 완전히 생략할 수 있습니다.
issue_query = gql(
"""
mutation IssueQuery($sql: String!) {
executeDataLakeQuery(input: { sql: $sql }) {
id
}
}
"""
)
# `GetQueryResults`는 쿼리의 별칭입니다. 완전히 생략할 수 있습니다.
get_query_results = gql(
"""
query GetQueryResults($id: ID!, $cursor: String) {
dataLakeQuery(id: $id) {
message
status
results(input: { cursor: $cursor }) {
edges {
node
}
pageInfo {
endCursor
hasNextPage
}
}
}
}
"""
)
# 모든 페이지에서 가져오는 모든 결과를 보관하는 누산기
all_results = []
# 루프를 언제 종료할지 알기 위한 도우미.
has_more = True
# 페이지네이션 커서
cursor = None
# 데이터 레이크(Data Explorer) 쿼리 실행
mutation_data = client.execute(
issue_query,
variable_values={
"sql": "select * from panther_logs.public.aws_alb limit 5"
}
)
# 쿼리가 결과를 반환할 때까지 폴링을 시작합니다. 그다음,
# 더 이상 남은 페이지가 없을 때까지 계속 가져옵니다
while has_more:
query_data = client.execute(
get_query_results,
variable_values = {
"id": mutation_data["executeDataLakeQuery"]["id"],
"cursor": cursor
}
)
# 아직 실행 중이면 메시지를 출력하고 폴링을 계속합니다
if query_data["dataLakeQuery"]["status"] == "running":
print(query_data["dataLakeQuery"]["message"])
continue
# 실행 중도 아니고 완료도 아니라면,
# 취소되었거나 오류가 발생한 것입니다. 이 경우,
# 예외를 발생시킵니다
if query_data["dataLakeQuery"]["status"] != "succeeded":
raise Exception(query_data["dataLakeQuery"]["message"])
all_results.extend([edge["node"] for edge in query_data["dataLakeQuery"]["results"]["edges"]])
has_more = query_data["dataLakeQuery"]["results"]["pageInfo"]["hasNextPage"]
cursor = query_data["dataLakeQuery"]["results"]["pageInfo"]["endCursor"]
print(f'쿼리에서 {len(all_results)}개의 결과가 반환되었습니다!')
// npm install graphql graphql-request
import { GraphQLClient, gql } from 'graphql-request';
const client = new GraphQLClient(
'YOUR_PANTHER_API_URL',
{ headers: { 'X-API-Key': 'YOUR_API_KEY' }
});
// `IssueQuery`는 쿼리의 별칭입니다. 완전히 생략할 수 있습니다.
const issueQuery = gql`
mutation IssueQuery($input: ExecuteIndicatorSearchQueryInput!) {
executeIndicatorSearchQuery(input: $input) {
id
}
}
`;
// `GetQueryResults`는 쿼리의 별칭입니다. 완전히 생략할 수 있습니다.
const getQueryResults = gql`
query GetQueryResults($id: ID!, $cursor: String) {
dataLakeQuery(id: $id) {
message
status
results(input: { cursor: $cursor }) {
edges {
node
}
pageInfo {
endCursor
hasNextPage
}
}
}
}
`;
(async () => {
try {
// 가져오는 모든 결과 노드를 보관하는 누산기
let allResults = [];
// 루프를 언제 종료할지 알기 위한 헬퍼
let hasMore = true;
// 페이지네이션 커서
let cursor = null;
// 쿼리 실행
const mutationData = await client.request(issueQuery, {
input: {
indicators: ["226103014039"],
startTime: "2022-03-29T00:00:00.001Z",
endTime: "2022-03-30T00:00:00.001Z",
indicatorName: "p_any_aws_account_ids"
}
});
// 더 이상 남은 페이지가 없을 때까지 계속 가져오기
do {
const queryData = await client.request(getQueryResults, {
id: mutationData.executeIndicatorSearchQuery.id,
cursor,
});
// 아직 실행 중이면 메시지를 출력하고 폴링을 계속합니다
if (queryData.dataLakeQuery.status === 'running') {
console.log(queryData.dataLakeQuery.message);
continue;
}
// 실행 중도 아니고 완료도 아니라면,
// 취소되었거나 오류가 발생한 것입니다. 이 경우,
// 예외를 발생시킵니다
if (queryData.dataLakeQuery.status !== 'succeeded') {
throw new Error(queryData.dataLakeQuery.message);
}
allResults = [...allResults, ...queryData.dataLakeQuery.results.edges.map(edge => edge.node)ាស់];
hasMore = queryData.dataLakeQuery.results.pageInfo.hasNextPage;
cursor = queryData.dataLakeQuery.results.pageInfo.endCursor;
} while (hasMore);
console.log(`쿼리에서 ${allResults.length}개의 결과가 반환되었습니다!`);
} catch (err) {
console.error(err.response);
}
})();
# pip install gql aiohttp
from gql import gql, Client
from gql.transport.aiohttp import AIOHTTPTransport
transport = AIOHTTPTransport(
url="YOUR_PANTHER_API_URL",
headers={"X-API-Key": "YOUR_API_KEY"}
)
client = Client(transport=transport, fetch_schema_from_transport=True)
# `IssueQuery`는 쿼리의 별칭입니다. 완전히 생략할 수 있습니다.
issue_query = gql(
"""
mutation IssueQuery($input: ExecuteIndicatorSearchQueryInput!) {
executeIndicatorSearchQuery(input: $input) {
id
}
}
"""
)
# `GetQueryResults`는 쿼리의 별칭입니다. 완전히 생략할 수 있습니다.
get_query_results = gql(
"""
query GetQueryResults($id: ID!, $cursor: String) {
dataLakeQuery(id: $id) {
message
status
results(input: { cursor: $cursor }) {
edges {
node
}
pageInfo {
endCursor
hasNextPage
}
}
}
}
"""
)
# 모든 페이지에서 가져오는 모든 결과를 보관하는 누산기
all_results = []
# 루프를 언제 종료할지 알기 위한 헬퍼
has_more = True
# 페이지네이션 커서
cursor = None
# Indicator Search 쿼리 실행
mutation_data = client.execute(
issue_query,
variable_values={
"input": {
"indicators": ["226103014039"],
"startTime": "2022-03-29T00:00:00.001Z",
"endTime": "2022-03-30T00:00:00.001Z",
"indicatorName": "p_any_aws_account_ids"
}
}
)
# 쿼리가 결과를 반환할 때까지 폴링을 시작합니다. 그다음,
# 더 이상 남은 페이지가 없을 때까지 계속 가져옵니다
while has_more:
query_data = client.execute(
get_query_results,
variable_values = {
"id": mutation_data["executeIndicatorSearchQuery"]["id",
"cursor": cursor
}
)
# 아직 실행 중이면 메시지를 출력하고 폴링을 계속합니다
if query_data["dataLakeQuery"]["status"] == "running":
print(query_data["dataLakeQuery"]["message"])
continue
# 실행 중도 아니고 완료도 아니라면,
# 취소되었거나 오류가 발생한 것입니다. 이 경우,
# 예외를 발생시킵니다
if query_data["dataLakeQuery"]["status"] != "succeeded":
raise Exception(query_data["dataLakeQuery"]["message"])
all_results.extend([edge["node"] for edge in query_data["dataLakeQuery"]["results"]["edges"]])
has_more = query_data["dataLakeQuery"]["results"]["pageInfo"]["hasNextPage"]
cursor = query_data["dataLakeQuery"]["results"]["pageInfo"]["endCursor"]
print(f'쿼리에서 {len(all_results)}개의 결과가 반환되었습니다!')