mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
CloudWatch: replace full query parser with regex scanner that extracts stats groups (#32610)
This commit is contained in:
parent
ce6e31c030
commit
a9e90b5088
@ -219,7 +219,6 @@
|
|||||||
"@sentry/browser": "5.25.0",
|
"@sentry/browser": "5.25.0",
|
||||||
"@sentry/types": "5.24.2",
|
"@sentry/types": "5.24.2",
|
||||||
"@sentry/utils": "5.24.2",
|
"@sentry/utils": "5.24.2",
|
||||||
"@types/antlr4": "^4.7.1",
|
|
||||||
"@types/braintree__sanitize-url": "4.0.0",
|
"@types/braintree__sanitize-url": "4.0.0",
|
||||||
"@types/common-tags": "^1.8.0",
|
"@types/common-tags": "^1.8.0",
|
||||||
"@types/hoist-non-react-statics": "3.3.1",
|
"@types/hoist-non-react-statics": "3.3.1",
|
||||||
@ -235,7 +234,6 @@
|
|||||||
"angular-bindonce": "0.3.1",
|
"angular-bindonce": "0.3.1",
|
||||||
"angular-route": "1.8.2",
|
"angular-route": "1.8.2",
|
||||||
"angular-sanitize": "1.8.2",
|
"angular-sanitize": "1.8.2",
|
||||||
"antlr4": "^4.8.0",
|
|
||||||
"baron": "3.0.3",
|
"baron": "3.0.3",
|
||||||
"brace": "0.11.1",
|
"brace": "0.11.1",
|
||||||
"calculate-size": "1.1.1",
|
"calculate-size": "1.1.1",
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,566 +0,0 @@
|
|||||||
// Generated from ScrollQLParser.g4 by ANTLR 4.8
|
|
||||||
// jshint ignore: start
|
|
||||||
var antlr4 = require('antlr4/index');
|
|
||||||
|
|
||||||
// This class defines a complete listener for a parse tree produced by ScrollQLParser.
|
|
||||||
function ScrollQLParserListener() {
|
|
||||||
antlr4.tree.ParseTreeListener.call(this);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ScrollQLParserListener.prototype = Object.create(antlr4.tree.ParseTreeListener.prototype);
|
|
||||||
ScrollQLParserListener.prototype.constructor = ScrollQLParserListener;
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#query.
|
|
||||||
ScrollQLParserListener.prototype.enterQuery = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#query.
|
|
||||||
ScrollQLParserListener.prototype.exitQuery = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#logQuery.
|
|
||||||
ScrollQLParserListener.prototype.enterLogQuery = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#logQuery.
|
|
||||||
ScrollQLParserListener.prototype.exitLogQuery = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#logAesthetic.
|
|
||||||
ScrollQLParserListener.prototype.enterLogAesthetic = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#logAesthetic.
|
|
||||||
ScrollQLParserListener.prototype.exitLogAesthetic = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#logSourceStage.
|
|
||||||
ScrollQLParserListener.prototype.enterLogSourceStage = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#logSourceStage.
|
|
||||||
ScrollQLParserListener.prototype.exitLogSourceStage = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#logStatsStage.
|
|
||||||
ScrollQLParserListener.prototype.enterLogStatsStage = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#logStatsStage.
|
|
||||||
ScrollQLParserListener.prototype.exitLogStatsStage = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#logOp.
|
|
||||||
ScrollQLParserListener.prototype.enterLogOp = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#logOp.
|
|
||||||
ScrollQLParserListener.prototype.exitLogOp = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#logAestheticOp.
|
|
||||||
ScrollQLParserListener.prototype.enterLogAestheticOp = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#logAestheticOp.
|
|
||||||
ScrollQLParserListener.prototype.exitLogAestheticOp = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#logSource.
|
|
||||||
ScrollQLParserListener.prototype.enterLogSource = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#logSource.
|
|
||||||
ScrollQLParserListener.prototype.exitLogSource = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#timeExpr.
|
|
||||||
ScrollQLParserListener.prototype.enterTimeExpr = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#timeExpr.
|
|
||||||
ScrollQLParserListener.prototype.exitTimeExpr = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#nowTimeExpr.
|
|
||||||
ScrollQLParserListener.prototype.enterNowTimeExpr = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#nowTimeExpr.
|
|
||||||
ScrollQLParserListener.prototype.exitNowTimeExpr = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#negRelativeTimeExpr.
|
|
||||||
ScrollQLParserListener.prototype.enterNegRelativeTimeExpr = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#negRelativeTimeExpr.
|
|
||||||
ScrollQLParserListener.prototype.exitNegRelativeTimeExpr = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#posRelativeTimeExpr.
|
|
||||||
ScrollQLParserListener.prototype.enterPosRelativeTimeExpr = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#posRelativeTimeExpr.
|
|
||||||
ScrollQLParserListener.prototype.exitPosRelativeTimeExpr = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#iso8601TimeExpr.
|
|
||||||
ScrollQLParserListener.prototype.enterIso8601TimeExpr = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#iso8601TimeExpr.
|
|
||||||
ScrollQLParserListener.prototype.exitIso8601TimeExpr = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#epochTimeExpr.
|
|
||||||
ScrollQLParserListener.prototype.enterEpochTimeExpr = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#epochTimeExpr.
|
|
||||||
ScrollQLParserListener.prototype.exitEpochTimeExpr = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#bareSpaceDelimited.
|
|
||||||
ScrollQLParserListener.prototype.enterBareSpaceDelimited = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#bareSpaceDelimited.
|
|
||||||
ScrollQLParserListener.prototype.exitBareSpaceDelimited = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#logStats.
|
|
||||||
ScrollQLParserListener.prototype.enterLogStats = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#logStats.
|
|
||||||
ScrollQLParserListener.prototype.exitLogStats = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#statsExpr.
|
|
||||||
ScrollQLParserListener.prototype.enterStatsExpr = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#statsExpr.
|
|
||||||
ScrollQLParserListener.prototype.exitStatsExpr = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#statsGroupFieldId.
|
|
||||||
ScrollQLParserListener.prototype.enterStatsGroupFieldId = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#statsGroupFieldId.
|
|
||||||
ScrollQLParserListener.prototype.exitStatsGroupFieldId = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#statsGroupFieldProjection.
|
|
||||||
ScrollQLParserListener.prototype.enterStatsGroupFieldProjection = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#statsGroupFieldProjection.
|
|
||||||
ScrollQLParserListener.prototype.exitStatsGroupFieldProjection = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#logOpFieldsFields.
|
|
||||||
ScrollQLParserListener.prototype.enterLogOpFieldsFields = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#logOpFieldsFields.
|
|
||||||
ScrollQLParserListener.prototype.exitLogOpFieldsFields = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#logOpFieldsDisplay.
|
|
||||||
ScrollQLParserListener.prototype.enterLogOpFieldsDisplay = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#logOpFieldsDisplay.
|
|
||||||
ScrollQLParserListener.prototype.exitLogOpFieldsDisplay = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#fieldSpec.
|
|
||||||
ScrollQLParserListener.prototype.enterFieldSpec = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#fieldSpec.
|
|
||||||
ScrollQLParserListener.prototype.exitFieldSpec = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#logOpParse.
|
|
||||||
ScrollQLParserListener.prototype.enterLogOpParse = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#logOpParse.
|
|
||||||
ScrollQLParserListener.prototype.exitLogOpParse = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#logOpSearch.
|
|
||||||
ScrollQLParserListener.prototype.enterLogOpSearch = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#logOpSearch.
|
|
||||||
ScrollQLParserListener.prototype.exitLogOpSearch = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#implicitLogOpSearch.
|
|
||||||
ScrollQLParserListener.prototype.enterImplicitLogOpSearch = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#implicitLogOpSearch.
|
|
||||||
ScrollQLParserListener.prototype.exitImplicitLogOpSearch = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#searchExprTerm.
|
|
||||||
ScrollQLParserListener.prototype.enterSearchExprTerm = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#searchExprTerm.
|
|
||||||
ScrollQLParserListener.prototype.exitSearchExprTerm = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#searchExprNot.
|
|
||||||
ScrollQLParserListener.prototype.enterSearchExprNot = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#searchExprNot.
|
|
||||||
ScrollQLParserListener.prototype.exitSearchExprNot = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#searchExprAnd.
|
|
||||||
ScrollQLParserListener.prototype.enterSearchExprAnd = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#searchExprAnd.
|
|
||||||
ScrollQLParserListener.prototype.exitSearchExprAnd = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#searchExprNested.
|
|
||||||
ScrollQLParserListener.prototype.enterSearchExprNested = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#searchExprNested.
|
|
||||||
ScrollQLParserListener.prototype.exitSearchExprNested = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#searchExprOr.
|
|
||||||
ScrollQLParserListener.prototype.enterSearchExprOr = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#searchExprOr.
|
|
||||||
ScrollQLParserListener.prototype.exitSearchExprOr = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#searchTerm.
|
|
||||||
ScrollQLParserListener.prototype.enterSearchTerm = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#searchTerm.
|
|
||||||
ScrollQLParserListener.prototype.exitSearchTerm = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#logOpFilter.
|
|
||||||
ScrollQLParserListener.prototype.enterLogOpFilter = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#logOpFilter.
|
|
||||||
ScrollQLParserListener.prototype.exitLogOpFilter = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#logOpSort.
|
|
||||||
ScrollQLParserListener.prototype.enterLogOpSort = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#logOpSort.
|
|
||||||
ScrollQLParserListener.prototype.exitLogOpSort = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#sortExprDesc.
|
|
||||||
ScrollQLParserListener.prototype.enterSortExprDesc = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#sortExprDesc.
|
|
||||||
ScrollQLParserListener.prototype.exitSortExprDesc = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#sortExprAsc.
|
|
||||||
ScrollQLParserListener.prototype.enterSortExprAsc = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#sortExprAsc.
|
|
||||||
ScrollQLParserListener.prototype.exitSortExprAsc = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#logOpLimitHead.
|
|
||||||
ScrollQLParserListener.prototype.enterLogOpLimitHead = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#logOpLimitHead.
|
|
||||||
ScrollQLParserListener.prototype.exitLogOpLimitHead = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#logOpLimitTail.
|
|
||||||
ScrollQLParserListener.prototype.enterLogOpLimitTail = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#logOpLimitTail.
|
|
||||||
ScrollQLParserListener.prototype.exitLogOpLimitTail = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#expressionRoot.
|
|
||||||
ScrollQLParserListener.prototype.enterExpressionRoot = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#expressionRoot.
|
|
||||||
ScrollQLParserListener.prototype.exitExpressionRoot = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#expressionAddSub.
|
|
||||||
ScrollQLParserListener.prototype.enterExpressionAddSub = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#expressionAddSub.
|
|
||||||
ScrollQLParserListener.prototype.exitExpressionAddSub = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#expressionEq.
|
|
||||||
ScrollQLParserListener.prototype.enterExpressionEq = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#expressionEq.
|
|
||||||
ScrollQLParserListener.prototype.exitExpressionEq = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#expressionComp.
|
|
||||||
ScrollQLParserListener.prototype.enterExpressionComp = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#expressionComp.
|
|
||||||
ScrollQLParserListener.prototype.exitExpressionComp = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#expressionExpo.
|
|
||||||
ScrollQLParserListener.prototype.enterExpressionExpo = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#expressionExpo.
|
|
||||||
ScrollQLParserListener.prototype.exitExpressionExpo = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#expressionLike.
|
|
||||||
ScrollQLParserListener.prototype.enterExpressionLike = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#expressionLike.
|
|
||||||
ScrollQLParserListener.prototype.exitExpressionLike = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#expressionTerm.
|
|
||||||
ScrollQLParserListener.prototype.enterExpressionTerm = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#expressionTerm.
|
|
||||||
ScrollQLParserListener.prototype.exitExpressionTerm = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#expressionNeg.
|
|
||||||
ScrollQLParserListener.prototype.enterExpressionNeg = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#expressionNeg.
|
|
||||||
ScrollQLParserListener.prototype.exitExpressionNeg = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#expressionNot.
|
|
||||||
ScrollQLParserListener.prototype.enterExpressionNot = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#expressionNot.
|
|
||||||
ScrollQLParserListener.prototype.exitExpressionNot = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#expressionPos.
|
|
||||||
ScrollQLParserListener.prototype.enterExpressionPos = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#expressionPos.
|
|
||||||
ScrollQLParserListener.prototype.exitExpressionPos = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#expressionMulDivMod.
|
|
||||||
ScrollQLParserListener.prototype.enterExpressionMulDivMod = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#expressionMulDivMod.
|
|
||||||
ScrollQLParserListener.prototype.exitExpressionMulDivMod = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#expressionAnd.
|
|
||||||
ScrollQLParserListener.prototype.enterExpressionAnd = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#expressionAnd.
|
|
||||||
ScrollQLParserListener.prototype.exitExpressionAnd = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#expressionNested.
|
|
||||||
ScrollQLParserListener.prototype.enterExpressionNested = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#expressionNested.
|
|
||||||
ScrollQLParserListener.prototype.exitExpressionNested = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#expressionOr.
|
|
||||||
ScrollQLParserListener.prototype.enterExpressionOr = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#expressionOr.
|
|
||||||
ScrollQLParserListener.prototype.exitExpressionOr = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#expressionIn.
|
|
||||||
ScrollQLParserListener.prototype.enterExpressionIn = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#expressionIn.
|
|
||||||
ScrollQLParserListener.prototype.exitExpressionIn = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#termId.
|
|
||||||
ScrollQLParserListener.prototype.enterTermId = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#termId.
|
|
||||||
ScrollQLParserListener.prototype.exitTermId = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#termNum.
|
|
||||||
ScrollQLParserListener.prototype.enterTermNum = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#termNum.
|
|
||||||
ScrollQLParserListener.prototype.exitTermNum = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#termStr.
|
|
||||||
ScrollQLParserListener.prototype.enterTermStr = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#termStr.
|
|
||||||
ScrollQLParserListener.prototype.exitTermStr = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#termFn.
|
|
||||||
ScrollQLParserListener.prototype.enterTermFn = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#termFn.
|
|
||||||
ScrollQLParserListener.prototype.exitTermFn = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#likeTerm.
|
|
||||||
ScrollQLParserListener.prototype.enterLikeTerm = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#likeTerm.
|
|
||||||
ScrollQLParserListener.prototype.exitLikeTerm = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#functionWithArgs.
|
|
||||||
ScrollQLParserListener.prototype.enterFunctionWithArgs = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#functionWithArgs.
|
|
||||||
ScrollQLParserListener.prototype.exitFunctionWithArgs = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#functionWithNoArgs.
|
|
||||||
ScrollQLParserListener.prototype.enterFunctionWithNoArgs = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#functionWithNoArgs.
|
|
||||||
ScrollQLParserListener.prototype.exitFunctionWithNoArgs = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#functionArgTimePeriod.
|
|
||||||
ScrollQLParserListener.prototype.enterFunctionArgTimePeriod = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#functionArgTimePeriod.
|
|
||||||
ScrollQLParserListener.prototype.exitFunctionArgTimePeriod = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#functionArgFieldClause.
|
|
||||||
ScrollQLParserListener.prototype.enterFunctionArgFieldClause = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#functionArgFieldClause.
|
|
||||||
ScrollQLParserListener.prototype.exitFunctionArgFieldClause = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#array.
|
|
||||||
ScrollQLParserListener.prototype.enterArray = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#array.
|
|
||||||
ScrollQLParserListener.prototype.exitArray = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#arrayElem.
|
|
||||||
ScrollQLParserListener.prototype.enterArrayElem = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#arrayElem.
|
|
||||||
ScrollQLParserListener.prototype.exitArrayElem = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#number.
|
|
||||||
ScrollQLParserListener.prototype.enterNumber = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#number.
|
|
||||||
ScrollQLParserListener.prototype.exitNumber = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#string.
|
|
||||||
ScrollQLParserListener.prototype.enterString = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#string.
|
|
||||||
ScrollQLParserListener.prototype.exitString = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#stringOrBareString.
|
|
||||||
ScrollQLParserListener.prototype.enterStringOrBareString = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#stringOrBareString.
|
|
||||||
ScrollQLParserListener.prototype.exitStringOrBareString = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#regex.
|
|
||||||
ScrollQLParserListener.prototype.enterRegex = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#regex.
|
|
||||||
ScrollQLParserListener.prototype.exitRegex = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#regexString.
|
|
||||||
ScrollQLParserListener.prototype.enterRegexString = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#regexString.
|
|
||||||
ScrollQLParserListener.prototype.exitRegexString = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#logId.
|
|
||||||
ScrollQLParserListener.prototype.enterLogId = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#logId.
|
|
||||||
ScrollQLParserListener.prototype.exitLogId = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#fieldId.
|
|
||||||
ScrollQLParserListener.prototype.enterFieldId = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#fieldId.
|
|
||||||
ScrollQLParserListener.prototype.exitFieldId = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#aliasId.
|
|
||||||
ScrollQLParserListener.prototype.enterAliasId = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#aliasId.
|
|
||||||
ScrollQLParserListener.prototype.exitAliasId = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#userId.
|
|
||||||
ScrollQLParserListener.prototype.enterUserId = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#userId.
|
|
||||||
ScrollQLParserListener.prototype.exitUserId = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#unquotedUserId.
|
|
||||||
ScrollQLParserListener.prototype.enterUnquotedUserId = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#unquotedUserId.
|
|
||||||
ScrollQLParserListener.prototype.exitUnquotedUserId = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#unquotedUserAtId.
|
|
||||||
ScrollQLParserListener.prototype.enterUnquotedUserAtId = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#unquotedUserAtId.
|
|
||||||
ScrollQLParserListener.prototype.exitUnquotedUserAtId = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#unquotedUserBareId.
|
|
||||||
ScrollQLParserListener.prototype.enterUnquotedUserBareId = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#unquotedUserBareId.
|
|
||||||
ScrollQLParserListener.prototype.exitUnquotedUserBareId = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#quotedUserId.
|
|
||||||
ScrollQLParserListener.prototype.enterQuotedUserId = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#quotedUserId.
|
|
||||||
ScrollQLParserListener.prototype.exitQuotedUserId = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#systemId.
|
|
||||||
ScrollQLParserListener.prototype.enterSystemId = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#systemId.
|
|
||||||
ScrollQLParserListener.prototype.exitSystemId = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#unquotedSystemId.
|
|
||||||
ScrollQLParserListener.prototype.enterUnquotedSystemId = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#unquotedSystemId.
|
|
||||||
ScrollQLParserListener.prototype.exitUnquotedSystemId = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#quotedSystemId.
|
|
||||||
ScrollQLParserListener.prototype.enterQuotedSystemId = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#quotedSystemId.
|
|
||||||
ScrollQLParserListener.prototype.exitQuotedSystemId = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#resultId.
|
|
||||||
ScrollQLParserListener.prototype.enterResultId = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#resultId.
|
|
||||||
ScrollQLParserListener.prototype.exitResultId = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#functionId.
|
|
||||||
ScrollQLParserListener.prototype.enterFunctionId = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#functionId.
|
|
||||||
ScrollQLParserListener.prototype.exitFunctionId = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#rawId.
|
|
||||||
ScrollQLParserListener.prototype.enterRawId = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#rawId.
|
|
||||||
ScrollQLParserListener.prototype.exitRawId = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#keywords.
|
|
||||||
ScrollQLParserListener.prototype.enterKeywords = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#keywords.
|
|
||||||
ScrollQLParserListener.prototype.exitKeywords = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#timeUnitMilliSeconds.
|
|
||||||
ScrollQLParserListener.prototype.enterTimeUnitMilliSeconds = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#timeUnitMilliSeconds.
|
|
||||||
ScrollQLParserListener.prototype.exitTimeUnitMilliSeconds = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#timeUnitSeconds.
|
|
||||||
ScrollQLParserListener.prototype.enterTimeUnitSeconds = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#timeUnitSeconds.
|
|
||||||
ScrollQLParserListener.prototype.exitTimeUnitSeconds = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#timeUnitMinutes.
|
|
||||||
ScrollQLParserListener.prototype.enterTimeUnitMinutes = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#timeUnitMinutes.
|
|
||||||
ScrollQLParserListener.prototype.exitTimeUnitMinutes = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#timeUnitHours.
|
|
||||||
ScrollQLParserListener.prototype.enterTimeUnitHours = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#timeUnitHours.
|
|
||||||
ScrollQLParserListener.prototype.exitTimeUnitHours = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#timeUnitDays.
|
|
||||||
ScrollQLParserListener.prototype.enterTimeUnitDays = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#timeUnitDays.
|
|
||||||
ScrollQLParserListener.prototype.exitTimeUnitDays = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#timeUnitWeeks.
|
|
||||||
ScrollQLParserListener.prototype.enterTimeUnitWeeks = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#timeUnitWeeks.
|
|
||||||
ScrollQLParserListener.prototype.exitTimeUnitWeeks = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#timeUnitMonths.
|
|
||||||
ScrollQLParserListener.prototype.enterTimeUnitMonths = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#timeUnitMonths.
|
|
||||||
ScrollQLParserListener.prototype.exitTimeUnitMonths = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#timeUnitQuarters.
|
|
||||||
ScrollQLParserListener.prototype.enterTimeUnitQuarters = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#timeUnitQuarters.
|
|
||||||
ScrollQLParserListener.prototype.exitTimeUnitQuarters = function (ctx) {};
|
|
||||||
|
|
||||||
// Enter a parse tree produced by ScrollQLParser#timeUnitYears.
|
|
||||||
ScrollQLParserListener.prototype.enterTimeUnitYears = function (ctx) {};
|
|
||||||
|
|
||||||
// Exit a parse tree produced by ScrollQLParser#timeUnitYears.
|
|
||||||
ScrollQLParserListener.prototype.exitTimeUnitYears = function (ctx) {};
|
|
||||||
|
|
||||||
exports.ScrollQLParserListener = ScrollQLParserListener;
|
|
@ -1,6 +1,8 @@
|
|||||||
import { getStatsGroups } from './getStatsGroups';
|
import { getStatsGroups } from './getStatsGroups';
|
||||||
|
|
||||||
describe('GroupListener', () => {
|
describe('GroupListener', () => {
|
||||||
|
// https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/CWL_QuerySyntax-examples.html
|
||||||
|
// https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Container-Insights-view-metrics.html
|
||||||
it('should correctly parse groups in stats query', () => {
|
it('should correctly parse groups in stats query', () => {
|
||||||
const testQueries = [
|
const testQueries = [
|
||||||
{
|
{
|
||||||
@ -60,6 +62,17 @@ describe('GroupListener', () => {
|
|||||||
query: `stats count(*)`,
|
query: `stats count(*)`,
|
||||||
expected: [],
|
expected: [],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
query: `filter responseCode="SERVFAIL" | stats count(*) by queryName.0.1 as f0, bin(5m)`,
|
||||||
|
expected: ['f0', 'bin(5m)'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
query: `fields @timestamp, @message
|
||||||
|
| filter @message like /dial tcp /
|
||||||
|
| parse log /dial tcp (?<ip>[\d\.]+)\:(?<port>\d+)\: (?<reason>[^\\\"]+)/
|
||||||
|
| stats count() by bin($__interval), reason`,
|
||||||
|
expected: ['bin($__interval)', 'reason'],
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
for (const { query, expected } of testQueries) {
|
for (const { query, expected } of testQueries) {
|
||||||
|
@ -1,41 +1,27 @@
|
|||||||
const antlr4 = require('antlr4');
|
const byRE = /\s+by\s+/im;
|
||||||
const ScrollQLLexer = require('./ScrollQLLexer').ScrollQLLexer;
|
|
||||||
const ScrollQLParser = require('./ScrollQLParser').ScrollQLParser;
|
|
||||||
const ScrollQLParserListener = require('./ScrollQLParserListener').ScrollQLParserListener;
|
|
||||||
|
|
||||||
class GroupListener extends ScrollQLParserListener {
|
/**
|
||||||
groupNames: string[] = [];
|
* groups look like this: (@a.foo)( as )(bar),
|
||||||
|
* group 1 is the field, group 2 is " as " and group 3 is the alias
|
||||||
|
* this regex will not advance past any non-identifier or whitespace characters, e.g. |
|
||||||
|
*/
|
||||||
|
const groupsRE = /([\w$@().]+)(?:(\s+as\s+)([\w$]+))?\s*,?\s*/iy;
|
||||||
|
|
||||||
enterLogStats(ctx: any) {
|
export function getStatsGroups(query: string): string[] {
|
||||||
this.groupNames = [];
|
let groups = [];
|
||||||
if (ctx.groups && ctx.groups.length > 0) {
|
|
||||||
const groups = ctx.groups;
|
|
||||||
|
|
||||||
groups.forEach((group: any) => {
|
// find " by "
|
||||||
// This code is for handling the case where a field specifier is aliased, with the alias available via
|
let b;
|
||||||
// the proj property. Otherwise we can just take the group text as it is.
|
if ((b = query.match(byRE))) {
|
||||||
const proj = group.fieldSpec?.().proj;
|
// continue incremental scanning from there for groups & aliases
|
||||||
if (proj) {
|
groupsRE.lastIndex = b.index! + b[0].length;
|
||||||
this.groupNames.push(proj.getText());
|
|
||||||
} else {
|
let g;
|
||||||
this.groupNames.push(group.getText());
|
while ((g = groupsRE.exec(query))) {
|
||||||
}
|
groups.push(g[2] ? g[3] : g[1]);
|
||||||
});
|
groupsRE.lastIndex = g.index + g[0].length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
export function getStatsGroups(text: string): string[] {
|
return groups;
|
||||||
// Dummy prefix needed here for parser to function correctly
|
|
||||||
const dummyPrefix = 'source test start=0 end=1|';
|
|
||||||
const queryText = dummyPrefix + text;
|
|
||||||
const chars = new antlr4.InputStream(queryText);
|
|
||||||
const lexer = new ScrollQLLexer(chars);
|
|
||||||
const tokens = new antlr4.CommonTokenStream(lexer);
|
|
||||||
const parser = new ScrollQLParser(tokens);
|
|
||||||
parser.buildParseTrees = true;
|
|
||||||
const tree = parser.query();
|
|
||||||
const groupListener = new GroupListener();
|
|
||||||
antlr4.tree.ParseTreeWalker.DEFAULT.walk(groupListener, tree);
|
|
||||||
return groupListener.groupNames;
|
|
||||||
}
|
}
|
||||||
|
10
yarn.lock
10
yarn.lock
@ -4957,11 +4957,6 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/angular/-/angular-1.6.56.tgz#20124077bd44061e018c7283c0bb83f4b00322dd"
|
resolved "https://registry.yarnpkg.com/@types/angular/-/angular-1.6.56.tgz#20124077bd44061e018c7283c0bb83f4b00322dd"
|
||||||
integrity sha512-HxtqilvklZ7i6XOaiP7uIJIrFXEVEhfbSY45nfv2DeBRngncI58Y4ZOUMiUkcT8sqgLL1ablmbfylChUg7A3GA==
|
integrity sha512-HxtqilvklZ7i6XOaiP7uIJIrFXEVEhfbSY45nfv2DeBRngncI58Y4ZOUMiUkcT8sqgLL1ablmbfylChUg7A3GA==
|
||||||
|
|
||||||
"@types/antlr4@^4.7.1":
|
|
||||||
version "4.7.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/antlr4/-/antlr4-4.7.1.tgz#09a8f985e29149c73e92b161d08691a1fd8425ef"
|
|
||||||
integrity sha512-mjQv+WtdJnwI5qhNh5yJkZ9rVFdRClUyaO5KebaLSJFHT6uSyDLAK9jUke4zLKZXk6vQQ/QJN2j7QV2q7l5Slw==
|
|
||||||
|
|
||||||
"@types/anymatch@*":
|
"@types/anymatch@*":
|
||||||
version "1.3.1"
|
version "1.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/@types/anymatch/-/anymatch-1.3.1.tgz#336badc1beecb9dacc38bea2cf32adf627a8421a"
|
resolved "https://registry.yarnpkg.com/@types/anymatch/-/anymatch-1.3.1.tgz#336badc1beecb9dacc38bea2cf32adf627a8421a"
|
||||||
@ -7320,11 +7315,6 @@ ansi-to-html@^0.6.11:
|
|||||||
dependencies:
|
dependencies:
|
||||||
entities "^1.1.2"
|
entities "^1.1.2"
|
||||||
|
|
||||||
antlr4@^4.8.0:
|
|
||||||
version "4.8.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/antlr4/-/antlr4-4.8.0.tgz#f938ec171be7fc2855cd3a533e87647185b32b6a"
|
|
||||||
integrity sha512-en/MxQ4OkPgGJQ3wD/muzj1uDnFSzdFIhc2+c6bHZokWkuBb6RRvFjpWhPxWLbgQvaEzldJZ0GSQpfSAaE3hqg==
|
|
||||||
|
|
||||||
any-observable@^0.3.0:
|
any-observable@^0.3.0:
|
||||||
version "0.3.0"
|
version "0.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/any-observable/-/any-observable-0.3.0.tgz#af933475e5806a67d0d7df090dd5e8bef65d119b"
|
resolved "https://registry.yarnpkg.com/any-observable/-/any-observable-0.3.0.tgz#af933475e5806a67d0d7df090dd5e8bef65d119b"
|
||||||
|
Loading…
Reference in New Issue
Block a user