mirror of
https://github.com/grafana/grafana.git
synced 2025-02-20 11:48:34 -06:00
* Adding plugin state feature to transforms * initial help box * New HelpBox component * More progress * Testing * Removing HelpBox, simple new design, new active state for OperationRowAction * Updated tests * Fixed typing issue * Removed AlphaNotice * Made focus and enter key trigger OnClick and sorted transformations * Fixed e2e tests
277 lines
9.2 KiB
TypeScript
277 lines
9.2 KiB
TypeScript
import React, { PureComponent } from 'react';
|
|
import { stripIndent, stripIndents } from 'common-tags';
|
|
import { QueryEditorHelpProps } from '@grafana/data';
|
|
import Prism from 'prismjs';
|
|
import tokenizer from '../syntax';
|
|
import { flattenTokens } from '@grafana/ui/src/slate-plugins/slate-prism';
|
|
import { css, cx } from '@emotion/css';
|
|
import { CloudWatchQuery } from '../types';
|
|
|
|
interface QueryExample {
|
|
category: string;
|
|
examples: Array<{
|
|
title: string;
|
|
expr: string;
|
|
}>;
|
|
}
|
|
|
|
const CLIQ_EXAMPLES: QueryExample[] = [
|
|
{
|
|
category: 'Lambda',
|
|
examples: [
|
|
{
|
|
title: 'View latency statistics for 5-minute intervals',
|
|
expr: stripIndents`filter @type = "REPORT" |
|
|
stats avg(@duration), max(@duration), min(@duration) by bin(5m)`,
|
|
},
|
|
{
|
|
title: 'Determine the amount of overprovisioned memory',
|
|
expr: stripIndent`
|
|
filter @type = "REPORT" |
|
|
stats max(@memorySize / 1024 / 1024) as provisonedMemoryMB,
|
|
min(@maxMemoryUsed / 1024 / 1024) as smallestMemoryRequestMB,
|
|
avg(@maxMemoryUsed / 1024 / 1024) as avgMemoryUsedMB,
|
|
max(@maxMemoryUsed / 1024 / 1024) as maxMemoryUsedMB,
|
|
provisonedMemoryMB - maxMemoryUsedMB as overProvisionedMB`,
|
|
},
|
|
{
|
|
title: 'Find the most expensive requests',
|
|
expr: stripIndents`filter @type = "REPORT" |
|
|
fields @requestId, @billedDuration |
|
|
sort by @billedDuration desc`,
|
|
},
|
|
],
|
|
},
|
|
|
|
{
|
|
category: 'VPC Flow Logs',
|
|
examples: [
|
|
{
|
|
title: 'Average, min, and max byte transfers by source and destination IP addresses',
|
|
expr: `stats avg(bytes), min(bytes), max(bytes) by srcAddr, dstAddr`,
|
|
},
|
|
{
|
|
title: 'IP addresses using UDP transfer protocol',
|
|
expr: 'filter protocol=17 | stats count(*) by srcAddr',
|
|
},
|
|
{
|
|
title: 'Top 10 byte transfers by source and destination IP addresses',
|
|
expr: stripIndents`stats sum(bytes) as bytesTransferred by srcAddr, dstAddr |
|
|
sort bytesTransferred desc |
|
|
limit 10`,
|
|
},
|
|
{
|
|
title: 'Top 20 source IP addresses with highest number of rejected requests',
|
|
expr: stripIndents`filter action="REJECT" |
|
|
stats count(*) as numRejections by srcAddr |
|
|
sort numRejections desc |
|
|
limit 20`,
|
|
},
|
|
],
|
|
},
|
|
{
|
|
category: 'CloudTrail',
|
|
examples: [
|
|
{
|
|
title: 'Number of log entries by service, event type, and region',
|
|
expr: 'stats count(*) by eventSource, eventName, awsRegion',
|
|
},
|
|
|
|
{
|
|
title: 'Number of log entries by region and EC2 event type',
|
|
expr: stripIndents`filter eventSource="ec2.amazonaws.com" |
|
|
stats count(*) as eventCount by eventName, awsRegion |
|
|
sort eventCount desc`,
|
|
},
|
|
|
|
{
|
|
title: 'Regions, usernames, and ARNs of newly created IAM users',
|
|
expr: stripIndents`filter eventName="CreateUser" |
|
|
fields awsRegion, requestParameters.userName, responseElements.user.arn`,
|
|
},
|
|
],
|
|
},
|
|
{
|
|
category: 'Common Queries',
|
|
examples: [
|
|
{
|
|
title: '25 most recently added log events',
|
|
expr: stripIndents`fields @timestamp, @message |
|
|
sort @timestamp desc |
|
|
limit 25`,
|
|
},
|
|
{
|
|
title: 'Number of exceptions logged every 5 minutes',
|
|
expr: stripIndents`filter @message like /Exception/ |
|
|
stats count(*) as exceptionCount by bin(5m) |
|
|
sort exceptionCount desc`,
|
|
},
|
|
{
|
|
title: 'List of log events that are not exceptions',
|
|
expr: 'fields @message | filter @message not like /Exception/',
|
|
},
|
|
],
|
|
},
|
|
{
|
|
category: 'Route 53',
|
|
examples: [
|
|
{
|
|
title: 'Number of requests received every 10 minutes by edge location',
|
|
expr: 'stats count(*) by queryType, bin(10m)',
|
|
},
|
|
{
|
|
title: 'Number of unsuccessful requests by domain',
|
|
expr: 'filter responseCode="SERVFAIL" | stats count(*) by queryName',
|
|
},
|
|
{
|
|
title: 'Number of requests received every 10 minutes by edge location',
|
|
expr: 'stats count(*) as numRequests by resolverIp | sort numRequests desc | limit 10',
|
|
},
|
|
],
|
|
},
|
|
{
|
|
category: 'AWS AppSync',
|
|
examples: [
|
|
{
|
|
title: 'Number of unique HTTP status codes',
|
|
expr: stripIndents`fields ispresent(graphQLAPIId) as isApi |
|
|
filter isApi |
|
|
filter logType = "RequestSummary" |
|
|
stats count() as statusCount by statusCode |
|
|
sort statusCount desc`,
|
|
},
|
|
{
|
|
title: 'Top 10 resolvers with maximum latency',
|
|
expr: stripIndents`fields resolverArn, duration |
|
|
filter logType = "Tracing" |
|
|
sort duration desc |
|
|
limit 10`,
|
|
},
|
|
{
|
|
title: 'Most frequently invoked resolvers',
|
|
expr: stripIndents`fields ispresent(resolverArn) as isRes |
|
|
stats count() as invocationCount by resolverArn |
|
|
filter isRes |
|
|
filter logType = "Tracing" |
|
|
sort invocationCount desc |
|
|
limit 10`,
|
|
},
|
|
{
|
|
title: 'Resolvers with most errors in mapping templates',
|
|
expr: stripIndents`fields ispresent(resolverArn) as isRes |
|
|
stats count() as errorCount by resolverArn, logType |
|
|
filter isRes and (logType = "RequestMapping" or logType = "ResponseMapping") and fieldInError |
|
|
sort errorCount desc |
|
|
limit 10`,
|
|
},
|
|
{
|
|
title: 'Field latency statistics',
|
|
expr: stripIndents`fields requestId, latency |
|
|
filter logType = "RequestSummary" |
|
|
sort latency desc |
|
|
limit 10`,
|
|
},
|
|
{
|
|
title: 'Resolver latency statistics',
|
|
expr: stripIndents`fields ispresent(resolverArn) as isRes |
|
|
filter isRes |
|
|
filter logType = "Tracing" |
|
|
stats min(duration), max(duration), avg(duration) as avgDur by resolverArn |
|
|
sort avgDur desc |
|
|
limit 10`,
|
|
},
|
|
{
|
|
title: 'Top 10 requests with maximum latency',
|
|
expr: stripIndents`fields requestId, latency |
|
|
filter logType = "RequestSummary" |
|
|
sort latency desc |
|
|
limit 10`,
|
|
},
|
|
],
|
|
},
|
|
];
|
|
|
|
function renderHighlightedMarkup(code: string, keyPrefix: string) {
|
|
const grammar = tokenizer;
|
|
const tokens = flattenTokens(Prism.tokenize(code, grammar));
|
|
const spans = tokens
|
|
.filter((token) => typeof token !== 'string')
|
|
.map((token, i) => {
|
|
return (
|
|
<span
|
|
className={`prism-token token ${token.types.join(' ')} ${token.aliases.join(' ')}`}
|
|
key={`${keyPrefix}-token-${i}`}
|
|
>
|
|
{token.content}
|
|
</span>
|
|
);
|
|
});
|
|
|
|
return <div className="slate-query-field">{spans}</div>;
|
|
}
|
|
|
|
const exampleCategory = css`
|
|
margin-top: 5px;
|
|
`;
|
|
|
|
export default class LogsCheatSheet extends PureComponent<
|
|
QueryEditorHelpProps<CloudWatchQuery>,
|
|
{ userExamples: string[] }
|
|
> {
|
|
onClickExample(query: CloudWatchQuery) {
|
|
this.props.onClickExample(query);
|
|
}
|
|
|
|
renderExpression(expr: string, keyPrefix: string) {
|
|
return (
|
|
<div
|
|
className="cheat-sheet-item__example"
|
|
key={expr}
|
|
onClick={(e) =>
|
|
this.onClickExample({ refId: 'A', expression: expr, queryMode: 'Logs', region: 'default', id: 'A' })
|
|
}
|
|
>
|
|
<pre>{renderHighlightedMarkup(expr, keyPrefix)}</pre>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
renderLogsCheatSheet() {
|
|
return (
|
|
<div>
|
|
<h2>CloudWatch Logs Cheat Sheet</h2>
|
|
{CLIQ_EXAMPLES.map((cat, i) => (
|
|
<div key={`${cat.category}-${i}`}>
|
|
<div className={`cheat-sheet-item__title ${cx(exampleCategory)}`}>{cat.category}</div>
|
|
{cat.examples.map((item, j) => (
|
|
<div className="cheat-sheet-item" key={`item-${j}`}>
|
|
<h4>{item.title}</h4>
|
|
{this.renderExpression(item.expr, `item-${j}`)}
|
|
</div>
|
|
))}
|
|
</div>
|
|
))}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
render() {
|
|
return (
|
|
<div>
|
|
<h3>CloudWatch Logs cheat sheet</h3>
|
|
{CLIQ_EXAMPLES.map((cat, i) => (
|
|
<div key={`cat-${i}`}>
|
|
<div className={`cheat-sheet-item__title ${cx(exampleCategory)}`}>{cat.category}</div>
|
|
{cat.examples.map((item, j) => (
|
|
<div className="cheat-sheet-item" key={`item-${j}`}>
|
|
<h4>{item.title}</h4>
|
|
{this.renderExpression(item.expr, `item-${j}`)}
|
|
</div>
|
|
))}
|
|
</div>
|
|
))}
|
|
</div>
|
|
);
|
|
}
|
|
}
|