# `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
}
}
# `AbandonQuery`는 이 작업의 별칭입니다
mutation AbandonQuery {
cancelDataLakeQuery(input: { id: "1234-5678" }) {
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
이름
isScheduled
issuedBy {
... on User {
email
}
... on APIToken {
이름
}
}
sql
message
status
startedAt
completedAt
results {
edges {
node
}
}
}
}
# `ListDataLakeQueries`는 이 작업의 별칭입니다
query ListDataLakeQueries {
dataLakeQueries {
이름
isScheduled
issuedBy {
... on User {
email
}
... on APIToken {
이름
}
}
sql
message
status
startedAt
completedAt
results { # 각 쿼리에 대해 첫 페이지 결과만 가져옴
edges {
node
}
}
}
# `ListDataLakeQueries`는 이 작업의 별칭입니다
query ListDataLakeQueries {
dataLakeQueries(input: { cursor: "5678-5678-5678-5678" }) { # `endCursor`의 값
이름
isScheduled
issuedBy {
... on User {
email
}
... on APIToken {
이름
}
}
sql
message
status
startedAt
completedAt
results { # 각 쿼리에 대해 첫 페이지 결과만 가져옴
edges {
node
}
}
pageInfo {
endCursor
hasNextPage
}
}
# `ListDataLakeQueries`는 이 작업의 별칭입니다
query ListDataLakeQueries {
dataLakeQueries(input: { contains: "aws_alb", isScheduled: true }) {
이름
isScheduled
issuedBy {
... on User {
email
}
... on APIToken {
이름
}
}
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(`Your query returned ${allResults.length} result(s)!`);
} 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'Query returned {len(all_results)} results(s)!')
// 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(`Your query returned ${allResults.length} result(s)!`);
} 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'Query returned {len(all_results)} results(s)!')