fix:explore logql 支持语法高亮 以及适配换行输入

This commit is contained in:
zhangyu
2023-09-25 17:30:13 +08:00
parent b0a11fcd9b
commit d76d84c46d
12 changed files with 2826 additions and 81 deletions

View File

@@ -3127,7 +3127,7 @@
"babel-helper-builder-binary-assignment-operator-visitor": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz",
"integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=",
"integrity": "sha512-gCtfYORSG1fUMX4kKraymq607FWgMWg+j42IFPc18kFQEsmtaibP4UrqsXt8FlEJle25HUd4tsoDR7H2wDhe9Q==",
"dev": true,
"requires": {
"babel-helper-explode-assignable-expression": "^6.24.1",
@@ -3138,7 +3138,7 @@
"babel-helper-call-delegate": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz",
"integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=",
"integrity": "sha512-RL8n2NiEj+kKztlrVJM9JT1cXzzAdvWFh76xh/H1I4nKwunzE4INBXn8ieCZ+wh4zWszZk7NBS1s/8HR5jDkzQ==",
"dev": true,
"requires": {
"babel-helper-hoist-variables": "^6.24.1",
@@ -3150,7 +3150,7 @@
"babel-helper-define-map": {
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz",
"integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=",
"integrity": "sha512-bHkmjcC9lM1kmZcVpA5t2om2nzT/xiZpo6TJq7UlZ3wqKfzia4veeXbIhKvJXAMzhhEBd3cR1IElL5AenWEUpA==",
"dev": true,
"requires": {
"babel-helper-function-name": "^6.24.1",
@@ -3162,7 +3162,7 @@
"babel-helper-explode-assignable-expression": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz",
"integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=",
"integrity": "sha512-qe5csbhbvq6ccry9G7tkXbzNtcDiH4r51rrPUbwwoTzZ18AqxWYRZT6AOmxrpxKnQBW0pYlBI/8vh73Z//78nQ==",
"dev": true,
"requires": {
"babel-runtime": "^6.22.0",
@@ -3185,7 +3185,7 @@
"babel-helper-function-name": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz",
"integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=",
"integrity": "sha512-Oo6+e2iX+o9eVvJ9Y5eKL5iryeRdsIkwRYheCuhYdVHsdEQysbc2z2QkqCLIYnNxkT5Ss3ggrHdXiDI7Dhrn4Q==",
"dev": true,
"requires": {
"babel-helper-get-function-arity": "^6.24.1",
@@ -3198,7 +3198,7 @@
"babel-helper-get-function-arity": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz",
"integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=",
"integrity": "sha512-WfgKFX6swFB1jS2vo+DwivRN4NB8XUdM3ij0Y1gnC21y1tdBoe6xjVnd7NSI6alv+gZXCtJqvrTeMW3fR/c0ng==",
"dev": true,
"requires": {
"babel-runtime": "^6.22.0",
@@ -3208,7 +3208,7 @@
"babel-helper-hoist-variables": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz",
"integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=",
"integrity": "sha512-zAYl3tqerLItvG5cKYw7f1SpvIxS9zi7ohyGHaI9cgDUjAT6YcY9jIEH5CstetP5wHIVSceXwNS7Z5BpJg+rOw==",
"dev": true,
"requires": {
"babel-runtime": "^6.22.0",
@@ -3218,7 +3218,7 @@
"babel-helper-optimise-call-expression": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz",
"integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=",
"integrity": "sha512-Op9IhEaxhbRT8MDXx2iNuMgciu2V8lDvYCNQbDGjdBNCjaMvyLf4wl4A3b8IgndCyQF8TwfgsQ8T3VD8aX1/pA==",
"dev": true,
"requires": {
"babel-runtime": "^6.22.0",
@@ -3239,7 +3239,7 @@
"babel-helper-remap-async-to-generator": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz",
"integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=",
"integrity": "sha512-RYqaPD0mQyQIFRu7Ho5wE2yvA/5jxqCIj/Lv4BXNq23mHYu/vxikOy2JueLiBxQknwapwrJeNCesvY0ZcfnlHg==",
"dev": true,
"requires": {
"babel-helper-function-name": "^6.24.1",
@@ -3252,7 +3252,7 @@
"babel-helper-replace-supers": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz",
"integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=",
"integrity": "sha512-sLI+u7sXJh6+ToqDr57Bv973kCepItDhMou0xCP2YPVmR1jkHSCY+p1no8xErbV1Siz5QE8qKT1WIwybSWlqjw==",
"dev": true,
"requires": {
"babel-helper-optimise-call-expression": "^6.24.1",
@@ -3311,7 +3311,7 @@
"babel-plugin-check-es2015-constants": {
"version": "6.22.0",
"resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz",
"integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=",
"integrity": "sha512-B1M5KBP29248dViEo1owyY32lk1ZSH2DaNNrXLGt8lyjjHm7pBqAdQ7VKUPR6EEDO323+OvT3MQXbCin8ooWdA==",
"dev": true,
"requires": {
"babel-runtime": "^6.22.0"
@@ -3370,7 +3370,7 @@
"babel-plugin-syntax-async-functions": {
"version": "6.13.0",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz",
"integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=",
"integrity": "sha512-4Zp4unmHgw30A1eWI5EpACji2qMocisdXhAftfhXoSV9j0Tvj6nRFE3tOmRY912E0FMRm/L5xWE7MGVT2FoLnw==",
"dev": true
},
"babel-plugin-syntax-async-generators": {
@@ -3388,7 +3388,7 @@
"babel-plugin-syntax-decorators": {
"version": "6.13.0",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz",
"integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=",
"integrity": "sha512-AWj19x2aDm8qFQ5O2JcD6pwJDW1YdcnO+1b81t7gxrGjz5VHiUqeYWAR4h7zueWMalRelrQDXprv2FrY1dbpbw==",
"dev": true
},
"babel-plugin-syntax-dynamic-import": {
@@ -3400,13 +3400,13 @@
"babel-plugin-syntax-exponentiation-operator": {
"version": "6.13.0",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz",
"integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=",
"integrity": "sha512-Z/flU+T9ta0aIEKl1tGEmN/pZiI1uXmCiGFRegKacQfEJzp7iNsKloZmyJlQr+75FCJtiFfGIK03SiCvCt9cPQ==",
"dev": true
},
"babel-plugin-syntax-jsx": {
"version": "6.18.0",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz",
"integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=",
"integrity": "sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw==",
"dev": true
},
"babel-plugin-syntax-object-rest-spread": {
@@ -3418,7 +3418,7 @@
"babel-plugin-syntax-trailing-function-commas": {
"version": "6.22.0",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz",
"integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=",
"integrity": "sha512-Gx9CH3Q/3GKbhs07Bszw5fPTlU+ygrOGfAhEt7W2JICwufpC4SuO0mG0+4NykPBSYPMJhqvVlDBU17qB1D+hMQ==",
"dev": true
},
"babel-plugin-transform-async-generator-functions": {
@@ -3435,7 +3435,7 @@
"babel-plugin-transform-async-to-generator": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz",
"integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=",
"integrity": "sha512-7BgYJujNCg0Ti3x0c/DL3tStvnKS6ktIYOmo9wginv/dfZOrbSZ+qG4IRRHMBOzZ5Awb1skTiAsQXg/+IWkZYw==",
"dev": true,
"requires": {
"babel-helper-remap-async-to-generator": "^6.24.1",
@@ -3471,7 +3471,7 @@
"babel-plugin-transform-es2015-arrow-functions": {
"version": "6.22.0",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz",
"integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=",
"integrity": "sha512-PCqwwzODXW7JMrzu+yZIaYbPQSKjDTAsNNlK2l5Gg9g4rz2VzLnZsStvp/3c46GfXpwkyufb3NCyG9+50FF1Vg==",
"dev": true,
"requires": {
"babel-runtime": "^6.22.0"
@@ -3480,7 +3480,7 @@
"babel-plugin-transform-es2015-block-scoped-functions": {
"version": "6.22.0",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz",
"integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=",
"integrity": "sha512-2+ujAT2UMBzYFm7tidUsYh+ZoIutxJ3pN9IYrF1/H6dCKtECfhmB8UkHVpyxDwkj0CYbQG35ykoz925TUnBc3A==",
"dev": true,
"requires": {
"babel-runtime": "^6.22.0"
@@ -3489,7 +3489,7 @@
"babel-plugin-transform-es2015-block-scoping": {
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz",
"integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=",
"integrity": "sha512-YiN6sFAQ5lML8JjCmr7uerS5Yc/EMbgg9G8ZNmk2E3nYX4ckHR01wrkeeMijEf5WHNK5TW0Sl0Uu3pv3EdOJWw==",
"dev": true,
"requires": {
"babel-runtime": "^6.26.0",
@@ -3502,7 +3502,7 @@
"babel-plugin-transform-es2015-classes": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz",
"integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=",
"integrity": "sha512-5Dy7ZbRinGrNtmWpquZKZ3EGY8sDgIVB4CU8Om8q8tnMLrD/m94cKglVcHps0BCTdZ0TJeeAWOq2TK9MIY6cag==",
"dev": true,
"requires": {
"babel-helper-define-map": "^6.24.1",
@@ -3519,7 +3519,7 @@
"babel-plugin-transform-es2015-computed-properties": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz",
"integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=",
"integrity": "sha512-C/uAv4ktFP/Hmh01gMTvYvICrKze0XVX9f2PdIXuriCSvUmV9j+u+BB9f5fJK3+878yMK6dkdcq+Ymr9mrcLzw==",
"dev": true,
"requires": {
"babel-runtime": "^6.22.0",
@@ -3529,7 +3529,7 @@
"babel-plugin-transform-es2015-destructuring": {
"version": "6.23.0",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz",
"integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=",
"integrity": "sha512-aNv/GDAW0j/f4Uy1OEPZn1mqD+Nfy9viFGBfQ5bZyT35YqOiqx7/tXdyfZkJ1sC21NyEsBdfDY6PYmLHF4r5iA==",
"dev": true,
"requires": {
"babel-runtime": "^6.22.0"
@@ -3538,7 +3538,7 @@
"babel-plugin-transform-es2015-duplicate-keys": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz",
"integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=",
"integrity": "sha512-ossocTuPOssfxO2h+Z3/Ea1Vo1wWx31Uqy9vIiJusOP4TbF7tPs9U0sJ9pX9OJPf4lXRGj5+6Gkl/HHKiAP5ug==",
"dev": true,
"requires": {
"babel-runtime": "^6.22.0",
@@ -3548,7 +3548,7 @@
"babel-plugin-transform-es2015-for-of": {
"version": "6.23.0",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz",
"integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=",
"integrity": "sha512-DLuRwoygCoXx+YfxHLkVx5/NpeSbVwfoTeBykpJK7JhYWlL/O8hgAK/reforUnZDlxasOrVPPJVI/guE3dCwkw==",
"dev": true,
"requires": {
"babel-runtime": "^6.22.0"
@@ -3557,7 +3557,7 @@
"babel-plugin-transform-es2015-function-name": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz",
"integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=",
"integrity": "sha512-iFp5KIcorf11iBqu/y/a7DK3MN5di3pNCzto61FqCNnUX4qeBwcV1SLqe10oXNnCaxBUImX3SckX2/o1nsrTcg==",
"dev": true,
"requires": {
"babel-helper-function-name": "^6.24.1",
@@ -3568,7 +3568,7 @@
"babel-plugin-transform-es2015-literals": {
"version": "6.22.0",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz",
"integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=",
"integrity": "sha512-tjFl0cwMPpDYyoqYA9li1/7mGFit39XiNX5DKC/uCNjBctMxyL1/PT/l4rSlbvBG1pOKI88STRdUsWXB3/Q9hQ==",
"dev": true,
"requires": {
"babel-runtime": "^6.22.0"
@@ -3577,7 +3577,7 @@
"babel-plugin-transform-es2015-modules-amd": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz",
"integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=",
"integrity": "sha512-LnIIdGWIKdw7zwckqx+eGjcS8/cl8D74A3BpJbGjKTFFNJSMrjN4bIh22HY1AlkUbeLG6X6OZj56BDvWD+OeFA==",
"dev": true,
"requires": {
"babel-plugin-transform-es2015-modules-commonjs": "^6.24.1",
@@ -3600,7 +3600,7 @@
"babel-plugin-transform-es2015-modules-systemjs": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz",
"integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=",
"integrity": "sha512-ONFIPsq8y4bls5PPsAWYXH/21Hqv64TBxdje0FvU3MhIV6QM2j5YS7KvAzg/nTIVLot2D2fmFQrFWCbgHlFEjg==",
"dev": true,
"requires": {
"babel-helper-hoist-variables": "^6.24.1",
@@ -3611,7 +3611,7 @@
"babel-plugin-transform-es2015-modules-umd": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz",
"integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=",
"integrity": "sha512-LpVbiT9CLsuAIp3IG0tfbVo81QIhn6pE8xBJ7XSeCtFlMltuar5VuBV6y6Q45tpui9QWcy5i0vLQfCfrnF7Kiw==",
"dev": true,
"requires": {
"babel-plugin-transform-es2015-modules-amd": "^6.24.1",
@@ -3622,7 +3622,7 @@
"babel-plugin-transform-es2015-object-super": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz",
"integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=",
"integrity": "sha512-8G5hpZMecb53vpD3mjs64NhI1au24TAmokQ4B+TBFBjN9cVoGoOvotdrMMRmHvVZUEvqGUPWL514woru1ChZMA==",
"dev": true,
"requires": {
"babel-helper-replace-supers": "^6.24.1",
@@ -3632,7 +3632,7 @@
"babel-plugin-transform-es2015-parameters": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz",
"integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=",
"integrity": "sha512-8HxlW+BB5HqniD+nLkQ4xSAVq3bR/pcYW9IigY+2y0dI+Y7INFeTbfAQr+63T3E4UDsZGjyb+l9txUnABWxlOQ==",
"dev": true,
"requires": {
"babel-helper-call-delegate": "^6.24.1",
@@ -3646,7 +3646,7 @@
"babel-plugin-transform-es2015-shorthand-properties": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz",
"integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=",
"integrity": "sha512-mDdocSfUVm1/7Jw/FIRNw9vPrBQNePy6wZJlR8HAUBLybNp1w/6lr6zZ2pjMShee65t/ybR5pT8ulkLzD1xwiw==",
"dev": true,
"requires": {
"babel-runtime": "^6.22.0",
@@ -3656,7 +3656,7 @@
"babel-plugin-transform-es2015-spread": {
"version": "6.22.0",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz",
"integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=",
"integrity": "sha512-3Ghhi26r4l3d0Js933E5+IhHwk0A1yiutj9gwvzmFbVV0sPMYk2lekhOufHBswX7NCoSeF4Xrl3sCIuSIa+zOg==",
"dev": true,
"requires": {
"babel-runtime": "^6.22.0"
@@ -3665,7 +3665,7 @@
"babel-plugin-transform-es2015-sticky-regex": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz",
"integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=",
"integrity": "sha512-CYP359ADryTo3pCsH0oxRo/0yn6UsEZLqYohHmvLQdfS9xkf+MbCzE3/Kolw9OYIY4ZMilH25z/5CbQbwDD+lQ==",
"dev": true,
"requires": {
"babel-helper-regex": "^6.24.1",
@@ -3676,7 +3676,7 @@
"babel-plugin-transform-es2015-template-literals": {
"version": "6.22.0",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz",
"integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=",
"integrity": "sha512-x8b9W0ngnKzDMHimVtTfn5ryimars1ByTqsfBDwAqLibmuuQY6pgBQi5z1ErIsUOWBdw1bW9FSz5RZUojM4apg==",
"dev": true,
"requires": {
"babel-runtime": "^6.22.0"
@@ -3685,7 +3685,7 @@
"babel-plugin-transform-es2015-typeof-symbol": {
"version": "6.23.0",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz",
"integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=",
"integrity": "sha512-fz6J2Sf4gYN6gWgRZaoFXmq93X+Li/8vf+fb0sGDVtdeWvxC9y5/bTD7bvfWMEq6zetGEHpWjtzRGSugt5kNqw==",
"dev": true,
"requires": {
"babel-runtime": "^6.22.0"
@@ -3694,7 +3694,7 @@
"babel-plugin-transform-es2015-unicode-regex": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz",
"integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=",
"integrity": "sha512-v61Dbbihf5XxnYjtBN04B/JBvsScY37R1cZT5r9permN1cp+b70DY3Ib3fIkgn1DI9U3tGgBJZVD8p/mE/4JbQ==",
"dev": true,
"requires": {
"babel-helper-regex": "^6.24.1",
@@ -3705,7 +3705,7 @@
"babel-plugin-transform-exponentiation-operator": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz",
"integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=",
"integrity": "sha512-LzXDmbMkklvNhprr20//RStKVcT8Cu+SQtX18eMHLhjHf2yFzwtQ0S2f0jQ+89rokoNdmwoSqYzAhq86FxlLSQ==",
"dev": true,
"requires": {
"babel-helper-builder-binary-assignment-operator-visitor": "^6.24.1",
@@ -3726,7 +3726,7 @@
"babel-plugin-transform-regenerator": {
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz",
"integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=",
"integrity": "sha512-LS+dBkUGlNR15/5WHKe/8Neawx663qttS6AGqoOUhICc9d1KciBvtrQSuc0PI+CxQ2Q/S1aKuJ+u64GtLdcEZg==",
"dev": true,
"requires": {
"regenerator-transform": "^0.10.0"
@@ -3735,7 +3735,7 @@
"babel-plugin-transform-runtime": {
"version": "6.23.0",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-runtime/-/babel-plugin-transform-runtime-6.23.0.tgz",
"integrity": "sha1-iEkNRGUC6puOfvsP4J7E2ZR5se4=",
"integrity": "sha512-cpGMVC1vt/772y3jx1gwSaTitQVZuFDlllgreMsZ+rTYC6jlYXRyf5FQOgSnckOiA5QmzbXTyBY2A5AmZXF1fA==",
"dev": true,
"requires": {
"babel-runtime": "^6.22.0"
@@ -3744,7 +3744,7 @@
"babel-plugin-transform-strict-mode": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz",
"integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=",
"integrity": "sha512-j3KtSpjyLSJxNoCDrhwiJad8kw0gJ9REGj8/CqL0HeRyLnvUNYV9zcqluL6QJSXh3nfsLEmSLvwRfGzrgR96Pw==",
"dev": true,
"requires": {
"babel-runtime": "^6.22.0",
@@ -4197,7 +4197,7 @@
"boolbase": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
"integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="
},
"brace-expansion": {
"version": "1.1.11",
@@ -5182,7 +5182,7 @@
"color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
},
"color-string": {
"version": "1.9.1",
@@ -5293,7 +5293,7 @@
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
},
"concat-stream": {
"version": "1.6.2",
@@ -8139,7 +8139,7 @@
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="
},
"escodegen": {
"version": "1.14.3",
@@ -9199,7 +9199,7 @@
"fast-levenshtein": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
"dev": true
},
"faye-websocket": {
@@ -9617,7 +9617,7 @@
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
},
"fsevents": {
"version": "1.2.13",
@@ -10148,7 +10148,7 @@
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="
},
"has-symbol-support-x": {
"version": "1.4.2",
@@ -10704,7 +10704,7 @@
"imurmurhash": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
"integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o="
"integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="
},
"in-publish": {
"version": "2.0.1",
@@ -10730,7 +10730,7 @@
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
"requires": {
"once": "^1.3.0",
"wrappy": "1"
@@ -10974,7 +10974,7 @@
"is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="
},
"is-finite": {
"version": "1.0.2",
@@ -11189,7 +11189,7 @@
"isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
"dev": true
},
"isobject": {
@@ -12492,7 +12492,7 @@
"json-stable-stringify-without-jsonify": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
"integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE="
"integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="
},
"json-stringify-safe": {
"version": "5.0.1",
@@ -13806,6 +13806,11 @@
"moment": ">= 2.9.0"
}
},
"monaco-editor": {
"version": "0.20.0",
"resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.20.0.tgz",
"integrity": "sha512-hkvf4EtPJRMQlPC3UbMoRs0vTAFAYdzFQ+gpMb8A+9znae1c43q8Mab9iVsgTcg/4PNiLGGn3SlDIa8uvK1FIQ=="
},
"move-concurrently": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
@@ -13987,6 +13992,11 @@
"integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==",
"dev": true
},
"nano-assign": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/nano-assign/-/nano-assign-1.0.1.tgz",
"integrity": "sha512-1K8ncUoAYFPYcCZqrB+K2XQaFCmA35rryJCtPkGrG3zYkwm+iIUZRIHyaAfuy6zxaK9siPdjeJq7+Inijm6xhw=="
},
"nanoid": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
@@ -14020,7 +14030,7 @@
"natural-compare": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
"integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
"dev": true
},
"ncp": {
@@ -14510,7 +14520,7 @@
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"requires": {
"wrappy": "1"
}
@@ -14887,7 +14897,7 @@
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="
},
"path-is-inside": {
"version": "1.0.2",
@@ -16633,7 +16643,7 @@
"rechoir": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
"integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=",
"integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==",
"dev": true,
"requires": {
"resolve": "^1.1.6"
@@ -16717,7 +16727,7 @@
"regexpu-core": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz",
"integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=",
"integrity": "sha512-tJ9+S4oKjxY8IZ9jmjnp/mtytu1u3iyIQAfmI51IKWH6bFf7XR1ybtaO6j7INhZKXOTYADk7V5qxaqLkmNxiZQ==",
"dev": true,
"requires": {
"regenerate": "^1.2.1",
@@ -16728,13 +16738,13 @@
"regjsgen": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz",
"integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=",
"integrity": "sha512-x+Y3yA24uF68m5GA+tBjbGYo64xXVJpbToBaWCoSNSc1hdk6dfctaRWrNFTVJZIIhL5GxW8zwjoixbnifnK59g==",
"dev": true
},
"regjsparser": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz",
"integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=",
"integrity": "sha512-jlQ9gYLfk2p3V5Ag5fYhA7fv7OHzd1KUH0PRP46xc3TgwjwgROIW572AfYg/X9kaNq/LJnu6oJcFRXlIrGoTRw==",
"dev": true,
"requires": {
"jsesc": "~0.5.0"
@@ -16743,7 +16753,7 @@
"jsesc": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
"integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=",
"integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==",
"dev": true
}
}
@@ -18465,7 +18475,7 @@
"svg-tags": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz",
"integrity": "sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=",
"integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==",
"dev": true
},
"svgo": {
@@ -19180,7 +19190,7 @@
"text-table": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
"integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
"integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
"dev": true
},
"throat": {
@@ -19820,7 +19830,7 @@
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
},
"util.promisify": {
"version": "1.0.0",
@@ -20153,6 +20163,15 @@
}
}
},
"vue-monaco": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/vue-monaco/-/vue-monaco-1.2.2.tgz",
"integrity": "sha512-+BhCHeAuDmjtCUP9MUxan6OjGgOqDR7xHlNScZ8Cfq32iac76Fv7z6RfC+lSrp0YpCjEPl6bvpY21N11UBRmMg==",
"requires": {
"monaco-editor": "^0.20.0",
"nano-assign": "^1.0.0"
}
},
"vue-quill-editor": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/vue-quill-editor/-/vue-quill-editor-3.0.6.tgz",
@@ -21146,7 +21165,7 @@
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
},
"write-file-atomic": {
"version": "2.4.1",

View File

@@ -90,6 +90,7 @@
"vue-grid-layout": "^2.3.12",
"vue-i18n": "^8.15.1",
"vue-introjs": "^1.3.2",
"vue-monaco": "^1.2.2",
"vue-quill-editor": "^3.0.6",
"vue-resource": "^1.5.1",
"vue-router": "^3.0.1",

View File

@@ -177,6 +177,12 @@
.el-col .el-col-24 .metric-selector-input-box{
}
.lines-content {
//height: auto !important;
//width: 100% !important;
//position: unset !important;
top: 5px !important;
}
}
.topo-page {
.promqlInput {

View File

@@ -0,0 +1,9 @@
import { DefaultTimeRange } from '../../variables/interpolation/defaults.js'
import { getClosest } from './utils.js'
function getTimeRange (sceneObject) {
let _a
return (_a = getClosest(sceneObject, (s) => s.state.$timeRange)) != null ? _a : DefaultTimeRange
}
export { getTimeRange }

View File

@@ -0,0 +1,908 @@
const lr = require('@lezer/lr')
const lodash = require('lodash')
// This file was generated by lezer-generator. You probably shouldn't edit it.
const Json$1 = 1
const Logfmt$1 = 2
const Unpack$1 = 3
const Pattern$1 = 4
const Regexp$1 = 5
const Unwrap$1 = 6
const Ip$1 = 7
const LabelFormat$1 = 8
const LineFormat$1 = 9
const LabelReplace$1 = 10
const Vector$1 = 11
const Offset$1 = 12
const Bool$1 = 13
const On$1 = 14
const Ignoring$1 = 15
const GroupLeft$1 = 16
const GroupRight$1 = 17
const Decolorize$1 = 18
const Drop$1 = 19
const Keep$1 = 20
const By$1 = 21
const Without$1 = 22
const And$1 = 23
const Or$1 = 24
const Unless$1 = 25
const Sum$1 = 26
const Avg$1 = 27
const Count$1 = 28
const Max$1 = 29
const Min$1 = 30
const Stddev$1 = 31
const Stdvar$1 = 32
const Bottomk$1 = 33
const Topk$1 = 34
const LogExpr$1 = 38
const MetricExpr$1 = 86
const keywordTokens = {
json: Json$1,
logfmt: Logfmt$1,
unpack: Unpack$1,
pattern: Pattern$1,
regexp: Regexp$1,
ip: Ip$1,
label_format: LabelFormat$1,
line_format: LineFormat$1,
label_replace: LabelReplace$1,
vector: Vector$1,
offset: Offset$1,
bool: Bool$1,
on: On$1,
ignoring: Ignoring$1,
group_left: GroupLeft$1,
group_right: GroupRight$1,
unwrap: Unwrap$1,
decolorize: Decolorize$1,
drop: Drop$1,
keep: Keep$1
}
const specializeIdentifier = (value) => {
return keywordTokens[value.toLowerCase()] || -1
}
const contextualKeywordTokens = {
by: By$1,
without: Without$1,
and: And$1,
or: Or$1,
unless: Unless$1,
sum: Sum$1,
avg: Avg$1,
count: Count$1,
max: Max$1,
min: Min$1,
stddev: Stddev$1,
stdvar: Stdvar$1,
bottomk: Bottomk$1,
topk: Topk$1
}
const extendIdentifier = (value) => {
return contextualKeywordTokens[value.toLowerCase()] || -1
}
// This file was generated by lezer-generator. You probably shouldn't edit it.
// eslint-disable-next-line camelcase
const spec_Identifier = { __proto__: null, count_over_time: 281, rate: 283, rate_counter: 285, bytes_over_time: 287, bytes_rate: 289, avg_over_time: 291, sum_over_time: 293, min_over_time: 295, max_over_time: 297, stddev_over_time: 299, stdvar_over_time: 301, quantile_over_time: 303, first_over_time: 305, last_over_time: 307, absent_over_time: 309, bytes: 315, duration: 317, duration_seconds: 319 }
const parser = lr.LRParser.deserialize({
version: 14,
states: "CdOYQPOOO#]QPO'#DTO$lQPO'#DSOYQPO'#DSOOQO'#EW'#EWO$yQPO'#EVOOQO'#Es'#EsO%OQPO'#ErQ%ZQPOOOOQO'#FR'#FRO&[QPO'#FRO&aQPO'#FSO&fQPO'#FTOOQO'#EU'#EUOOQO'#DR'#DROOQO'#EX'#EXOOQO'#EY'#EYOOQO'#EZ'#EZOOQO'#E['#E[OOQO'#E]'#E]OOQO'#E^'#E^OOQO'#E_'#E_OOQO'#E`'#E`OOQO'#Ea'#EaOOQO'#Eb'#EbOOQO'#Ec'#EcOOQO'#Ed'#EdOOQO'#Ee'#EeOOQO'#Ef'#EfOOQO'#Eg'#EgO&kQPO'#DVOOQO'#DU'#DUO&yQPO,59oOOQO'#Db'#DbO'RQPO'#DaOOQO'#D`'#D`O'ZQPO'#D_O(tQPO'#D_OOQO'#D^'#D^O*vQPO,59nO,UQPO,59nO,]QPO,5:pO,dQPO,5:qO,oQPO'#EpO.tQPO,5;^O.{QPO,5;^O/QQPO,5;`O/QQPO,5;`O/QQPO,5;`O/QQPO,5;`O/QQPO,5;`O/QQPO,5;`OOQO,5;m,5;mOYQPO,5;nO1^QPO,5;oO1cQPO,59qO#]QPO,59pOOQO1G/Z1G/ZOOQO'#De'#DeOOQO,59{,59{O1hQPO,59{OOQO,59z,59zO1mQPO'#DVO2[QPO'#DgOOQO'#Dg'#DgO3xQPO'#DgOOQO'#Dm'#DmOOQO'#Dk'#DkO)dQPO'#DkO3}QPO,59yO5hQPO'#DyO5mQPO'#DzOOQO'#D}'#D}O5rQPO'#EOO5wQPO'#EROOQO,59y,59yOOQO,59x,59xOOQO1G/Y1G/YOOQO1G0[1G0[O5|QPO'#EhO,gQPO'#EhO6bQPO1G0]O6gQPO1G0]O6lQPO,5;[O6tQPO1G0xO8PQPO1G0xO8WQPO1G0xO8_QPO'#EvO:gQPO'#EuO:qQPO'#EuOYQPO1G0zOYQPO1G0zOYQPO1G0zOYQPO1G0zOYQPO1G0zOYQPO1G0zO:{QPO1G1YO;SQPO1G1ZOOQO1G/]1G/]OOQO1G/[1G/[O;XQPO1G/gO;^QPO,59qO;dQPO,5:YO;oQPO'#DjOOQO'#Di'#DiO;tQPO,5:SOOQO,5:R,5:RO=_QPO,5:VO)dQPO,5:VO)dQPO,5:VOOQO,5:e,5:eO=mQPO'#D|OOQO'#D{'#D{O=rQPO,5:fO?]QPO'#EQOOQO'#EQ'#EQOOQO'#EP'#EPO@|QPO,5:jOBgQPO'#ETOOQO'#ET'#ETOOQO'#ES'#ESODWQPO,5:mOEqQPO'#D_O5|QPO,5;SOExQPO'#EiOE}QPO,5;SOFhQPO,5;SOFrQPO,5;SOFyQPO,5;SOGOQPO7+%wO,gQPO7+%wOOQO'#Eq'#EqOH`QPO1G0vOOQO1G0v1G0vOHhQPO7+&dOYQPO7+&dOIxQPO7+&dOJPQPO7+&dOJWQQO'#EwOOQO,5;b,5;bOL`QPO,5;aOLgQPO,5;aOMxQPO7+&fONPQPO7+&fOOQO7+&f7+&fON^QPO7+&fONeQPO7+&fO! jQPO7+&fO! zQPO7+&tOOQO7+&u7+&uO!!PQPO7+%RO!!UQPO1G/rOOQO1G/t1G/tOOQO1G/{1G/{OOQO1G/}1G/}O!!ZQPO,5:UO!!`QPO,5:TOOQO1G/q1G/qO!!eQPO1G/qO!$OQPO,5:hO5mQPO,5:gO5rQPO,5:kO5wQPO,5:nO!$WQPO,5;VOE}QPO1G0nO!$fQPO1G0nO!$nQPO,5;TO)dQPO,5;VO!$sQPO1G0nO!$zQPO'#EjO!%PQPO1G0nO!$sQPO1G0nO!%XQPO1G0nO!%`QPO1G0nO6]QPO1G0nOOQO1G0n1G0nOOQO<<Ic<<IcO!%kQPO<<IcO!%pQPO,5;]OOQO7+&b7+&bOOQO<<JO<<JOO!%uQPO<<JOOYQPO<<JOOOQO'#Ey'#EyO!%|QPO,5;cOOQO'#Ex'#ExOOQO,5;c,5;cOOQO1G0{1G0{O!&UQPO1G0{O!(XQPO<<J`OOQO<<Hm<<HmO!(^QPO7+%^OOQO1G/p1G/pOOQO1G/o1G/oOOQO1G0S1G0SOOQO1G0R1G0ROOQO1G0V1G0VOOQO1G0Y1G0YOOQO'#El'#ElOOQO1G0q1G0qO!(cQPO1G0qOOQO'#Em'#EmOOQO'#En'#EnOOQO'#Eo'#EoOOQO7+&Y7+&YOOQO1G0o1G0oO!(hQPO1G0qO!(|QPO7+&YOOQO,5;U,5;UO!)UQPO7+&YO6]QPO7+&YO!)]QPO7+&YO!)hQPOAN>}OOQO1G0w1G0wO!*xQPOAN?jO!,YQPOAN?jO!,aQQO1G0}OOQO1G0}1G0}OOQO7+&g7+&gO!,iQPOAN?zO!,nQPO<<HxO!,sQPO7+&]O!,xQPO<<ItO!-QQPO<<ItO!-YQPO'#EkO!-_QPO<<ItOOQOG24iG24iOOQOG25UG25UOOQO1G1O1G1OOOQO7+&i7+&iO!-gQPOG25fOOQOAN>dAN>dO!-lQPO<<IwOOQOAN?`AN?`O!-qQPOAN?`O!-yQPOLD+QOOQOAN?cAN?cOOQO,5:f,5:fO!.OQPO!$'NlO!.TQPO!)9DWO!.YQPO!.K9rOOQO!4//^!4//^O5mQPO'#DzO!._QPO'#D_O!/VQPO,59nO!/aQPO'#DSOYQPO1G0zOYQPO1G0zOYQPO1G0zOYQPO1G0zOYQPO1G0zOYQPO1G0zO/QQPO,5;`O/QQPO,5;`O/QQPO,5;`O/QQPO,5;`O/QQPO,5;`O/QQPO,5;`O!0lQPO7+&fO!0sQPO7+&fO!1QQPO7+&fO!2YQPO7+&fO!2aQPO7+&fO!1XQPO'#Et",
stateData: '!2n~O#zOSsOS~OYZOZ[OjUOkUOlUOmUOnUOoUOpUOqUOrUO!lXO#oYO#pYO#{PO$ORO$Q_O$R`O$SaO$TbO$UcO$VdO$WeO$XfO$YgO$ZhO$[iO$]jO$^kO$_lO$`mO~OznO~O}qO!PqO!VqO!WqOgvXhvXivX!cvX!evX!fvX!gvX!hvX#ovX#pvX#qvX#rvX#svX#tvX~O!YuO#xvX$PvX~P#bO$OzO~Oe{Of{O$O|O~Og!POh!OOi!PO}!TO!c!TO!e!TO!f!TO!g!TO!h!TO#o!QO#p!QO#q!RO#r!RO#s!RO#t!SO~O!l!UO~O$O!VO~O$O!WO~O{!XO}!XO!O!XO!P!XO~O#|!YO#}!ZO~OV![O|!]O~O}qO!PqO!VqO!WqOg!RXh!RXi!RX!Y!RX!c!RX!e!RX!f!RX!g!RX!h!RX#o!RX#p!RX#q!RX#r!RX#s!RX#t!RX#x!RX$P!RX$a!RX#|!RX~OP!aOQ!bOR!bOS!cOT!cOW!iOX!hOb!jOc!kOd!lOz!`O$O!fO~O}qO!PqO!VqO!WqOgvahvaiva!cva!eva!fva!gva!hva#ova#pva#qva#rva#sva#tva~O!YuO#xva$Pva~P)lOguXhuXiuX}uX!cuX!euX!fuX!guX!huX#ouX#puX#quX#ruX#suX#tuX~O$P!oO~P+TO$P!pO~P+TO!l!tO#{PO$O!rO~O$O!uO~OYZOZ[OjUOkUOlUOmUOnUOoUOpUOqUOrUO#oYO#pYO#{PO$ORO$Q_O$R`O$SaO$TbO$UcO$VdO$WeO$XfO$YgO$ZhO$[iO$]jO$^kO$_lO$`mO~O!l!wO~P,tO$O!xO~O]!{O^!yO_!yOY#iPZ#iPj#iPk#iPl#iPm#iPn#iPo#iPp#iPq#iPr#iP!l#iP#o#iP#p#iP#{#iP$O#iP$Q#iP$R#iP$S#iP$T#iP$U#iP$V#iP$W#iP$X#iP$Y#iP$Z#iP$[#iP$]#iP$^#iP$_#iP$`#iP~O!l#TO~O|#UO~O$O#WO~O{#XO}#XO!O!XO!P!XO!c#YO!e#YO!f#YO!g#YO!h#YO~Oz#ZOg!ZXh!ZXi!ZX}!ZX!P!ZX!V!ZX!W!ZX!Y!ZX!c!ZX!e!ZX!f!ZX!g!ZX!h!ZX#o!ZX#p!ZX#q!ZX#r!ZX#s!ZX#t!ZX#x!ZX$P!ZX$a!ZX#|!ZX~O|#^O~Og#`Oh#aO#|#`Oi!Ra}!Ra!P!Ra!V!Ra!W!Ra!Y!Ra!c!Ra!e!Ra!f!Ra!g!Ra!h!Ra#o!Ra#p!Ra#q!Ra#r!Ra#s!Ra#t!Ra#x!Ra$P!Ra$a!Ra~O|#bO~Oz#cO~Oz#fO~Oz#jO~O}qO!PqO!VqO!WqO!Y#nO$a#pO~O$P#uO~O#|#vO~Oz#wO$P#yO~O$P#zO~P+TOg#uXh#uXi#uX}#uX!c#uX!e#uX!f#uX!g#uX!h#uX#o#uX#p#uX#q#uX#r#uX#s#uX#t#uX$P#uX~O#|#{O~P6{O!l#}O~P,tO$O$OO~OY#iXZ#iXj#iXk#iXl#iXm#iXn#iXo#iXp#iXq#iXr#iX!l#iX#o#iX#p#iX#{#iX$O#iX$Q#iX$R#iX$S#iX$T#iX$U#iX$V#iX$W#iX$X#iX$Y#iX$Z#iX$[#iX$]#iX$^#iX$_#iX$`#iX~O`$QOa$QO~P8dO^!yO_!yO~P8dO#|$YO~P+TO$P$ZO~O|$[O~OV$]O|#UO!d$^O!j$_O!l$`O~O{$aO~O#|$bOg![ah![ai![a}![a!P![a!V![a!W![a!Y![a!c![a!e![a!f![a!g![a!h![a#o![a#p![a#q![a#r![a#s![a#t![a#x![a$P![a$a![a~Og#`Oh#aO#|#`O$P$cO~O{$eO~O#|$fOg!nah!nai!na}!na!P!na!V!na!W!na!Y!na!c!na!e!na!f!na!g!na!h!na#o!na#p!na#q!na#r!na#s!na#t!na#x!na$P!na$a!na~O{!XO}!XO!O!XO!P!XOg!tXh!tXi!tX!V!tX!W!tX!Y!tX!c!tX!e!tX!f!tX!g!tX!h!tX#o!tX#p!tX#q!tX#r!tX#s!tX#t!tX#x!tX#|!tX$P!tX$a!tX~O#|$gOg!rah!rai!ra}!ra!P!ra!V!ra!W!ra!Y!ra!c!ra!e!ra!f!ra!g!ra!h!ra#o!ra#p!ra#q!ra#r!ra#s!ra#t!ra#x!ra$P!ra$a!ra~O{!XO}!XO!O!XO!P!XOg!wXh!wXi!wX!V!wX!W!wX!Y!wX!c!wX!e!wX!f!wX!g!wX!h!wX#o!wX#p!wX#q!wX#r!wX#s!wX#t!wX#x!wX#|!wX$P!wX$a!wX~O#|$hOg!uah!uai!ua}!ua!P!ua!V!ua!W!ua!Y!ua!c!ua!e!ua!f!ua!g!ua!h!ua#o!ua#p!ua#q!ua#r!ua#s!ua#t!ua#x!ua$P!ua$a!ua~OU$iO~P(tO!d$lO~O!Y$mO$a#pO~O}qO!PqO!VqO!WqO!Y#nO~O[$oO$P#[a~PFVO$P$tO~P5|O$P$uO~Oe{Of{Og!yqh!yqi!yq}!yq!c!yq!e!yq!f!yq!g!yq!h!yq#o!yq#p!yq#q!yq#r!yq#s!yq#t!yq#x!yq$P!yq#|!yq~O#|$xO$P$yO~Oe{Of{Og#fqh#fqi#fq}#fq!c#fq!e#fq!f#fq!g#fq!h#fq#o#fq#p#fq#q#fq#r#fq#s#fq#t#fq#x#fq$P#fq#|#fq~O$P$zO~P+TO#|$|O~P6{O#n$}O$P%QO~OY#iaZ#iaj#iak#ial#iam#ian#iao#iap#iaq#iar#ia!l#ia#o#ia#p#ia#{#ia$Q#ia$R#ia$S#ia$T#ia$U#ia$V#ia$W#ia$X#ia$Y#ia$Z#ia$[#ia$]#ia$^#ia$_#ia$`#ia~O$O$OO~PJ`O`%SOa%SO$O#ia~PJ`Og!POi!PO}!TO!c!TO!e!TO!f!TO!g!TO!h!TO#o!QO#p!QO#q#hq#r#hq#s#hq#t#hq#x#hq$P#hq~Oh#hq~PLtOg#hqh#hqi#hq~PLzOh!OO~PLtO#x#hq$P#hq~P%ZOg#hqh#hqi#hq}#hq!c#hq!e#hq!f#hq!g#hq!h#hq#q#hq#r#hq#s#hq#t#hq~O#o!QO#p!QO#x#hq$P#hq~PNoO|%TO~O$P%UO~O$O%VO~O|%WO~Oz#ZO~Og#`O#|#`Oh!_ii!_i}!_i!P!_i!V!_i!W!_i!Y!_i!c!_i!e!_i!f!_i!g!_i!h!_i#o!_i#p!_i#q!_i#r!_i#s!_i#t!_i#x!_i$P!_i$a!_i~Oz%YO|%YO~Oz%_O$c%aO$d%bO$e%cO~O[$oO$P#[i~O$b%eO~O$P#[i~PFVO!d%hO~O!Y$mO$P#[i~O$P%jO~P5|O!Y$mO$P%jO$a#pO~O$P%lO~Oz%mO~O$P%nO~P+TO#|%pO$P%qO~O$O$OOY#iiZ#iij#iik#iil#iim#iin#iio#iip#iiq#iir#ii!l#ii#o#ii#p#ii#{#ii$Q#ii$R#ii$S#ii$T#ii$U#ii$V#ii$W#ii$X#ii$Y#ii$Z#ii$[#ii$]#ii$^#ii$_#ii$`#ii~O#|%sO~O|%tO~O$O%uO~Og#`Oh#aO#|#`O!Y#_i$a#_i$P#_i~O!Y$mO$P#[q~O$P#[q~PFVO[$oO!Y%xO$P#[q~Oe{Of{Og!y!Rh!y!Ri!y!R}!y!R!c!y!R!e!y!R!f!y!R!g!y!R!h!y!R#o!y!R#p!y!R#q!y!R#r!y!R#s!y!R#t!y!R#x!y!R$P!y!R#|!y!R~Oe{Of{Og#f!Rh#f!Ri#f!R}#f!R!c#f!R!e#f!R!f#f!R!g#f!R!h#f!R#o#f!R#p#f!R#q#f!R#r#f!R#s#f!R#t#f!R#x#f!R$P#f!R#|#f!R~O$P%{O~P+TO#n$}O$P%}O~O|&OO~O$P&PO~Oz&QO~O!Y$mO$P#[y~O[$oO$P#[y~OU$iO~O!Y%xO$P#[y~O#|&TO~O$P&UO~O!Y$mO$P#[!R~O|&WO~O#|&XO~O|&YO~O$P&ZO~OP!aOQ!bOR!bOS!cOT!cOW&[OX!hOb!jOc!kOd!lOz!`O$O!fO~O!Y&]O#|va~P)lO!Y&]O#|vX~P#bOg&gOi&gO}&kO!c&kO!e&kO!f&kO!g&kO!h&kO#o&hO#p&hO#q#hq#r#hq#s#hq#t#hq#|#hq~Oh#hq~P!/kOg#hqh#hqi#hq~P!/qOh&fO~P!/kOg&gOh&fOi&gO}&kO!c&kO!e&kO!f&kO!g&kO!h&kO#o&hO#p&hO#q&iO#r&iO#s&iO#t&jO~O#|#hq~P!1XO#o&hO#p&hO#|#hq~PNoO',
// eslint-disable-next-line no-template-curly-in-string
goto: "0U#xPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP#y$x%a&P&SPPPPPP&k&}'_'m(OPP(_P(b(b(g(j(p)R)R)[PPPPPP)[P)RP(b(b)e)k(b(b)r)u(b){*O*U*w+^+s+s+s+s+s+s+s+s+s+s+s+s+s+s+s,Y,c,v-S-l-o-o-o-r.R*w.U*w.k/a/r/{0OPPPPPPP*w*w*w[WOR|!x#{$|Q$S!|Q$T!}S$U#O&bQ$V#PQ$W#QQ$X#RQ&l&`Q&m&aQ&n&cQ&o&dQ&p&eR&q!Vt^O|!V!x!|!}#O#P#Q#R#{$|&`&a&b&c&d&eRxRjQOR|!V!x!|!}#O#P#Q#R#{$|S!qz#vQ#s!r]&_&`&a&b&c&d&eRpPQoP^!eu!f#`#a#n$m&]Q#V!YS#g!k$gT#k!l$hQwQQ#o!qQ$n#rQ$r#sQ%i$qR&^&_[vQ!q#r#s$q&_]!nw#o$n$r%i&^itQw!q#o#r#s$n$q$r%i&^&_hsQw!q#o#r#s$n$q$r%i&^&_R!_tkrQtw!q#o#r#s$n$q$r%i&^&_R!^rV!mu#n&]R#]!aQ#[!aR%X$bU!gu#n&]Q#_!fQ$c#`Q$d#aR%f$m_!eu!f#`#a#n$m&]_!du!f#`#a#n$m&]Q#e!iR&V&[S#d!i&[R%Z$fR#i!kQ#h!kR%[$gR#m!lQ#l!lR%]$hj^O!|!}#O#P#Q#R&`&a&b&c&d&eQyRQ!v|Q#S!VQ#|!xQ${#{R%o$|w]OR|!V!x!|!}#O#P#Q#R#{$|&`&a&b&c&d&ewTOR|!V!x!|!}#O#P#Q#R#{$|&`&a&b&c&d&ewSOR|!V!x!|!}#O#P#Q#R#{$|&`&a&b&c&d&eQ!szQ#t!rR$w#vS#r!q#sW$k#o#q$r$sQ%d$jQ%k$tR%w%jQ$q#rQ%d$kQ%y%kR&R%wQ#q!qS$j#o$rQ$p#rQ$s#sS%g$n$qS%v%i%kR&S%yR%`$iR%^$iQ}VQ$v#uQ$z#zQ%z%lR%{%nR#x!uwVOR|!V!x!|!}#O#P#Q#R#{$|&`&a&b&c&d&eQ!|!OQ!}!PQ#O!QQ#P!RQ#Q!SQ#R!TQ&`&fQ&a&gQ&b&hQ&c&iQ&d&jR&e&kh!z!O!P!Q!R!S!T&f&g&h&i&j&kR$R!{Q$P!yQ%R$QR%r%SR%O$OQ%P$OR%|%p",
nodeNames: '⚠ Json Logfmt Unpack Pattern Regexp Unwrap Ip LabelFormat LineFormat LabelReplace Vector Offset Bool On Ignoring GroupLeft GroupRight Decolorize Drop Keep By Without And Or Unless Sum Avg Count Max Min Stddev Stdvar Bottomk Topk LineComment LogQL Expr LogExpr Selector Matchers Matcher Identifier Eq String Neq Re Nre PipelineExpr PipelineStage LineFilters LineFilter Filter PipeExact PipeMatch FilterOp Pipe LabelParser JsonExpressionParser JsonExpressionList JsonExpression LabelFilter IpLabelFilter UnitFilter DurationFilter Gtr Duration Gte Lss Lte Eql BytesFilter Bytes NumberFilter Number LineFormatExpr LabelFormatExpr LabelsFormat LabelFormatMatcher DecolorizeExpr DropLabelsExpr DropLabels DropLabel KeepLabelsExpr KeepLabels KeepLabel MetricExpr RangeAggregationExpr RangeOp CountOverTime Rate RateCounter BytesOverTime BytesRate AvgOverTime SumOverTime MinOverTime MaxOverTime StddevOverTime StdvarOverTime QuantileOverTime FirstOverTime LastOverTime AbsentOverTime LogRangeExpr Range OffsetExpr UnwrapExpr ConvOp BytesConv DurationConv DurationSecondsConv Grouping Labels VectorAggregationExpr VectorOp BinOpExpr BinOpModifier OnOrIgnoringModifier GroupingLabels GroupingLabelList GroupingLabel LabelName Add Sub Mul Div Mod Pow LiteralExpr LabelReplaceExpr VectorExpr',
maxTerm: 159,
skippedNodes: [0, 35],
repeatNodeCount: 0,
tokenData: "3X~RvX^#ipq#iqr$^rs$qst%cuv%nxy%syz%xz{%}{|&S|}&X}!O&^!O!P&c!P!Q'c!Q!R'h!R![)O![!]0O!^!_0d!_!`0q!`!a1W!c!}1e!}#O1{#P#Q2Q#Q#R2V#R#S1e#S#T2[#T#o1e#o#p2h#p#q2m#q#r3S#y#z#i$f$g#i#BY#BZ#i$IS$I_#i$I|$JO#i$JT$JU#i$KV$KW#i&FU&FV#i~#nY#z~X^#ipq#i#y#z#i$f$g#i#BY#BZ#i$IS$I_#i$I|$JO#i$JT$JU#i$KV$KW#i&FU&FV#i~$aQ!_!`$g#r#s$l~$lO}~~$qO!P~~$tUOY$qZr$qrs%Ws#O$q#O#P%]#P~$q~%]O|~~%`PO~$q~%hQs~OY%cZ~%c~%sO#s~~%xO$O~~%}O$P~~&SO#q~~&XO#o~~&^O#|~~&cO#p~~&fP!Q![&i~&nR!l~!Q![&i!g!h&w#X#Y&w~&zR{|'T}!O'T!Q!['Z~'WP!Q!['Z~'`P!l~!Q!['Z~'hO#r~~'me!l~!O!P&i!Q![)O!g!h*c!i!j+Q!m!n+Q!o!p+Q!r!s+Q!v!w+Q#U#V*u#W#X+Z#X#Y-]#Z#[-o#[#]+r#_#`-o#a#b-x#d#e-o#g#h,z#h#i-o#k#l.Z#l#m/d#m#n.u~)Td!l~!O!P&i!Q![)O!g!h*c!i!j+Q!m!n+Q!o!p+Q!r!s+Q!v!w+Q#U#V*u#W#X+Z#X#Y-]#Z#[-o#[#]+r#_#`-o#a#b-x#d#e-o#g#h,z#h#i-o#k#l.Z#m#n.u~*fT{|'T}!O'T!Q!['Z!d!e*u#]#^*z~*zO!j~~*}P#U#V*u~+TQ!d!e*u#]#^*z~+`P!d~!Q![+c~+fS!Q![+c#[#]+r#a#b,W#g#h,z~+wP!d~!Q![+z~+}R!Q![+z#a#b,W#g#h,z~,]Q!d~!Q![,c#g#h,u~,fR!Q![,c#a#b,o#g#h,z~,rP#g#h,u~,zO!d~~-PP!d~!Q![-S~-VQ!Q![-S#a#b,o~-`T{|'T}!O'T!Q!['Z#U#V*u#]#^*z~-rQ#U#V*u#]#^*z~-}S!d~!Q![,c#U#V*u#]#^*z#g#h,u~.`P!d~!Q![.c~.fT!Q![.c#W#X+Z#[#]+r#a#b,W#g#h,z~.zP!d~!Q![.}~/QU!Q![.}#W#X+Z#[#]+r#a#b,W#g#h,z#k#l.Z~/gR!Q![/p!c!i/p#T#Z/p~/uR!l~!Q![/p!c!i/p#T#Z/pP0TTzP!Q![0O![!]0O!c!}0O#R#S0O#T#o0O~0iP!f~!_!`0l~0qO!g~~0vQ{~!_!`0|#r#s1R~1RO!h~~1WO!O~~1]P!c~!_!`1`~1eO!e~R1lTzP#nQ!Q![1e![!]0O!c!}1e#R#S1e#T#o1e~2QO$a~~2VO$b~~2[O#t~~2_RO#S2[#S#T%W#T~2[~2mO#{~~2rQ!Y~!_!`2x#r#s2}~2}O!V~~3SO!W~~3XO#}~",
tokenizers: [0, 1],
topRules: { LogQL: [0, 36] },
specialized: [{ term: 42, get: (value, stack) => (specializeIdentifier(value) << 1) }, { term: 42, get: (value, stack) => (extendIdentifier(value) << 1) | 1 }, { term: 42, get: value => spec_Identifier[value] || -1 }],
tokenPrec: 0
})
// This file was generated by lezer-generator. You probably shouldn't edit it.
const Json = 1
const Logfmt = 2
const Unpack = 3
const Pattern = 4
const Regexp = 5
const Unwrap = 6
const Ip = 7
const LabelFormat = 8
const LineFormat = 9
const LabelReplace = 10
const Vector = 11
const Offset = 12
const Bool = 13
const On = 14
const Ignoring = 15
const GroupLeft = 16
const GroupRight = 17
const Decolorize = 18
const Drop = 19
const Keep = 20
const By = 21
const Without = 22
const And = 23
const Or = 24
const Unless = 25
const Sum = 26
const Avg = 27
const Count = 28
const Max = 29
const Min = 30
const Stddev = 31
const Stdvar = 32
const Bottomk = 33
const Topk = 34
const LineComment = 35
const LogQL = 36
const Expr = 37
const LogExpr = 38
const Selector = 39
const Matchers = 40
const Matcher = 41
const Identifier = 42
const Eq = 43
const String = 44
const Neq = 45
const Re = 46
const Nre = 47
const PipelineExpr = 48
const PipelineStage = 49
const LineFilters = 50
const LineFilter = 51
const Filter = 52
const PipeExact = 53
const PipeMatch = 54
const FilterOp = 55
const Pipe = 56
const LabelParser = 57
const JsonExpressionParser = 58
const JsonExpressionList = 59
const JsonExpression = 60
const LabelFilter = 61
const IpLabelFilter = 62
const UnitFilter = 63
const DurationFilter = 64
const Gtr = 65
const Duration = 66
const Gte = 67
const Lss = 68
const Lte = 69
const Eql = 70
const BytesFilter = 71
const Bytes = 72
const NumberFilter = 73
const Number = 74
const LineFormatExpr = 75
const LabelFormatExpr = 76
const LabelsFormat = 77
const LabelFormatMatcher = 78
const DecolorizeExpr = 79
const DropLabelsExpr = 80
const DropLabels = 81
const DropLabel = 82
const KeepLabelsExpr = 83
const KeepLabels = 84
const KeepLabel = 85
const MetricExpr = 86
const RangeAggregationExpr = 87
const RangeOp = 88
const CountOverTime = 89
const Rate = 90
const RateCounter = 91
const BytesOverTime = 92
const BytesRate = 93
const AvgOverTime = 94
const SumOverTime = 95
const MinOverTime = 96
const MaxOverTime = 97
const StddevOverTime = 98
const StdvarOverTime = 99
const QuantileOverTime = 100
const FirstOverTime = 101
const LastOverTime = 102
const AbsentOverTime = 103
const LogRangeExpr = 104
const Range = 105
const OffsetExpr = 106
const UnwrapExpr = 107
const ConvOp = 108
const BytesConv = 109
const DurationConv = 110
const DurationSecondsConv = 111
const Grouping = 112
const Labels = 113
const VectorAggregationExpr = 114
const VectorOp = 115
const BinOpExpr = 116
const BinOpModifier = 117
const OnOrIgnoringModifier = 118
const GroupingLabels = 119
const GroupingLabelList = 120
const GroupingLabel = 121
const LabelName = 122
const Add = 123
const Sub = 124
const Mul = 125
const Div = 126
const Mod = 127
const Pow = 128
const LiteralExpr = 129
const LabelReplaceExpr = 130
const VectorExpr = 131
function getNodeFromQuery (query, nodeType) {
const nodes = []
const tree = parser.parse(query)
tree.iterate({
enter: (node) => {
if (nodeType === undefined || nodeType === node.type.id) {
nodes.push(node.node)
}
}
})
return nodes[0]
}
function isLogsQuery (query) {
if (getNodeFromQuery(query, MetricExpr$1)) {
return false
}
return true
}
function indent (level) {
return ' '.repeat(level)
}
function indentMultiline (block, level) {
const lines = block.split('\n')
return lines.map((line) => indent(level) + line).join('\n')
}
function trimMultiline (block) {
const lines = block.split('\n')
return lines.map((line) => line.trimEnd()).join('\n')
}
function needsBrackets (node, queryType) {
const childNodeIsSame = node.firstChild && (node.firstChild.type.id === queryType)
let addBrackets = false
if (node.firstChild && childNodeIsSame) {
addBrackets = true
node = node.firstChild
}
return { addBrackets, newNode: node }
}
function iterateNode (node, lookingFor) {
const nodes = []
let child = node.firstChild
while (child) {
if (lookingFor.includes(child.type.id)) {
nodes.push(child)
}
nodes.push(...iterateNode(child, lookingFor))
child = child.nextSibling
}
return nodes
}
function buildResponse (pipelineType, lastPipelineType, formattedNode) {
if (lastPipelineType === pipelineType) {
return ` ${formattedNode}`
}
return `\n${indent(1)}${formattedNode}`
}
function trimEnd (input, charactersToTrim) {
let endIndex = input.length - 1
while (endIndex >= 0 && charactersToTrim.includes(input[endIndex])) {
endIndex--
}
return input.substring(0, endIndex + 1)
}
const formatLogExpr = (node, query) => {
const { addBrackets, newNode } = needsBrackets(node, LogExpr)
node = newNode
const tree = parser.parse(query.substring(node.from, node.to))
let formatted = ''
tree.iterate({
enter: (ref) => {
const node = ref.node
switch (node.type.id) {
case Selector:
formatted += formatSelector(node, query)
break
case PipelineExpr:
node.parent && (node.parent.type.id !== PipelineExpr && (formatted += formatPipelineExpr(node, query)))
break
}
}
})
return addBrackets ? '(' + formatted + ')' : formatted
}
function formatSelector (node, query) {
const selector = query.substring(node.from, node.to)
const subtree = parser.parse(selector)
const labelNodes = []
let response = ''
subtree.iterate({
enter: (ref) => {
const node = ref.node
if (node.type.id === Matcher) {
labelNodes.push(node)
}
}
})
labelNodes.sort((a, b) => {
const labelNodeA = a.getChild(Identifier)
const labelNodeB = b.getChild(Identifier)
const labelValueA = labelNodeA && query.substring(labelNodeA.from, labelNodeA.to)
const labelValueB = labelNodeB && query.substring(labelNodeB.from, labelNodeB.to)
if (!labelValueA || !labelValueB) {
return 0
}
if (labelValueA < labelValueB) {
return -1
}
if (labelValueA > labelValueB) {
return 1
}
return 0
})
labelNodes.forEach((node) => {
const labelNode = node.getChild(Identifier)
const operatorNode = labelNode ? labelNode.nextSibling : null
const valueNode = node.getChild(String)
const label = labelNode ? query.substring(labelNode.from, labelNode.to) : null
const operator = operatorNode ? query.substring(operatorNode.from, operatorNode.to) : null
const value = valueNode ? query.substring(valueNode.from, valueNode.to) : null
response += `${label}${operator}${value}, `
})
return '{' + trimEnd(response, ', ') + '}'
}
function formatPipelineExpr (node, query) {
const pipelineExprNodes = [
LineFilter,
LabelParser,
LabelFilter,
JsonExpressionParser,
LineFormatExpr,
LabelFormatExpr,
DecolorizeExpr
]
let lastPipelineType
let response = ''
iterateNode(node, pipelineExprNodes).forEach((node) => {
switch (node.type.id) {
case LineFilter:
response += buildResponse(LineFilter, lastPipelineType, formatLineFilter(node, query))
lastPipelineType = LineFilter
break
case LabelParser:
response += buildResponse(LabelParser, lastPipelineType, formatLabelParser(node, query))
lastPipelineType = LabelParser
break
case JsonExpressionParser:
response += buildResponse(JsonExpressionParser, lastPipelineType, formatJsonExpressionParser(node, query))
lastPipelineType = JsonExpressionParser
break
case LabelFilter:
response += buildResponse(LabelFilter, lastPipelineType, formatLabelFilter(node, query))
lastPipelineType = LabelFilter
break
case LineFormatExpr:
response += buildResponse(LineFormatExpr, lastPipelineType, formatLineFormatExpr(node, query))
lastPipelineType = LineFormatExpr
break
case LabelFormatExpr:
response += buildResponse(LabelFormatExpr, lastPipelineType, formatLabelFormatExpr(node, query))
lastPipelineType = LabelFormatExpr
break
case DecolorizeExpr:
response += buildResponse(DecolorizeExpr, lastPipelineType, formatDecolorizeExpr())
lastPipelineType = DecolorizeExpr
break
}
})
return response
}
function formatLineFilter (node, query) {
const filterNode = node.getChild(Filter)
const filterOperationNode = node.getChild(FilterOp)
const stringNode = node.getChild(String)
const filter = filterNode && query.substring(filterNode.from, filterNode.to)
const string = stringNode && query.substring(stringNode.from, stringNode.to)
if (filterOperationNode) {
return `${filter} ip(${string})`
}
return `${filter} ${string}`
}
function formatLabelParser (node, query) {
const hasString = node.getChild(String)
if (hasString) {
const parserNode = node.getChild(Regexp) || node.getChild(Pattern)
const stringNode = node.getChild(String)
const parser = parserNode && query.substring(parserNode.from, parserNode.to)
const string = stringNode && query.substring(stringNode.from, stringNode.to)
return `| ${parser}${string}`
}
const labelParser = query.substring(node.from, node.to)
return `| ${labelParser}`
}
function formatJsonExpressionParser (node, query) {
const jsonExpressionNodes = iterateNode(node, [JsonExpression])
let response = ''
jsonExpressionNodes.forEach((node) => {
const identifierNode = node.getChild(Identifier)
const valueNode = node.getChild(String)
const identifier = identifierNode && query.substring(identifierNode.from, identifierNode.to)
const value = valueNode && query.substring(valueNode.from, valueNode.to)
response += `${identifier}=${value}, `
})
return `| json ${trimEnd(response, ', ')}`
}
function formatLabelFilter (node, query) {
const selectedFilter =
node.getChild(Matcher) ||
node.getChild(IpLabelFilter) ||
node.getChild(NumberFilter) ||
(node.getChild(UnitFilter) && node.getChild(UnitFilter).getChild(DurationFilter)) ||
(node.getChild(UnitFilter) && (node.getChild(UnitFilter).getChild(BytesFilter)))
if (!selectedFilter) {
return ''
}
const selectedFilterType = selectedFilter.type.id
const identifierNode = selectedFilter.getChild(Identifier)
const operatorNode = identifierNode && identifierNode.nextSibling
let valueNode
if (selectedFilterType === DurationFilter) {
valueNode = selectedFilter.getChild(Duration)
} else if (selectedFilterType === BytesFilter) {
valueNode = selectedFilter.getChild(Bytes)
} else if (selectedFilterType === NumberFilter) {
valueNode = selectedFilter.getChild(Number)
} else {
valueNode = selectedFilter.getChild(String)
}
const identifier = identifierNode && query.substring(identifierNode.from, identifierNode.to)
const operator = operatorNode && query.substring(operatorNode.from, operatorNode.to)
const value = valueNode && query.substring(valueNode.from, valueNode.to)
if (selectedFilterType === IpLabelFilter) {
return `| ${identifier}${operator}ip(${value})`
}
return `| ${identifier}${operator}${value}`
}
function formatLineFormatExpr (node, query) {
const stringNode = node.getChild(String)
const string = stringNode && query.substring(stringNode.from, stringNode.to)
return `| line_format ${string}`
}
function formatLabelFormatExpr (node, query) {
const labelFormatMatcherNodes = iterateNode(node, [LabelFormatMatcher])
let response = '| label_format '
labelFormatMatcherNodes.forEach((labelFormatMatcherNode) => {
let identifierNode
let valueNode
if (labelFormatMatcherNode.getChildren(Identifier).length === 2) {
[identifierNode, valueNode] = labelFormatMatcherNode.getChildren(Identifier)
} else {
identifierNode = labelFormatMatcherNode.getChild(Identifier)
valueNode = labelFormatMatcherNode.getChild(String)
}
const identifier = identifierNode && query.substring(identifierNode.from, identifierNode.to)
const value = valueNode && query.substring(valueNode.from, valueNode.to)
response += `${identifier}=${value}, `
})
return trimEnd(response, ', ')
}
function formatDecolorizeExpr () {
// eslint-disable-next-line quotes
return `| decolorize`
}
const formatMetricExpr = (node, query) => {
const { addBrackets, newNode } = needsBrackets(node, MetricExpr)
node = newNode
let formatted = ''
const childNode = node.firstChild
switch (childNode && childNode.type.id) {
case RangeAggregationExpr:
formatted = formatRangeAggregationExpr(node, query)
break
case VectorAggregationExpr:
formatted = formatVectorAggregationExpr(node, query)
break
case BinOpExpr:
formatted = formatBinOpExpr(node, query)
break
case LiteralExpr:
formatted = formatLiteralExpr(node, query)
break
case LabelReplaceExpr:
formatted = formatLabelReplaceExpr(node, query)
break
case VectorExpr:
formatted = formatVectorExpr(node, query)
break
}
return addBrackets ? '(' + formatted + ')' : formatted
}
function formatRangeAggregationExpr (node, query) {
let response = ''
iterateNode(node, [RangeOp, Number, LogRangeExpr, Grouping]).forEach((node) => {
if (node.parent && (node.parent.type.id !== RangeAggregationExpr)) {
return
}
switch (node.type.id) {
case RangeOp:
response += `${query.substring(node.from, node.to)}(\n`
break
case Number:
response += `${indent(1) + query.substring(node.from, node.to)},\n`
break
case LogRangeExpr:
response += formatLogRangeExpr(node, query)
break
case Grouping:
response += formatGrouping(node, query)
break
}
})
return response
}
function formatLogRangeExpr (node, query) {
const nodes = []
let selector = ''
let pipeline = ''
let range = ''
let offset = ''
let unwrap = ''
iterateNode(node, [Selector, Range, OffsetExpr, UnwrapExpr, PipelineExpr]).forEach((node) => {
if (node.parent && (node.parent.type.id !== LogRangeExpr)) {
return
}
nodes.push(node)
switch (node.type.id) {
case Selector: {
const logExpr = query.substring(node.from, node.to)
selector += formatSelector({ ...node, from: 0, to: logExpr.length }, logExpr)
break
}
case PipelineExpr:
pipeline += formatPipelineExpr(node, query)
break
case Range:
range += query.substring(node.from, node.to)
break
case OffsetExpr: {
const durationNode = node.getChild(Duration)
offset += ` offset ${durationNode ? query.substring(durationNode.from, durationNode.to) : ''}`
break
}
case UnwrapExpr:
iterateNode(node, [Identifier, ConvOp, LabelFilter]).forEach((node, _, arr) => {
switch (node.type.id) {
case Identifier: {
if (node.parent && (node.parent.type.id !== UnwrapExpr)) {
return
}
const hasConvOp = arr.find((node) => node.type.id === ConvOp)
if (hasConvOp) {
return
}
unwrap += `| unwrap ${query.substring(node.from, node.to)} `
return
}
case ConvOp: {
const identifierNode = arr.find((node) => node.type.id === Identifier)
const identifier = identifierNode ? query.substring(identifierNode.from, identifierNode.to) : ''
unwrap += `| unwrap ${query.substring(node.from, node.to)}(${identifier}) `
return
}
case LabelFilter:
unwrap += formatLabelFilter(node, query)
}
})
break
}
})
let response = ''
nodes.forEach((node, index, array) => {
const previousNode = array[index - 1]
if (node.type.id === Selector) {
response += indent(1) + selector
}
if (node.type.id === PipelineExpr) {
response += indentMultiline(pipeline, 1)
}
if (node.type.id === Range) {
response += '\n' + indent(1) + range
}
if (node.type.id === OffsetExpr) {
response += offset
}
if (node.type.id === UnwrapExpr) {
if (previousNode && ((previousNode.type.id !== OffsetExpr)) && (previousNode && (previousNode.type.id !== Range))) {
response += '\n' + indent(1) + unwrap
} else {
response += ' ' + unwrap
}
}
})
return (response += '\n)')
}
function formatGrouping (node, query) {
let response = ''
const labels = iterateNode(node, [Identifier]).map((node) => {
return query.substring(node.from, node.to)
})
iterateNode(node, [By, Without]).forEach((node) => {
if (node.parent && (node.parent.type.id !== Grouping)) {
return
}
switch (node.type.id) {
case By:
response = ` by (${labels.join(', ')}) `
break
case Without:
response = ` without (${labels.join(', ')}) `
break
}
})
return response
}
function formatVectorAggregationExpr (node, query) {
let response = ''
iterateNode(node, [VectorOp, Number, MetricExpr, Grouping]).forEach((node, _, arr) => {
if (node.parent && (node.parent.type.id !== VectorAggregationExpr)) {
return
}
switch (node.type.id) {
case VectorOp:
response += `${query.substring(node.from, node.to)}`
break
case Number:
response += '(\n'
response += `${indent(1) + query.substring(node.from, node.to)},\n`
break
case MetricExpr: {
const hasNumber = arr.find((node) => node.type.id === Number && node.parent.type.id === VectorAggregationExpr)
response += hasNumber ? '' : '(\n'
const metricExpr = query.substring(node.from, node.to)
const metricNode = getNodeFromQuery(metricExpr, MetricExpr)
response += indentMultiline(formatMetricExpr(metricNode, metricExpr), 1)
response += '\n)'
break
}
case Grouping:
response += formatGrouping(node, query)
break
}
})
return response
}
function formatBinOpExpr (node, query) {
let operator
const [leftExpr, rightExpr] = iterateNode(node, [Expr]).map((node, idx) => {
if (idx === 0) {
operator = query.substring(node.nextSibling.from || 0, node.nextSibling.to)
}
const expr = query.substring(node.from, node.to)
let expressionNode
if (isLogsQuery(expr)) {
expressionNode = getNodeFromQuery(expr, LogExpr$1)
return formatLogExpr(expressionNode, expr)
} else {
expressionNode = getNodeFromQuery(expr, MetricExpr)
return formatMetricExpr(expressionNode, expr)
}
})
return leftExpr + '\n' + operator + '\n' + rightExpr
}
function formatLiteralExpr (node, query) {
node = node.getChild(LiteralExpr) || node
const addNode = node.getChild(Add)
const subNode = node.getChild(Sub)
const numberNode = node.getChild(Number)
if (!numberNode) {
return ''
}
if (addNode) {
return `+${query.substring(numberNode.from, numberNode.to)}`
}
if (subNode) {
return `-${query.substring(numberNode.from, numberNode.to)}`
}
return query.substring(numberNode.from, numberNode.to)
}
function formatLabelReplaceExpr (node, query) {
let response = 'label_replace(\n'
iterateNode(node, [MetricExpr, String]).forEach((node) => {
if (node.parent.type.id !== LabelReplaceExpr) {
return
}
if (node.type.id === MetricExpr) {
const metricExpr = query.substring(node.from, node.to)
const metricNode = getNodeFromQuery(metricExpr, MetricExpr)
response += indentMultiline(formatMetricExpr(metricNode, metricExpr), 1) + ',\n'
} else {
response += indent(1) + query.substring(node.from, node.to) + ',\n'
}
})
return trimEnd(response, ',\n') + '\n)'
}
function formatVectorExpr (node, query) {
node = node.getChild(VectorExpr) || node
const numberNode = node.getChild(Number)
if (!numberNode) {
return ''
}
return `vector(${query.substring(numberNode.from, numberNode.to)})`
}
/**
* @experimental This feature is subject to change or removal in future versions.
*/
const formatLokiQuery = (query) => {
const tree = parser.parse(query)
let formatted = ''
tree.iterate({
enter: (ref) => {
const node = ref.node
if (lodash.get(node, 'parent.type.id', '') !== Expr || lodash.get(node,'parent.parent.type.id', '') === BinOpExpr) {
return
}
switch (node.type.id) {
case MetricExpr:
formatted = formatMetricExpr(node, query)
return false
case LogExpr:
formatted = formatLogExpr(node, query)
return false
}
}
})
return trimMultiline(formatted)
}
export { AbsentOverTime, Add, And, Avg, AvgOverTime, BinOpExpr, BinOpModifier, Bool, Bottomk, By, Bytes, BytesConv, BytesFilter, BytesOverTime, BytesRate, ConvOp, Count, CountOverTime, Decolorize, DecolorizeExpr, Div, Drop, DropLabel, DropLabels, DropLabelsExpr, Duration, DurationConv, DurationFilter, DurationSecondsConv, Eq, Eql, Expr, Filter, FilterOp, FirstOverTime, GroupLeft, GroupRight, Grouping, GroupingLabel, GroupingLabelList, GroupingLabels, Gte, Gtr, Identifier, Ignoring, Ip, IpLabelFilter, Json, JsonExpression, JsonExpressionList, JsonExpressionParser, Keep, KeepLabel, KeepLabels, KeepLabelsExpr, LabelFilter, LabelFormat, LabelFormatExpr, LabelFormatMatcher, LabelName, LabelParser, LabelReplace, LabelReplaceExpr, Labels, LabelsFormat, LastOverTime, LineComment, LineFilter, LineFilters, LineFormat, LineFormatExpr, LiteralExpr, LogExpr, LogQL, LogRangeExpr, Logfmt, Lss, Lte, Matcher, Matchers, Max, MaxOverTime, MetricExpr, Min, MinOverTime, Mod, Mul, Neq, Nre, Number, NumberFilter, Offset, OffsetExpr, On, OnOrIgnoringModifier, Or, Pattern, Pipe, PipeExact, PipeMatch, PipelineExpr, PipelineStage, Pow, QuantileOverTime, Range, RangeAggregationExpr, RangeOp, Rate, RateCounter, Re, Regexp, Selector, Stddev, StddevOverTime, Stdvar, StdvarOverTime, String, Sub, Sum, SumOverTime, Topk, UnitFilter, Unless, Unpack, Unwrap, UnwrapExpr, Vector, VectorAggregationExpr, VectorExpr, VectorOp, Without, formatLokiQuery, parser }

View File

@@ -0,0 +1,388 @@
<template>
<MonacoEditor
v-model="code"
theme="nz"
ref="monacoEditor"
style="width: 100%;height: auto;min-height: 40px;border: 1px solid #dedede"
language="logql"
:options="MONACO_EDITOR_OPTIONS"
@editorWillMount="handelBeforeMount"
@editorDidMount="handleMount"
@change="handleChange"
/>
</template>
<script>
import { languageConfiguration, monarchlanguage } from './monacoConfig'
import { parser, formatLokiQuery } from './lezerConfig'
import { validateQuery, placeHolderScopedVars } from './validation.ts'
import { getSituation } from './situation'
// import { sceneGraph } from '@grafana/scenes'
import MonacoEditor from 'vue-monaco'
export default {
name: 'logql',
props: {
code: String
},
// model: {
// prop: 'code',
// event: 'change'
// },
components: {
MonacoEditor
},
data () {
return {
code: '',
LANGUAGE_SETUP_STARTED: false,
parser,
MONACO_EDITOR_OPTIONS: {
automaticLayout: false,
formatOnType: true,
formatOnPaste: true,
codeLens: false,
contextmenu: false,
// we need `fixedOverflowWidgets` because otherwise in grafana-dashboards
// the popup is clipped by the panel-visualizations.
fixedOverflowWidgets: true,
folding: false,
fontSize: 14,
lineDecorationsWidth: 8, // used as "padding-left"
lineNumbers: 'off',
minimap: { enabled: true },
overviewRulerBorder: false,
overviewRulerLanes: 0,
padding: {
// these numbers were picked so that visually this matches the previous version
// of the query-editor the best
top: 4,
bottom: 5
},
renderLineHighlight: 'none',
scrollbar: {
// vertical: 'hidden',
verticalScrollbarSize: 8, // used as "padding-right"
horizontal: 'hidden',
horizontalScrollbarSize: 0
},
scrollBeyondLastLine: false,
suggest: {
showWords: true,
/**
* Enable custom contextmenu.
* Defaults to false.
*/
contextmenu: true,
/**
* The number of spaces a tab is equal to.
* This setting is overridden based on the file contents when `detectIndentation` is on.
* Defaults to 4.
*/
tabSize: 4,
/**
* Show code lens
* Defaults to false.
*/
codeLens: true,
/**
* Control the width of line numbers, by reserving horizontal space for rendering at least an amount of digits.
* Defaults to 4.
*/
lineNumbersMinChars: 4,
/**
* The width reserved for line decorations (in px).
* Line decorations are placed between line numbers and the editor content.
* You can pass in a string in the format floating point followed by "ch". e.g. 1.3ch.
* Defaults to 1 * theme.spacing.gridSize.
*/
// lineDecorationsWidth?: number | string;
/**
* Controls if a border should be drawn around the overview ruler.
* Defaults to `false`.
*/
overviewRulerBorder: false,
/**
* Enable that the editor will install an interval to check if its container dom node size has changed.
* Enabling this might have a severe performance impact.
* Defaults to true.
*/
automaticLayout: true
},
suggestFontSize: 12,
wordWrap: 'on',
placeHolderScopedVars: {
__interval: { text: '1s', value: '1s' },
__auto: { text: '1s', value: '1s' },
__interval_ms: { text: '1000', value: 1000 },
__range_ms: { text: '1000', value: 1000 },
__range_s: { text: '1', value: 1 },
__range: { text: '1s', value: '1s' }
}
},
templateSrv: ''
}
},
methods: {
handleChange (value, event) {
},
handleMount (editor) {
// // const monaco = this.$refs.monaco
// console.log(this.$refs.monacoEditor, this.$refs.monacoEditor.monaco)
// console.log(editor)
const LANG_ID = 'logql'
const monaco = this.$refs.monacoEditor.monaco
const self = this
// self.setPlaceholder(monaco, editor)
// editor.onDidChangeModelContent((e) => {
// const model = editor.getModel()
// if (!model) {
// return
// }
// const query = model.getValue()
// const errors =
// validateQuery(
// query,
// self.interpolateString(query, placeHolderScopedVars),
// model.getLinesContent()
// ) || []
// const markers = errors.map(({ error, ...boundary }) => ({
// message: `${
// error ? `Error parsing "${error}"` : 'Parse error'
// }. The query appears to be incorrect and could fail to be executed.`,
// severity: monaco.MarkerSeverity.Error,
// ...boundary
// }))
// console.log(errors)
// // onTypeDebounced(query)
// monaco.editor.setModelMarkers(model, 'owner', markers)
// })
},
handelBeforeMount (monaco) {
const LANG_ID = 'logql'
const self = this
if (this.LANGUAGE_SETUP_STARTED === false) {
this.LANGUAGE_SETUP_STARTED = true
// console.log(monaco)
monaco.languages.register({ id: LANG_ID })
monaco.languages.setLanguageConfiguration(LANG_ID, languageConfiguration)
monaco.languages.setMonarchTokensProvider(LANG_ID, monarchlanguage)
monaco.editor.defineTheme('nz', {
base: 'vs',
inherit: true,
colors: {
'editor.background': '#ffffff',
'minimap.background': '#f9f9f9'
},
// fallback syntax highlighting for languages that microsoft doesn't handle (ex cloudwatch's metric math)
rules: [
{ token: 'predefined', foreground: '#FF6600' },
{ token: 'operator', foreground: '#009966' },
{ token: 'tag', foreground: '#006699' }
]
})
monaco.languages.registerCompletionItemProvider('logql', {
provideCompletionItems: (model, position) => {
const suggestions = [
...monarchlanguage.keywords.map(k => {
// console.log(k)
return {
label: k,
kind: monaco.languages.CompletionItemKind.Keyword,
insertText: k
}
})
]
return { suggestions: suggestions }
}
})
}
},
nzSuggest (model, position) {
// console.log(model, position)
const suggestions = []
// console.log(parser.parse(this.code))
return suggestions
},
suggest (model, position) {
const monaco = this.$refs.monacoEditor.monaco
const self = this
const word = model.getWordAtPosition(position)
const INSERT_AS_SNIPPET_ENUM_VALUE = 4
console.log(monaco.Range.fromPositions(position))
const range = monaco.Range.fromPositions(position)
// documentation says `position` will be "adjusted" in `getOffsetAt`
// i don't know what that means, to be sure i clone it
const positionClone = {
column: position.column,
lineNumber: position.lineNumber
}
const offset = model.getOffsetAt(positionClone)
console.log(offset)
const situation = getSituation(model.getValue(), offset)
console.log(situation)
const completionsPromise = situation != null ? Promise.resolve([]) : Promise.resolve([])
return completionsPromise.then((items) => {
// monaco by default alphabetically orders the items.
// to stop it, we use a number-as-string sortkey,
// so that monaco keeps the order we use
const maxIndexDigits = items.length.toString().length
const suggestions = items.map((item, index) => ({
kind: self.getMonacoCompletionItemKind(item.type, monaco),
label: item.label,
insertText: item.insertText,
insertTextRules: item.isSnippet ? INSERT_AS_SNIPPET_ENUM_VALUE : undefined,
detail: item.detail,
documentation: item.documentation,
sortText: index.toString().padStart(maxIndexDigits, '0'), // to force the order we have
range,
command: item.triggerOnInsert
? {
id: 'editor.action.triggerSuggest',
title: ''
}
: undefined
}))
return { suggestions }
})
},
getMonacoCompletionItemKind (type, monaco) {
switch (type) {
case 'DURATION':
return monaco.languages.CompletionItemKind.Unit
case 'FUNCTION':
return monaco.languages.CompletionItemKind.Variable
case 'HISTORY':
return monaco.languages.CompletionItemKind.Snippet
case 'LABEL_NAME':
return monaco.languages.CompletionItemKind.Enum
case 'LABEL_VALUE':
return monaco.languages.CompletionItemKind.EnumMember
case 'PATTERN':
return monaco.languages.CompletionItemKind.Constructor
case 'PARSER':
return monaco.languages.CompletionItemKind.Class
case 'LINE_FILTER':
return monaco.languages.CompletionItemKind.TypeParameter
case 'PIPE_OPERATION':
return monaco.languages.CompletionItemKind.Interface
default:
return `Unexpected case in switch statement: ${JSON.stringify(type)}`
}
},
interpolateString (string, scopedVars) {
return this.interpolate(string, scopedVars, this.interpolateQueryExpr)
},
interpolateQueryExpr (value, variable) {
// if no multi or include all do not regexEscape
if (!variable.multi && !variable.includeAll) {
return this.lokiRegularEscape(value)
}
if (typeof value === 'string') {
return this.lokiSpecialRegexEscape(value)
}
const escapedValues = this.$lodash.map(value, this.lokiSpecialRegexEscape)
return escapedValues.join('|')
},
lokiRegularEscape (value) {
if (typeof value === 'string') {
return value.replace(/'/g, "\\\\'")
}
return value
},
lokiSpecialRegexEscape (value) {
if (typeof value === 'string') {
return this.lokiRegularEscape(value.replace(/\\/g, '\\\\\\\\').replace(/[$^*{}\[\]+?.()|]/g, '\\\\$&'))
}
return value
},
setPlaceholder (monaco, editor) {
const placeholderDecorators = [
{
range: new monaco.Range(1, 1, 1, 1),
options: {
className: 'nz-eqweqwe',
isWholeLine: true
}
}
]
let decorators = []
const checkDecorators = () => {
const model = editor.getModel()
if (!model) {
return
}
const newDecorators = model.getValueLength() === 0 ? placeholderDecorators : []
decorators = model.deltaDecorations(decorators, newDecorators)
}
checkDecorators()
editor.onDidChangeModelContent(checkDecorators)
},
interpolate (target, scopedVars, format, interpolations) {
if (scopedVars && scopedVars.__sceneObject) {
return sceneGraph.interpolate(
scopedVars.__sceneObject.value,
target,
scopedVars,
format
)
}
if (!target) {
return target || ''
}
this.regex.lastIndex = 0
return this._replaceWithVariableRegex(target, format, (match, variableName, fieldPath, fmt) => {
const value = this._evaluateVariableExpression(match, variableName, fieldPath, fmt, scopedVars)
// If we get passed this interpolations map we will also record all the expressions that were replaced
if (interpolations) {
interpolations.push({ match, variableName, fieldPath, format: fmt, value, found: value !== match })
}
return value
})
},
sceneInterpolator (sceneObject, target, scopedVars, format) {
const VARIABLE_REGEX = /\$(\w+)|\[\[(\w+?)(?::(\w+))?\]\]|\${(\w+)(?:\.([^:^\}]+))?(?::([^\}]+))?}/g
if (!target) {
return target != null ? target : ''
}
VARIABLE_REGEX.lastIndex = 0
return target.replace(VARIABLE_REGEX, (match, var1, var2, fmt2, var3, fieldPath, fmt3) => {
const variableName = var1 || var2 || var3
const fmt = fmt2 || fmt3 || format
const variable = this.lookupFormatVariable(variableName, match, scopedVars, sceneObject)
if (!variable) {
return match
}
return this.formatValue(variable, variable.getValue(fieldPath), fmt)
})
},
formatValue (variable, value, formatNameOrFn) {
if (value === null || value === 0) {
return ''
} else {
return value
}
},
lookupFormatVariable (name, match, scopedVars, sceneObject) {
console.log(name, match, scopedVars, sceneObject)
return null
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,340 @@
import { languageConfiguration, monarchlanguage } from './monacoConfig'
import { parser, formatLokiQuery } from './lezerConfig'
import { getSituation } from './situation'
export default {
data () {
return {
code: '',
LANGUAGE_SETUP_STARTED: false,
parser,
MONACO_EDITOR_OPTIONS: {
automaticLayout: true,
formatOnType: true,
formatOnPaste: true,
codeLens: false,
contextmenu: false,
// we need `fixedOverflowWidgets` because otherwise in grafana-dashboards
// the popup is clipped by the panel-visualizations.
fixedOverflowWidgets: true,
folding: false,
fontSize: 14,
lineDecorationsWidth: 8, // used as "padding-left"
lineNumbers: 'off',
minimap: { enabled: false },
overviewRulerBorder: false,
overviewRulerLanes: 0,
padding: {
// these numbers were picked so that visually this matches the previous version
// of the query-editor the best
top: 10,
bottom: 5
},
renderLineHighlight: 'none',
scrollbar: {
// vertical: 'hidden',
verticalScrollbarSize: 8, // used as "padding-right"
horizontal: 'hidden',
horizontalScrollbarSize: 0
},
scrollBeyondLastLine: false,
suggest: {
showWords: true,
/**
* Enable custom contextmenu.
* Defaults to false.
*/
contextmenu: true,
/**
* The number of spaces a tab is equal to.
* This setting is overridden based on the file contents when `detectIndentation` is on.
* Defaults to 4.
*/
tabSize: 4,
/**
* Show code lens
* Defaults to false.
*/
codeLens: true,
/**
* Control the width of line numbers, by reserving horizontal space for rendering at least an amount of digits.
* Defaults to 4.
*/
lineNumbersMinChars: 4,
/**
* The width reserved for line decorations (in px).
* Line decorations are placed between line numbers and the editor content.
* You can pass in a string in the format floating point followed by "ch". e.g. 1.3ch.
* Defaults to 1 * theme.spacing.gridSize.
*/
// lineDecorationsWidth?: number | string;
/**
* Controls if a border should be drawn around the overview ruler.
* Defaults to `false`.
*/
overviewRulerBorder: false,
/**
* Enable that the editor will install an interval to check if its container dom node size has changed.
* Enabling this might have a severe performance impact.
* Defaults to true.
*/
automaticLayout: true
},
suggestFontSize: 12,
wordWrap: 'on',
placeHolderScopedVars: {
__interval: { text: '1s', value: '1s' },
__auto: { text: '1s', value: '1s' },
__interval_ms: { text: '1000', value: 1000 },
__range_ms: { text: '1000', value: 1000 },
__range_s: { text: '1', value: 1 },
__range: { text: '1s', value: '1s' }
},
},
monacoEditorHeight: 30,
templateSrv: ''
}
},
methods: {
handleChange (value, event) {
this.heightChange()
},
heightChange () {
const dom = this.$refs.monacoEditor.$el
const el = dom.getElementsByClassName('view-line')
const height = 11 + el.length * 19
if (this.monacoEditorHeight !== height) {
this.monacoEditorHeight = height
}
},
handleMount (editor) {
// const dom = this.$refs.monacoEditor.$el
// const el = dom.getElementsByClassName('view-lines')
// if (el && el[0]) {
// el[0].addEventListener('DOMNodeInserted', this.heightChange)
// }
},
handelBeforeMount (monaco) {
const LANG_ID = 'logql'
const self = this
if (!window.LANGUAGE_SETUP_STARTED) {
window.LANGUAGE_SETUP_STARTED = true
// console.log(monaco)
monaco.languages.register({ id: LANG_ID })
monaco.languages.setLanguageConfiguration(LANG_ID, languageConfiguration)
monaco.languages.setMonarchTokensProvider(LANG_ID, monarchlanguage)
monaco.editor.defineTheme('nz', {
base: 'vs',
inherit: true,
colors: {
'editor.background': '#ffffff',
'minimap.background': '#f9f9f9'
},
// fallback syntax highlighting for languages that microsoft doesn't handle (ex cloudwatch's metric math)
rules: [
{ token: 'predefined', foreground: '#FF6600' },
{ token: 'operator', foreground: '#009966' },
{ token: 'tag', foreground: '#006699' }
]
})
monaco.languages.registerCompletionItemProvider('logql', {
provideCompletionItems: (model, position) => {
const suggestions = [
...monarchlanguage.keywords.map(k => {
// console.log(k)
return {
label: k,
kind: monaco.languages.CompletionItemKind.Keyword,
insertText: k
}
})
]
return { suggestions: suggestions }
}
})
}
},
nzSuggest (model, position) {
// console.log(model, position)
const suggestions = []
// console.log(parser.parse(this.code))
return suggestions
},
suggest (model, position) {
const monaco = this.$refs.monacoEditor.monaco
const self = this
const word = model.getWordAtPosition(position)
const INSERT_AS_SNIPPET_ENUM_VALUE = 4
console.log(monaco.Range.fromPositions(position))
const range = monaco.Range.fromPositions(position)
// documentation says `position` will be "adjusted" in `getOffsetAt`
// i don't know what that means, to be sure i clone it
const positionClone = {
column: position.column,
lineNumber: position.lineNumber
}
const offset = model.getOffsetAt(positionClone)
console.log(offset)
const situation = getSituation(model.getValue(), offset)
console.log(situation)
const completionsPromise = situation != null ? Promise.resolve([]) : Promise.resolve([])
return completionsPromise.then((items) => {
// monaco by default alphabetically orders the items.
// to stop it, we use a number-as-string sortkey,
// so that monaco keeps the order we use
const maxIndexDigits = items.length.toString().length
const suggestions = items.map((item, index) => ({
kind: self.getMonacoCompletionItemKind(item.type, monaco),
label: item.label,
insertText: item.insertText,
insertTextRules: item.isSnippet ? INSERT_AS_SNIPPET_ENUM_VALUE : undefined,
detail: item.detail,
documentation: item.documentation,
sortText: index.toString().padStart(maxIndexDigits, '0'), // to force the order we have
range,
command: item.triggerOnInsert
? {
id: 'editor.action.triggerSuggest',
title: ''
}
: undefined
}))
return { suggestions }
})
},
getMonacoCompletionItemKind (type, monaco) {
switch (type) {
case 'DURATION':
return monaco.languages.CompletionItemKind.Unit
case 'FUNCTION':
return monaco.languages.CompletionItemKind.Variable
case 'HISTORY':
return monaco.languages.CompletionItemKind.Snippet
case 'LABEL_NAME':
return monaco.languages.CompletionItemKind.Enum
case 'LABEL_VALUE':
return monaco.languages.CompletionItemKind.EnumMember
case 'PATTERN':
return monaco.languages.CompletionItemKind.Constructor
case 'PARSER':
return monaco.languages.CompletionItemKind.Class
case 'LINE_FILTER':
return monaco.languages.CompletionItemKind.TypeParameter
case 'PIPE_OPERATION':
return monaco.languages.CompletionItemKind.Interface
default:
return `Unexpected case in switch statement: ${JSON.stringify(type)}`
}
},
interpolateString (string, scopedVars) {
return this.interpolate(string, scopedVars, this.interpolateQueryExpr)
},
interpolateQueryExpr (value, variable) {
// if no multi or include all do not regexEscape
if (!variable.multi && !variable.includeAll) {
return this.lokiRegularEscape(value)
}
if (typeof value === 'string') {
return this.lokiSpecialRegexEscape(value)
}
const escapedValues = this.$lodash.map(value, this.lokiSpecialRegexEscape)
return escapedValues.join('|')
},
lokiRegularEscape (value) {
if (typeof value === 'string') {
return value.replace(/'/g, "\\\\'")
}
return value
},
lokiSpecialRegexEscape (value) {
if (typeof value === 'string') {
return this.lokiRegularEscape(value.replace(/\\/g, '\\\\\\\\').replace(/[$^*{}\[\]+?.()|]/g, '\\\\$&'))
}
return value
},
setPlaceholder (monaco, editor) {
const placeholderDecorators = [
{
range: new monaco.Range(1, 1, 1, 1),
options: {
className: 'nz-eqweqwe',
isWholeLine: true
}
}
]
let decorators = []
const checkDecorators = () => {
const model = editor.getModel()
if (!model) {
return
}
const newDecorators = model.getValueLength() === 0 ? placeholderDecorators : []
decorators = model.deltaDecorations(decorators, newDecorators)
}
checkDecorators()
editor.onDidChangeModelContent(checkDecorators)
},
interpolate (target, scopedVars, format, interpolations) {
if (scopedVars && scopedVars.__sceneObject) {
return sceneGraph.interpolate(
scopedVars.__sceneObject.value,
target,
scopedVars,
format
)
}
if (!target) {
return target || ''
}
this.regex.lastIndex = 0
return this._replaceWithVariableRegex(target, format, (match, variableName, fieldPath, fmt) => {
const value = this._evaluateVariableExpression(match, variableName, fieldPath, fmt, scopedVars)
// If we get passed this interpolations map we will also record all the expressions that were replaced
if (interpolations) {
interpolations.push({ match, variableName, fieldPath, format: fmt, value, found: value !== match })
}
return value
})
},
sceneInterpolator (sceneObject, target, scopedVars, format) {
const VARIABLE_REGEX = /\$(\w+)|\[\[(\w+?)(?::(\w+))?\]\]|\${(\w+)(?:\.([^:^\}]+))?(?::([^\}]+))?}/g
if (!target) {
return target != null ? target : ''
}
VARIABLE_REGEX.lastIndex = 0
return target.replace(VARIABLE_REGEX, (match, var1, var2, fmt2, var3, fieldPath, fmt3) => {
const variableName = var1 || var2 || var3
const fmt = fmt2 || fmt3 || format
const variable = this.lookupFormatVariable(variableName, match, scopedVars, sceneObject)
if (!variable) {
return match
}
return this.formatValue(variable, variable.getValue(fieldPath), fmt)
})
},
formatValue (variable, value, formatNameOrFn) {
if (value === null || value === 0) {
return ''
} else {
return value
}
},
lookupFormatVariable (name, match, scopedVars, sceneObject) {
console.log(name, match, scopedVars, sceneObject)
return null
}
},
beforeDestroy () {
}
}

View File

@@ -0,0 +1,198 @@
'use strict'
Object.defineProperty(exports, '__esModule', { value: true })
exports.monarchlanguage = exports.languageConfiguration = 0
exports.languageConfiguration = {
// the default separators except `@$`
wordPattern: /(-?\d*\.\d\w*)|([^`~!#%^&*()\-=+\[{\]}\\|;:'",.<>\/?\s]+)/g,
comments: {
lineComment: '#'
},
brackets: [
['{', '}'],
['[', ']'],
['(', ')']
],
autoClosingPairs: [
{ open: '{', close: '}' },
{ open: '[', close: ']' },
{ open: '(', close: ')' },
{ open: '"', close: '"' },
{ open: "'", close: "'" },
{ open: '`', close: '`' }
],
surroundingPairs: [
{ open: '{', close: '}' },
{ open: '[', close: ']' },
{ open: '(', close: ')' },
{ open: '"', close: '"' },
{ open: "'", close: "'" },
{ open: '`', close: '`' },
{ open: '<', close: '>' }
],
folding: {}
}
// LogQL built-in aggregation operators
// https://grafana.com/docs/loki/latest/logql/metric_queries/#built-in-aggregation-operators
const aggregations = [
'sum',
'avg',
'min',
'max',
'stddev',
'stdvar',
'count',
'topk',
'bottomk'
]
// LogQL parser expressions
// https://grafana.com/docs/loki/latest/logql/log_queries/#parser-expression
const parsers = ['json', 'logfmt', 'regexp', 'unpack', 'pattern']
// LogQL format expressions
// https://grafana.com/docs/loki/latest/logql/log_queries/#parser-expression
// eslint-disable-next-line camelcase
const format_expressions = ['line_format', 'label_format']
// LogQL vector aggregations
// https://grafana.com/docs/loki/latest/logql/metric_queries/#range-vector-aggregation
// eslint-disable-next-line camelcase
const vector_aggregations = [
'count_over_time',
'rate',
'bytes_over_time',
'bytes_rate',
'avg_over_time',
'sum_over_time',
'min_over_time',
'max_over_time',
'stdvar_over_time',
'stddev_over_time',
'quantile_over_time',
'first_over_time',
'last_over_time',
'absent_over_time'
]
// LogQL by and without clauses
// eslint-disable-next-line camelcase
const vector_matching = ['by', 'without']
// Produce a regex matching elements : (by|without)
const vectorMatchingRegex = '('.concat(vector_matching.reduce(function (prev, curr) { return ''.concat(prev, '|').concat(curr) }), ')')
// LogQL Operators
const operators = [
'+',
'-',
'*',
'/',
'%',
'^',
'==',
'!=',
'>',
'<',
'>=',
'<=',
'|=',
'!=',
'|~',
'!~',
'and',
'or',
'unless',
'|'
]
// Merging all the keywords in one list
const keywords = aggregations
.concat(parsers)
.concat(format_expressions)
.concat(vector_aggregations)
.concat(vector_matching)
exports.monarchlanguage = {
ignoreCase: false,
defaultToken: '',
tokenPostfix: '.logql',
keywords: keywords,
operators: operators,
vectorMatching: vectorMatchingRegex,
// we include these common regular expressions
symbols: /[=><!~?:&|+\-*\/^%]+/,
escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
digits: /\d+(_+\d+)*/,
octaldigits: /[0-7]+(_+[0-7]+)*/,
binarydigits: /[0-1]+(_+[0-1]+)*/,
hexdigits: /[[0-9a-fA-F]+(_+[0-9a-fA-F]+)*/,
integersuffix: /(ll|LL|u|U|l|L)?(ll|LL|u|U|l|L)?/,
floatsuffix: /[fFlL]?/,
// The main tokenizer for our languages
tokenizer: {
root: [
// 'by', 'without' and vector matching
[/@vectorMatching\s*(?=\()/, 'type', '@clauses'],
// labels
[/[a-z_]\w*(?=\s*(=|!=|=~|!~))/, 'tag'],
// comments
[/(^#.*$)/, 'comment'],
// all keywords have the same color
[
/[a-zA-Z_]\w*/,
{
cases: {
'@keywords': 'type',
'@default': 'identifier'
}
}
],
// strings
[/"/, 'string', '@string_double'],
[/'/, 'string', '@string_single'],
[/`/, 'string', '@string_backtick'],
// whitespace
{ include: '@whitespace' },
// delimiters and operators
[/[{}()\[\]]/, '@brackets'],
[/[<>](?!@symbols)/, '@brackets'],
[
/@symbols/,
{
cases: {
'@operators': 'delimiter',
'@default': ''
}
}
],
// numbers
[/\d+(?:ms|[smhdwy])/, 'number'],
[/\d*\d+[eE]([\-+]?\d+)?(@floatsuffix)/, 'number.float'],
[/\d*\.\d+([eE][\-+]?\d+)?(@floatsuffix)/, 'number.float'],
[/0[xX][0-9a-fA-F']*[0-9a-fA-F](@integersuffix)/, 'number.hex'],
[/0[0-7']*[0-7](@integersuffix)/, 'number.octal'],
[/0[bB][0-1']*[0-1](@integersuffix)/, 'number.binary'],
[/\d[\d']*\d(@integersuffix)/, 'number'],
[/\d(@integersuffix)/, 'number']
],
string_double: [
// Set to token: number to differentiate color
[/\{\{(.*?)\}\}/, { token: 'number' }],
[/[^\\"]/, 'string'],
[/@escapes/, 'string.escape'],
[/\\./, 'string.escape.invalid'],
[/"/, 'string', '@pop']
],
string_single: [
[/[^\\']+/, 'string'],
[/@escapes/, 'string.escape'],
[/\\./, 'string.escape.invalid'],
[/'/, 'string', '@pop']
],
string_backtick: [
// Set to token: number to differentiate color
[/\{\{(.*?)\}\}/, { token: 'number' }],
[/[^\\`]/, 'string'],
[/@escapes/, 'string.escape'],
[/\\./, 'string.escape.invalid'],
[/`/, 'string', '@pop']
],
clauses: [
[/[^(,)]/, 'tag'],
[/\)/, 'identifier', '@pop']
],
whitespace: [[/[ \t\r\n]+/, 'white']]
}
}

View File

@@ -0,0 +1,165 @@
import lodash from 'lodash'
const VARIABLE_REGEX = /\$(\w+)|\[\[(\w+?)(?::(\w+))?\]\]|\${(\w+)(?:\.([^:^\}]+))?(?::([^\}]+))?}/g
class ScopedVarsVariable {
constructor (name, value) {
this.state = { name, value, type: 'scopedvar' }
}
getValue (fieldPath) {
const { value } = this.state
let realValue = value.value
if (fieldPath) {
realValue = getFieldAccessor(fieldPath)(value.value)
} else {
realValue = value.value
}
if (realValue === 'string' || realValue === 'number' || realValue === 'boolean') {
return realValue
}
return String(realValue)
}
getValueText () {
const { value } = this.state
if (value.text != null) {
return String(value.text)
}
return String(value)
}
}
export const DataLinkBuiltInVars = {
keepTime: '__url_time_range',
timeRangeFrom: '__from',
timeRangeTo: '__to',
includeVars: '__all_variables',
seriesName: '__series.name',
fieldName: '__field.name',
valueTime: '__value.time',
valueNumeric: '__value.numeric',
valueText: '__value.text',
valueRaw: '__value.raw',
// name of the calculation represented by the value
valueCalc: '__value.calc'
}
class AllVariablesMacro {
constructor (name, sceneObject) {
this.state = { name, type: 'url_variable' }
this._sceneObject = sceneObject
}
getValue () {
const allVars = collectAllVariables(this._sceneObject)
const format = formatRegistry.get(schema.VariableFormatID.QueryParam)
const params = []
for (const name of Object.keys(allVars)) {
const variable = allVars[name]
const value = variable.getValue()
if (!value) {
continue
}
if (isCustomVariableValue(value)) {
params.push(value.formatter(schema.VariableFormatID.QueryParam))
} else {
params.push(format.formatter(value, [], variable))
}
}
return new SkipFormattingValue(params.join('&'))
}
getValueText () {
return ''
}
}
const macrosIndex = {
__all_variables: AllVariablesMacro,
__url_time_range: UrlTimeRangeMacro,
__value: ValueMacro,
__data: DataMacro,
__series: SeriesMacro,
__field: FieldMacro,
__url: UrlMacro,
__from: TimeFromAndToMacro,
__to: TimeFromAndToMacro,
__timezone: TimezoneMacro
}
const sceneGraph = {
// getVariables,
// getData,
// getTimeRange,
// getLayout,
interpolate
// lookupVariable,
// hasVariableDependencyInLoadingState,
// findObject
}
function interpolate (sceneObject, value, scopedVars, format) {
if (value === '' || value == null) {
return ''
}
return sceneInterpolator(sceneObject, value, scopedVars, format)
}
function sceneInterpolator (sceneObject, target, scopedVars, format) {
if (!target) {
return target != null ? target : ''
}
VARIABLE_REGEX.lastIndex = 0
return target.replace(VARIABLE_REGEX, (match, var1, var2, fmt2, var3, fieldPath, fmt3) => {
const variableName = var1 || var2 || var3
const fmt = fmt2 || fmt3 || format
const variable = lookupFormatVariable(variableName, match, scopedVars, sceneObject)
if (!variable) {
return match
}
return formatValue(variable, variable.getValue(fieldPath), fmt)
})
}
function lookupFormatVariable (name, match, scopedVars, sceneObject) {
const scopedVar = scopedVars == null ? 0 : scopedVars[name]
if (scopedVar) {
return getSceneVariableForScopedVar(name, scopedVar)
}
const variable = lookupVariable(name, sceneObject)
if (variable) {
return variable
}
if (macrosIndex[name]) {
return new macrosIndex[name](name, sceneObject, match, scopedVars)
}
return null
}
let scopedVarsVariable
function getSceneVariableForScopedVar (name, value) {
if (!scopedVarsVariable) {
scopedVarsVariable = new ScopedVarsVariable(name, value)
} else {
scopedVarsVariable.state.name = name
scopedVarsVariable.state.value = value
}
return scopedVarsVariable
}
const fieldAccessorCache = {}
function getFieldAccessor (fieldPath) {
const accessor = fieldAccessorCache[fieldPath]
if (accessor) {
return accessor
}
return (fieldAccessorCache[fieldPath] = lodash.property(fieldPath))
}
function lookupVariable (name, sceneObject) {
const variables = sceneObject.state.$variables
if (!variables) {
if (sceneObject.parent) {
return lookupVariable(name, sceneObject.parent)
} else {
return null
}
}
const found = variables.getByName(name)
if (found) {
return found
} else if (sceneObject.parent) {
return lookupVariable(name, sceneObject.parent)
}
return null
}
export default sceneGraph

View File

@@ -0,0 +1,559 @@
import {
parser,
VectorAggregationExpr,
String,
Selector,
RangeAggregationExpr,
Range,
PipelineExpr,
PipelineStage,
Matchers,
Matcher,
LogQL,
LogRangeExpr,
LogExpr,
Identifier,
Grouping,
Expr,
LiteralExpr,
MetricExpr,
UnwrapExpr,
DropLabelsExpr,
KeepLabelsExpr,
DropLabels,
KeepLabels
} from './lezerConfig'
function getLogQueryFromMetricsQuery (text) {
return text
}
function move (node, direction) {
return node[direction]
}
function walk (node, path) {
let current = node
for (const [direction, expectedNode] of path) {
current = move(current, direction)
if (current === null) {
// we could not move in the direction, we stop
return null
}
if (current.type.id !== expectedNode) {
// the reached node has wrong type, we stop
return null
}
}
return current
}
function getNodeText (node, text) {
return text.slice(node.from, node.to)
}
function parseStringLiteral (text) {
// If it is a string-literal, it is inside quotes of some kind
const inside = text.slice(1, text.length - 1)
// Very simple un-escaping:
// Double quotes
if (text.startsWith('"') && text.endsWith('"')) {
// NOTE: this is not 100% perfect, we only unescape the double-quote,
// there might be other characters too
return inside.replace(/\\"/gm, '"')
}
// Single quotes
if (text.startsWith("'") && text.endsWith("'")) {
// NOTE: this is not 100% perfect, we only unescape the single-quote,
// there might be other characters too
return inside.replace(/\\'/gm, "'")
}
// Backticks
if (text.startsWith('`') && text.endsWith('`')) {
return inside
}
throw new Error(`Invalid string literal: ${text}`)
}
export const LabelOperator = '=' | '!=' | '=~' | '!~'
export const Label = {}
export const Situation = {}
const Resolver = {
path: [],
fun: (node, text, pos) => Situation
}
function isPathMatch (resolverPath, cursorPath) {
return resolverPath.every((item, index) => item === cursorPath[index])
}
const ERROR_NODE_ID = 0
const RESOLVERS = [
{
path: [Selector],
fun: resolveSelector
},
{
path: [ERROR_NODE_ID, Matchers, Selector],
fun: resolveSelector
},
{
path: [LogQL],
fun: resolveTopLevel
},
{
path: [String, Matcher],
fun: resolveMatcher
},
{
path: [Grouping],
fun: resolveLabelsForGrouping
},
{
path: [LogRangeExpr],
fun: resolveLogRange
},
{
path: [ERROR_NODE_ID, Matcher],
fun: resolveMatcher
},
{
path: [ERROR_NODE_ID, Range],
fun: resolveDurations
},
{
path: [ERROR_NODE_ID, LogRangeExpr],
fun: resolveLogRangeFromError
},
{
path: [ERROR_NODE_ID, LiteralExpr, MetricExpr, VectorAggregationExpr],
fun: () => ({ type: 'IN_AGGREGATION' })
},
{
path: [ERROR_NODE_ID, PipelineStage, PipelineExpr],
fun: resolvePipeError
},
{
path: [ERROR_NODE_ID, UnwrapExpr],
fun: resolveAfterUnwrap
},
{
path: [UnwrapExpr],
fun: resolveAfterUnwrap
},
{
path: [ERROR_NODE_ID, DropLabelsExpr],
fun: resolveAfterKeepAndDrop
},
{
path: [ERROR_NODE_ID, DropLabels],
fun: resolveAfterKeepAndDrop
},
{
path: [ERROR_NODE_ID, KeepLabelsExpr],
fun: resolveAfterKeepAndDrop
},
{
path: [ERROR_NODE_ID, KeepLabels],
fun: resolveAfterKeepAndDrop
}
]
const LABEL_OP_MAP = new Map([
['Eq', '='],
['Re', '=~'],
['Neq', '!='],
['Nre', '!~']
])
function getLabelOp (opNode) {
return LABEL_OP_MAP.get(opNode.name) || null
}
function getLabel (matcherNode, text) {
if (matcherNode.type.id !== Matcher) {
return null
}
const nameNode = walk(matcherNode, [['firstChild', Identifier]])
if (nameNode === null) {
return null
}
const opNode = nameNode.nextSibling
if (opNode === null) {
return null
}
const op = getLabelOp(opNode)
if (op === null) {
return null
}
const valueNode = walk(matcherNode, [['lastChild', String]])
if (valueNode === null) {
return null
}
const name = getNodeText(nameNode, text)
const value = parseStringLiteral(getNodeText(valueNode, text))
return { name, value, op }
}
function getLabels (selectorNode, text) {
if (selectorNode.type.id !== Selector) {
return []
}
let listNode = walk(selectorNode, [['firstChild', Matchers]])
const labels = []
while (listNode !== null) {
const matcherNode = walk(listNode, [['lastChild', Matcher]])
if (matcherNode !== null) {
const label = getLabel(matcherNode, text)
if (label !== null) {
labels.push(label)
}
}
// there might be more labels
listNode = walk(listNode, [['firstChild', Matchers]])
}
// our labels-list is last-first, so we reverse it
labels.reverse()
return labels
}
function resolveAfterUnwrap (node, text, pos) {
return {
type: 'AFTER_UNWRAP',
logQuery: getLogQueryFromMetricsQuery(text).trim()
}
}
function resolvePipeError (node, text, pos) {
// for example `{level="info"} |`
const exprNode = walk(node, [
['parent', PipelineStage],
['parent', PipelineExpr]
])
if (exprNode === null) {
return null
}
const { parent } = exprNode
if (parent === null) {
return null
}
if (parent.type.id === LogExpr || parent.type.id === LogRangeExpr) {
return resolveLogOrLogRange(parent, text, pos, true)
}
return null
}
function resolveLabelsForGrouping (node, text, pos) {
const aggrExpNode = walk(node, [['parent', VectorAggregationExpr]])
if (aggrExpNode === null) {
return null
}
const bodyNode = aggrExpNode.getChild('MetricExpr')
if (bodyNode === null) {
return null
}
const selectorNode = walk(bodyNode, [
['firstChild', RangeAggregationExpr],
['lastChild', LogRangeExpr],
['firstChild', Selector]
])
if (selectorNode === null) {
return null
}
return {
type: 'IN_GROUPING',
logQuery: getLogQueryFromMetricsQuery(text).trim()
}
}
function resolveMatcher (node, text, pos) {
// we can arrive here for two reasons. `node` is either:
// - a StringNode (like in `{job="^"}`)
// - or an error node (like in `{job=^}`)
const inStringNode = !node.type.isError
const parent = walk(node, [['parent', Matcher]])
if (parent === null) {
return null
}
const labelNameNode = walk(parent, [['firstChild', Identifier]])
if (labelNameNode === null) {
return null
}
const labelName = getNodeText(labelNameNode, text)
// now we need to go up, to the parent of Matcher,
// there can be one or many `Matchers` parents, we have
// to go through all of them
const firstListNode = walk(parent, [['parent', Matchers]])
if (firstListNode === null) {
return null
}
let listNode = firstListNode
// we keep going through the parent-nodes as long as they are Matchers.
// as soon as we reach Selector, we stop
let selectorNode = null
while (selectorNode === null) {
const parent = listNode.parent
if (parent === null) {
return null
}
switch (parent.type.id) {
case Matchers:
// we keep looping
listNode = parent
continue
case Selector:
// we reached the end, we can stop the loop
selectorNode = parent
continue
default:
// we reached some other node, we stop
return null
}
}
// now we need to find the other names
const allLabels = getLabels(selectorNode, text)
// we need to remove "our" label from all-labels, if it is in there
const otherLabels = allLabels.filter((label) => label.name !== labelName)
return {
type: 'IN_LABEL_SELECTOR_WITH_LABEL_NAME',
labelName,
betweenQuotes: inStringNode,
otherLabels
}
}
function resolveTopLevel (node, text, pos) {
// we try a couply specific paths here.
// `{x="y"}` situation, with the cursor at the end
const logExprNode = walk(node, [
['lastChild', Expr],
['lastChild', LogExpr]
])
if (logExprNode != null) {
return resolveLogOrLogRange(logExprNode, text, pos, false)
}
// `s` situation, with the cursor at the end.
// (basically, user enters a non-special characters as first
// character in query field)
const idNode = walk(node, [
['firstChild', ERROR_NODE_ID],
['firstChild', Identifier]
])
if (idNode != null) {
return {
type: 'AT_ROOT'
}
}
// no patterns match
return null
}
function resolveDurations (node, text, pos) {
return {
type: 'IN_RANGE'
}
}
function resolveLogRange (node, text, pos) {
return resolveLogOrLogRange(node, text, pos, false)
}
function resolveLogRangeFromError (node, text, pos) {
const parent = walk(node, [['parent', LogRangeExpr]])
if (parent === null) {
return null
}
return resolveLogOrLogRange(parent, text, pos, false)
}
function resolveLogOrLogRange (node, text, pos, afterPipe) {
// Here the `node` is either a LogExpr or a LogRangeExpr
// We want to handle the case where we are next to a selector
const selectorNode = walk(node, [['firstChild', Selector]])
// Check that the selector is before the cursor, not after it
if (!selectorNode || selectorNode.to > pos) {
return null
}
return {
type: 'AFTER_SELECTOR',
afterPipe,
hasSpace: text.endsWith(' '),
logQuery: getLogQueryFromMetricsQuery(text).trim()
}
}
function resolveSelector (node, text, pos) {
// for example `{^}`
// false positive:
// `{a="1"^}`
const child = walk(node, [['firstChild', Matchers]])
if (child !== null) {
// means the label-matching part contains at least one label already.
//
// in this case, we will need to have a `,` character at the end,
// to be able to suggest adding the next label.
// the area between the end-of-the-child-node and the cursor-pos
// must contain a `,` in this case.
const textToCheck = text.slice(child.from, pos)
if (!textToCheck.trim().endsWith(',')) {
return null
}
}
const selectorNode =
node.type.id === ERROR_NODE_ID
? walk(node, [
['parent', Matchers],
['parent', Selector]
])
: node
if (!selectorNode) {
return null
}
const otherLabels = getLabels(selectorNode, text)
return {
type: 'IN_LABEL_SELECTOR_NO_LABEL_NAME',
otherLabels
}
}
function resolveAfterKeepAndDrop (node, text, pos) {
let logQuery = getLogQueryFromMetricsQuery(text).trim()
let keepAndDropParent = null
let parent = node.parent
while (parent !== null) {
if (parent.type.id === PipelineStage) {
keepAndDropParent = parent
break
}
parent = parent.parent
}
if (keepAndDropParent.type && (keepAndDropParent.type.id === PipelineStage)) {
logQuery = logQuery.slice(0, keepAndDropParent.from)
}
return {
type: 'AFTER_KEEP_AND_DROP',
logQuery
}
}
// we find the first error-node in the tree that is at the cursor-position.
// NOTE: this might be too slow, might need to optimize it
// (ideas: we do not need to go into every subtree, based on from/to)
// also, only go to places that are in the sub-tree of the node found
// by default by lezer. problem is, `next()` will go upward too,
// and we do not want to go higher than our node
function getErrorNode (tree, text, cursorPos) {
// sometimes the cursor is a couple spaces after the end of the expression.
// to account for this situation, we "move" the cursor position back,
// so that there are no spaces between the end-of-expression and the cursor
const trimRightTextLen = text.trimEnd().length
console.log(trimRightTextLen)
const pos = trimRightTextLen < cursorPos ? trimRightTextLen : cursorPos
console.log(pos)
const cur = tree.cursorAt(pos)
console.log(cur)
do {
if (cur.from === pos && cur.to === pos) {
const { node } = cur
console.log(node)
console.log(node.type.isError)
if (node.type.isError) {
return node
}
}
} while (cur.next())
return null
}
export function getSituation (text, pos) {
// there is a special case when we are at the start of writing text,
// so we handle that case first
if (text === '') {
return {
type: 'EMPTY'
}
}
const tree = parser.parse(text)
console.log(tree)
// if the tree contains error, it is very probable that
// our node is one of those error nodes.
// also, if there are errors, the node lezer finds us,
// might not be the best node.
// so first we check if there is an error node at the cursor position
const maybeErrorNode = getErrorNode(tree, text, pos)
console.log(maybeErrorNode)
const cur = maybeErrorNode.cursor().cursorAt(pos)
const currentNode = cur.node
const ids = [cur.type.id]
while (cur.parent()) {
ids.push(cur.type.id)
}
for (const resolver of RESOLVERS) {
if (isPathMatch(resolver.path, ids)) {
return resolver.fun(currentNode, text, pos)
}
}
return null
}

View File

@@ -0,0 +1,125 @@
package logql
import (
"syscall/js"
"errors"
"fmt"
"strconv"
"strings"
"text/scanner"
"github.com/prometheus/prometheus/model/labels"
)
func init() {
// Improve the error messages coming out of yacc.
exprErrorVerbose = true
for str, tok := range tokens {
exprToknames[tok-exprPrivate+1] = str
}
c := make(chan struct{}, 0)
// 注册函数
js.Global().Set("parsePromQL", js.FuncOf(parsePromQL))
<-c
}
// ParseExpr parses a string and returns an Expr.
func ParseExpr(input string) (Expr, error) {
l := lexer{
parser: exprNewParser().(*exprParserImpl),
}
l.Init(strings.NewReader(input))
l.Scanner.Error = func(_ *scanner.Scanner, msg string) {
l.Error(msg)
}
e := l.parser.Parse(&l)
if e != 0 || len(l.errs) > 0 {
return nil, l.errs[0]
}
return l.expr, nil
}
// ParseMatchers parses a string and returns labels matchers, if the expression contains
// anything else it will return an error.
func ParseMatchers(input string) ([]*labels.Matcher, error) {
expr, err := ParseExpr(input)
if err != nil {
return nil, err
}
matcherExpr, ok := expr.(*matchersExpr)
if !ok {
return nil, errors.New("only label matchers is supported")
}
return matcherExpr.matchers, nil
}
var tokens = map[string]int{
",": COMMA,
".": DOT,
"{": OPEN_BRACE,
"}": CLOSE_BRACE,
"=": EQ,
"!=": NEQ,
"=~": RE,
"!~": NRE,
"|=": PIPE_EXACT,
"|~": PIPE_MATCH,
}
type lexer struct {
scanner.Scanner
errs []ParseError
expr Expr
parser *exprParserImpl
}
func (l *lexer) Lex(lval *exprSymType) int {
r := l.Scan()
switch r {
case scanner.EOF:
return 0
case scanner.String:
var err error
lval.str, err = strconv.Unquote(l.TokenText())
if err != nil {
l.Error(err.Error())
return 0
}
return STRING
}
if tok, ok := tokens[l.TokenText()+string(l.Peek())]; ok {
l.Next()
return tok
}
if tok, ok := tokens[l.TokenText()]; ok {
return tok
}
lval.str = l.TokenText()
return IDENTIFIER
}
func (l *lexer) Error(msg string) {
l.errs = append(l.errs, ParseError{
msg: msg,
line: l.Line,
col: l.Column,
})
}
// ParseError is what is returned when we failed to parse.
type ParseError struct {
msg string
line, col int
}
func (p ParseError) Error() string {
return fmt.Sprintf("parse error at line %d, col %d: %s", p.line, p.col, p.msg)
}

View File

@@ -86,20 +86,38 @@
class="not-fixed-height no-resize no-close"
>
</div> -->
<el-input
v-if="type == 'log'"
:id="inputId"
v-model="expressionList[index]"
size="small" :rows="1"
autosize
class="not-fixed-height no-resize"
type="textarea"
show-word-limit maxlength="256"
@input="metricKeyDown"
@keyup.enter.native="expressionChange"
ref="elInput"
>
</el-input>
<!-- <el-input-->
<!-- v-if="type == 'log'"-->
<!-- :id="inputId"-->
<!-- v-model="expressionList[index]"-->
<!-- size="small" :rows="1"-->
<!-- autosize-->
<!-- class="not-fixed-height no-resize"-->
<!-- type="textarea"-->
<!-- show-word-limit maxlength="256"-->
<!-- @input="metricKeyDown"-->
<!-- @keyup.enter.native="expressionChange"-->
<!-- ref="elInput"-->
<!-- >-->
<!-- </el-input>-->
<div>
<MonacoEditor
v-if="type == 'log'"
v-model="expressionList[index]"
theme="nz"
class="not-fixed-height no-resize"
ref="monacoEditor"
style="border: 1px solid #dedede;"
:style="{
height: monacoEditorHeight + 'px'
}"
language="logql"
:options="MONACO_EDITOR_OPTIONS"
@editorWillMount="handelBeforeMount"
@editorDidMount="handleMount"
@change="expressionChange"
/>
</div>
<div v-if="errorMsg" class="append-msg error" style="position: absolute">
<span>{{ errorMsg }}</span>
@@ -459,11 +477,15 @@ import {
closeBracketsKeymap
} from '@codemirror/autocomplete'
import exploreHistory from '@/components/page/dashboard/explore/histoyrComponent/exploreHistory'
import MonacoEditor from 'vue-monaco'
import logqlMixin from '@/components/page/dashboard/explore/logql/logqlMixin'
export default {
name: 'promqlInput',
mixins: [logqlMixin],
components: {
selectAlertSilence,
exploreHistory
exploreHistory,
MonacoEditor
},
props: {
index: { type: Number },
@@ -884,6 +906,11 @@ export default {
}
},
expressionChange: function () {
if (this.$refs.monacoEditor) {
setTimeout(() => {
this.heightChange()
}, 100)
}
this.$emit('change')
},
setError: function (errMsg) {