Compare commits
8 Commits
serge/disp
...
ifrost/tra
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c558072c0c | ||
|
|
2ce89f099f | ||
|
|
48625d67e5 | ||
|
|
8bad33de4c | ||
|
|
040854c8af | ||
|
|
829022d488 | ||
|
|
987c1fc6b6 | ||
|
|
170ac31c5a |
1
.github/CODEOWNERS
vendored
1
.github/CODEOWNERS
vendored
@@ -543,6 +543,7 @@ i18next.config.ts @grafana/grafana-frontend-platform
|
||||
/packages/grafana-data/tsconfig.json @grafana/grafana-frontend-platform
|
||||
/packages/grafana-data/test/ @grafana/grafana-frontend-platform
|
||||
/packages/grafana-data/typings/ @grafana/grafana-frontend-platform
|
||||
/packages/grafana-data/scripts/ @grafana/grafana-frontend-platform
|
||||
|
||||
/packages/grafana-data/src/**/*logs* @grafana/observability-logs
|
||||
/packages/grafana-data/src/context/plugins/ @grafana/plugins-platform-frontend
|
||||
|
||||
23
go.mod
23
go.mod
@@ -44,8 +44,8 @@ require (
|
||||
github.com/beevik/etree v1.4.1 // @grafana/grafana-backend-group
|
||||
github.com/benbjohnson/clock v1.3.5 // @grafana/alerting-backend
|
||||
github.com/blang/semver/v4 v4.0.0 // indirect; @grafana/grafana-developer-enablement-squad
|
||||
github.com/blevesearch/bleve/v2 v2.5.0 // @grafana/grafana-search-and-storage
|
||||
github.com/blevesearch/bleve_index_api v1.2.7 // @grafana/grafana-search-and-storage
|
||||
github.com/blevesearch/bleve/v2 v2.5.7 // @grafana/grafana-search-and-storage
|
||||
github.com/blevesearch/bleve_index_api v1.3.0 // @grafana/grafana-search-and-storage
|
||||
github.com/blugelabs/bluge v0.2.2 // @grafana/grafana-backend-group
|
||||
github.com/blugelabs/bluge_segment_api v0.2.0 // @grafana/grafana-backend-group
|
||||
github.com/bradfitz/gomemcache v0.0.0-20250403215159-8d39553ac7cf // @grafana/grafana-backend-group
|
||||
@@ -365,22 +365,22 @@ require (
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bits-and-blooms/bitset v1.22.0 // indirect
|
||||
github.com/blang/semver v3.5.1+incompatible // indirect
|
||||
github.com/blevesearch/geo v0.1.20 // indirect
|
||||
github.com/blevesearch/go-faiss v1.0.25 // indirect
|
||||
github.com/blevesearch/geo v0.2.4 // indirect
|
||||
github.com/blevesearch/go-faiss v1.0.26 // indirect
|
||||
github.com/blevesearch/go-porterstemmer v1.0.3 // indirect
|
||||
github.com/blevesearch/gtreap v0.1.1 // indirect
|
||||
github.com/blevesearch/mmap-go v1.0.4 // indirect
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.3.9 // indirect
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.3.13 // indirect
|
||||
github.com/blevesearch/segment v0.9.1 // indirect
|
||||
github.com/blevesearch/snowballstem v0.9.0 // indirect
|
||||
github.com/blevesearch/upsidedown_store_api v1.0.2 // indirect
|
||||
github.com/blevesearch/vellum v1.1.0 // indirect
|
||||
github.com/blevesearch/zapx/v11 v11.4.1 // indirect
|
||||
github.com/blevesearch/zapx/v12 v12.4.1 // indirect
|
||||
github.com/blevesearch/zapx/v13 v13.4.1 // indirect
|
||||
github.com/blevesearch/zapx/v14 v14.4.1 // indirect
|
||||
github.com/blevesearch/zapx/v15 v15.4.1 // indirect
|
||||
github.com/blevesearch/zapx/v16 v16.2.2 // indirect
|
||||
github.com/blevesearch/zapx/v11 v11.4.2 // indirect
|
||||
github.com/blevesearch/zapx/v12 v12.4.2 // indirect
|
||||
github.com/blevesearch/zapx/v13 v13.4.2 // indirect
|
||||
github.com/blevesearch/zapx/v14 v14.4.2 // indirect
|
||||
github.com/blevesearch/zapx/v15 v15.4.2 // indirect
|
||||
github.com/blevesearch/zapx/v16 v16.2.8 // indirect
|
||||
github.com/bluele/gcache v0.0.2 // indirect
|
||||
github.com/blugelabs/ice v1.0.0 // indirect
|
||||
github.com/blugelabs/ice/v2 v2.0.1 // indirect
|
||||
@@ -443,7 +443,6 @@ require (
|
||||
github.com/golang-jwt/jwt/v5 v5.3.0 // indirect
|
||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
|
||||
github.com/golang-sql/sqlexp v0.1.0 // indirect
|
||||
github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 // indirect
|
||||
github.com/gomodule/redigo v1.8.9 // indirect
|
||||
github.com/google/btree v1.1.3 // indirect
|
||||
github.com/google/cel-go v0.26.1 // indirect
|
||||
|
||||
46
go.sum
46
go.sum
@@ -931,14 +931,14 @@ github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdn
|
||||
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
|
||||
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
|
||||
github.com/blevesearch/bleve/v2 v2.5.0 h1:HzYqBy/5/M9Ul9ESEmXzN/3Jl7YpmWBdHM/+zzv/3k4=
|
||||
github.com/blevesearch/bleve/v2 v2.5.0/go.mod h1:PcJzTPnEynO15dCf9isxOga7YFRa/cMSsbnRwnszXUk=
|
||||
github.com/blevesearch/bleve_index_api v1.2.7 h1:c8r9vmbaYQroAMSGag7zq5gEVPiuXrUQDqfnj7uYZSY=
|
||||
github.com/blevesearch/bleve_index_api v1.2.7/go.mod h1:rKQDl4u51uwafZxFrPD1R7xFOwKnzZW7s/LSeK4lgo0=
|
||||
github.com/blevesearch/geo v0.1.20 h1:paaSpu2Ewh/tn5DKn/FB5SzvH0EWupxHEIwbCk/QPqM=
|
||||
github.com/blevesearch/geo v0.1.20/go.mod h1:DVG2QjwHNMFmjo+ZgzrIq2sfCh6rIHzy9d9d0B59I6w=
|
||||
github.com/blevesearch/go-faiss v1.0.25 h1:lel1rkOUGbT1CJ0YgzKwC7k+XH0XVBHnCVWahdCXk4U=
|
||||
github.com/blevesearch/go-faiss v1.0.25/go.mod h1:OMGQwOaRRYxrmeNdMrXJPvVx8gBnvE5RYrr0BahNnkk=
|
||||
github.com/blevesearch/bleve/v2 v2.5.7 h1:2d9YrL5zrX5EBBW++GOaEKjE+NPWeZGaX77IM26m1Z8=
|
||||
github.com/blevesearch/bleve/v2 v2.5.7/go.mod h1:yj0NlS7ocGC4VOSAedqDDMktdh2935v2CSWOCDMHdSA=
|
||||
github.com/blevesearch/bleve_index_api v1.3.0 h1:DsMpWVjFNlBw9/6pyWf59XoqcAkhHj3H0UWiQsavb6E=
|
||||
github.com/blevesearch/bleve_index_api v1.3.0/go.mod h1:xvd48t5XMeeioWQ5/jZvgLrV98flT2rdvEJ3l/ki4Ko=
|
||||
github.com/blevesearch/geo v0.2.4 h1:ECIGQhw+QALCZaDcogRTNSJYQXRtC8/m8IKiA706cqk=
|
||||
github.com/blevesearch/geo v0.2.4/go.mod h1:K56Q33AzXt2YExVHGObtmRSFYZKYGv0JEN5mdacJJR8=
|
||||
github.com/blevesearch/go-faiss v1.0.26 h1:4dRLolFgjPyjkaXwff4NfbZFdE/dfywbzDqporeQvXI=
|
||||
github.com/blevesearch/go-faiss v1.0.26/go.mod h1:OMGQwOaRRYxrmeNdMrXJPvVx8gBnvE5RYrr0BahNnkk=
|
||||
github.com/blevesearch/go-porterstemmer v1.0.3 h1:GtmsqID0aZdCSNiY8SkuPJ12pD4jI+DdXTAn4YRcHCo=
|
||||
github.com/blevesearch/go-porterstemmer v1.0.3/go.mod h1:angGc5Ht+k2xhJdZi511LtmxuEf0OVpvUUNrwmM1P7M=
|
||||
github.com/blevesearch/gtreap v0.1.1 h1:2JWigFrzDMR+42WGIN/V2p0cUvn4UP3C4Q5nmaZGW8Y=
|
||||
@@ -947,8 +947,8 @@ github.com/blevesearch/mmap-go v1.0.2/go.mod h1:ol2qBqYaOUsGdm7aRMRrYGgPvnwLe6Y+
|
||||
github.com/blevesearch/mmap-go v1.0.3/go.mod h1:pYvKl/grLQrBxuaRYgoTssa4rVujYYeenDp++2E+yvs=
|
||||
github.com/blevesearch/mmap-go v1.0.4 h1:OVhDhT5B/M1HNPpYPBKIEJaD0F3Si+CrEKULGCDPWmc=
|
||||
github.com/blevesearch/mmap-go v1.0.4/go.mod h1:EWmEAOmdAS9z/pi/+Toxu99DnsbhG1TIxUoRmJw/pSs=
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.3.9 h1:X6nJXnNHl7nasXW+U6y2Ns2Aw8F9STszkYkyBfQ+p0o=
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.3.9/go.mod h1:IrzspZlVjhf4X29oJiEhBxEteTqOY9RlYlk1lCmYHr4=
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.3.13 h1:ZPjv/4VwWvHJZKeMSgScCapOy8+DdmsmRyLmSB88UoY=
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.3.13/go.mod h1:ENk2LClTehOuMS8XzN3UxBEErYmtwkE7MAArFTXs9Vc=
|
||||
github.com/blevesearch/segment v0.9.0/go.mod h1:9PfHYUdQCgHktBgvtUOF4x+pc4/l8rdH0u5spnW85UQ=
|
||||
github.com/blevesearch/segment v0.9.1 h1:+dThDy+Lvgj5JMxhmOVlgFfkUtZV2kw49xax4+jTfSU=
|
||||
github.com/blevesearch/segment v0.9.1/go.mod h1:zN21iLm7+GnBHWTao9I+Au/7MBiL8pPFtJBJTsk6kQw=
|
||||
@@ -960,18 +960,18 @@ github.com/blevesearch/vellum v1.0.5/go.mod h1:atE0EH3fvk43zzS7t1YNdNC7DbmcC3uz+
|
||||
github.com/blevesearch/vellum v1.0.7/go.mod h1:doBZpmRhwTsASB4QdUZANlJvqVAUdUyX0ZK7QJCTeBE=
|
||||
github.com/blevesearch/vellum v1.1.0 h1:CinkGyIsgVlYf8Y2LUQHvdelgXr6PYuvoDIajq6yR9w=
|
||||
github.com/blevesearch/vellum v1.1.0/go.mod h1:QgwWryE8ThtNPxtgWJof5ndPfx0/YMBh+W2weHKPw8Y=
|
||||
github.com/blevesearch/zapx/v11 v11.4.1 h1:qFCPlFbsEdwbbckJkysptSQOsHn4s6ZOHL5GMAIAVHA=
|
||||
github.com/blevesearch/zapx/v11 v11.4.1/go.mod h1:qNOGxIqdPC1MXauJCD9HBG487PxviTUUbmChFOAosGs=
|
||||
github.com/blevesearch/zapx/v12 v12.4.1 h1:K77bhypII60a4v8mwvav7r4IxWA8qxhNjgF9xGdb9eQ=
|
||||
github.com/blevesearch/zapx/v12 v12.4.1/go.mod h1:QRPrlPOzAxBNMI0MkgdD+xsTqx65zbuPr3Ko4Re49II=
|
||||
github.com/blevesearch/zapx/v13 v13.4.1 h1:EnkEMZFUK0lsW/jOJJF2xOcp+W8TjEsyeN5BeAZEYYE=
|
||||
github.com/blevesearch/zapx/v13 v13.4.1/go.mod h1:e6duBMlCvgbH9rkzNMnUa9hRI9F7ri2BRcHfphcmGn8=
|
||||
github.com/blevesearch/zapx/v14 v14.4.1 h1:G47kGCshknBZzZAtjcnIAMn3oNx8XBLxp8DMq18ogyE=
|
||||
github.com/blevesearch/zapx/v14 v14.4.1/go.mod h1:O7sDxiaL2r2PnCXbhh1Bvm7b4sP+jp4unE9DDPWGoms=
|
||||
github.com/blevesearch/zapx/v15 v15.4.1 h1:B5IoTMUCEzFdc9FSQbhVOxAY+BO17c05866fNruiI7g=
|
||||
github.com/blevesearch/zapx/v15 v15.4.1/go.mod h1:b/MreHjYeQoLjyY2+UaM0hGZZUajEbE0xhnr1A2/Q6Y=
|
||||
github.com/blevesearch/zapx/v16 v16.2.2 h1:MifKJVRTEhMTgSlle2bDRTb39BGc9jXFRLPZc6r0Rzk=
|
||||
github.com/blevesearch/zapx/v16 v16.2.2/go.mod h1:B9Pk4G1CqtErgQV9DyCSA9Lb7WZe4olYfGw7fVDZ4sk=
|
||||
github.com/blevesearch/zapx/v11 v11.4.2 h1:l46SV+b0gFN+Rw3wUI1YdMWdSAVhskYuvxlcgpQFljs=
|
||||
github.com/blevesearch/zapx/v11 v11.4.2/go.mod h1:4gdeyy9oGa/lLa6D34R9daXNUvfMPZqUYjPwiLmekwc=
|
||||
github.com/blevesearch/zapx/v12 v12.4.2 h1:fzRbhllQmEMUuAQ7zBuMvKRlcPA5ESTgWlDEoB9uQNE=
|
||||
github.com/blevesearch/zapx/v12 v12.4.2/go.mod h1:TdFmr7afSz1hFh/SIBCCZvcLfzYvievIH6aEISCte58=
|
||||
github.com/blevesearch/zapx/v13 v13.4.2 h1:46PIZCO/ZuKZYgxI8Y7lOJqX3Irkc3N8W82QTK3MVks=
|
||||
github.com/blevesearch/zapx/v13 v13.4.2/go.mod h1:knK8z2NdQHlb5ot/uj8wuvOq5PhDGjNYQQy0QDnopZk=
|
||||
github.com/blevesearch/zapx/v14 v14.4.2 h1:2SGHakVKd+TrtEqpfeq8X+So5PShQ5nW6GNxT7fWYz0=
|
||||
github.com/blevesearch/zapx/v14 v14.4.2/go.mod h1:rz0XNb/OZSMjNorufDGSpFpjoFKhXmppH9Hi7a877D8=
|
||||
github.com/blevesearch/zapx/v15 v15.4.2 h1:sWxpDE0QQOTjyxYbAVjt3+0ieu8NCE0fDRaFxEsp31k=
|
||||
github.com/blevesearch/zapx/v15 v15.4.2/go.mod h1:1pssev/59FsuWcgSnTa0OeEpOzmhtmr/0/11H0Z8+Nw=
|
||||
github.com/blevesearch/zapx/v16 v16.2.8 h1:SlnzF0YGtSlrsOE3oE7EgEX6BIepGpeqxs1IjMbHLQI=
|
||||
github.com/blevesearch/zapx/v16 v16.2.8/go.mod h1:murSoCJPCk25MqURrcJaBQ1RekuqSCSfMjXH4rHyA14=
|
||||
github.com/bluele/gcache v0.0.2 h1:WcbfdXICg7G/DGBh1PFfcirkWOQV+v077yF1pSy3DGw=
|
||||
github.com/bluele/gcache v0.0.2/go.mod h1:m15KV+ECjptwSPxKhOhQoAFQVtUFjTVkc3H8o0t/fp0=
|
||||
github.com/blugelabs/bluge v0.2.2 h1:gat8CqE6P6tOgeX30XGLOVNTC26cpM2RWVcreXWtYcM=
|
||||
@@ -1442,8 +1442,6 @@ github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2V
|
||||
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
|
||||
github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||
github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 h1:gtexQ/VGyN+VVFRXSFiguSNcXmS6rkKT+X7FdIrTtfo=
|
||||
github.com/golang/geo v0.0.0-20210211234256-740aa86cb551/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4=
|
||||
github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ=
|
||||
|
||||
29
go.work.sum
29
go.work.sum
@@ -520,14 +520,40 @@ github.com/benbjohnson/immutable v0.4.0 h1:CTqXbEerYso8YzVPxmWxh2gnoRQbbB9X1quUC
|
||||
github.com/benbjohnson/immutable v0.4.0/go.mod h1:iAr8OjJGLnLmVUr9MZ/rz4PWUy6Ouc2JLYuMArmvAJM=
|
||||
github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
|
||||
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932 h1:mXoPYz/Ul5HYEDvkta6I8/rnYM5gSdSV2tJ6XbZuEtY=
|
||||
github.com/blevesearch/bleve/v2 v2.5.7 h1:2d9YrL5zrX5EBBW++GOaEKjE+NPWeZGaX77IM26m1Z8=
|
||||
github.com/blevesearch/bleve/v2 v2.5.7/go.mod h1:yj0NlS7ocGC4VOSAedqDDMktdh2935v2CSWOCDMHdSA=
|
||||
github.com/blevesearch/bleve_index_api v1.2.8/go.mod h1:rKQDl4u51uwafZxFrPD1R7xFOwKnzZW7s/LSeK4lgo0=
|
||||
github.com/blevesearch/bleve_index_api v1.2.11 h1:bXQ54kVuwP8hdrXUSOnvTQfgK0KI1+f9A0ITJT8tX1s=
|
||||
github.com/blevesearch/bleve_index_api v1.2.11/go.mod h1:rKQDl4u51uwafZxFrPD1R7xFOwKnzZW7s/LSeK4lgo0=
|
||||
github.com/blevesearch/bleve_index_api v1.3.0 h1:DsMpWVjFNlBw9/6pyWf59XoqcAkhHj3H0UWiQsavb6E=
|
||||
github.com/blevesearch/bleve_index_api v1.3.0/go.mod h1:xvd48t5XMeeioWQ5/jZvgLrV98flT2rdvEJ3l/ki4Ko=
|
||||
github.com/blevesearch/geo v0.2.4 h1:ECIGQhw+QALCZaDcogRTNSJYQXRtC8/m8IKiA706cqk=
|
||||
github.com/blevesearch/geo v0.2.4/go.mod h1:K56Q33AzXt2YExVHGObtmRSFYZKYGv0JEN5mdacJJR8=
|
||||
github.com/blevesearch/go-faiss v1.0.26/go.mod h1:OMGQwOaRRYxrmeNdMrXJPvVx8gBnvE5RYrr0BahNnkk=
|
||||
github.com/blevesearch/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:kDy+zgJFJJoJYBvdfBSiZYBbdsUL0XcjHYWezpQBGPA=
|
||||
github.com/blevesearch/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:9eJDeqxJ3E7WnLebQUlPD7ZjSce7AnDb9vjGmMCbD0A=
|
||||
github.com/blevesearch/goleveldb v1.0.1 h1:iAtV2Cu5s0GD1lwUiekkFHe2gTMCCNVj2foPclDLIFI=
|
||||
github.com/blevesearch/goleveldb v1.0.1/go.mod h1:WrU8ltZbIp0wAoig/MHbrPCXSOLpe79nz5lv5nqfYrQ=
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.3.10/go.mod h1:Z3e6ChN3qyN35yaQpl00MfI5s8AxUJbpTR/DL8QOQ+8=
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.3.13 h1:ZPjv/4VwWvHJZKeMSgScCapOy8+DdmsmRyLmSB88UoY=
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.3.13/go.mod h1:ENk2LClTehOuMS8XzN3UxBEErYmtwkE7MAArFTXs9Vc=
|
||||
github.com/blevesearch/snowball v0.6.1 h1:cDYjn/NCH+wwt2UdehaLpr2e4BwLIjN4V/TdLsL+B5A=
|
||||
github.com/blevesearch/snowball v0.6.1/go.mod h1:ZF0IBg5vgpeoUhnMza2v0A/z8m1cWPlwhke08LpNusg=
|
||||
github.com/blevesearch/stempel v0.2.0 h1:CYzVPaScODMvgE9o+kf6D4RJ/VRomyi9uHF+PtB+Afc=
|
||||
github.com/blevesearch/stempel v0.2.0/go.mod h1:wjeTHqQv+nQdbPuJ/YcvOjTInA2EIc6Ks1FoSUzSLvc=
|
||||
github.com/blevesearch/vellum v1.0.10/go.mod h1:ul1oT0FhSMDIExNjIxHqJoGpVrBpKCdgDQNxfqgJt7k=
|
||||
github.com/blevesearch/zapx/v11 v11.4.2 h1:l46SV+b0gFN+Rw3wUI1YdMWdSAVhskYuvxlcgpQFljs=
|
||||
github.com/blevesearch/zapx/v11 v11.4.2/go.mod h1:4gdeyy9oGa/lLa6D34R9daXNUvfMPZqUYjPwiLmekwc=
|
||||
github.com/blevesearch/zapx/v12 v12.4.2 h1:fzRbhllQmEMUuAQ7zBuMvKRlcPA5ESTgWlDEoB9uQNE=
|
||||
github.com/blevesearch/zapx/v12 v12.4.2/go.mod h1:TdFmr7afSz1hFh/SIBCCZvcLfzYvievIH6aEISCte58=
|
||||
github.com/blevesearch/zapx/v13 v13.4.2 h1:46PIZCO/ZuKZYgxI8Y7lOJqX3Irkc3N8W82QTK3MVks=
|
||||
github.com/blevesearch/zapx/v13 v13.4.2/go.mod h1:knK8z2NdQHlb5ot/uj8wuvOq5PhDGjNYQQy0QDnopZk=
|
||||
github.com/blevesearch/zapx/v14 v14.4.2 h1:2SGHakVKd+TrtEqpfeq8X+So5PShQ5nW6GNxT7fWYz0=
|
||||
github.com/blevesearch/zapx/v14 v14.4.2/go.mod h1:rz0XNb/OZSMjNorufDGSpFpjoFKhXmppH9Hi7a877D8=
|
||||
github.com/blevesearch/zapx/v15 v15.4.2 h1:sWxpDE0QQOTjyxYbAVjt3+0ieu8NCE0fDRaFxEsp31k=
|
||||
github.com/blevesearch/zapx/v15 v15.4.2/go.mod h1:1pssev/59FsuWcgSnTa0OeEpOzmhtmr/0/11H0Z8+Nw=
|
||||
github.com/blevesearch/zapx/v16 v16.2.8 h1:SlnzF0YGtSlrsOE3oE7EgEX6BIepGpeqxs1IjMbHLQI=
|
||||
github.com/blevesearch/zapx/v16 v16.2.8/go.mod h1:murSoCJPCk25MqURrcJaBQ1RekuqSCSfMjXH4rHyA14=
|
||||
github.com/bmatcuk/doublestar v1.3.4 h1:gPypJ5xD31uhX6Tf54sDPUOBXTqKH4c9aPY66CyQrS0=
|
||||
github.com/bmatcuk/doublestar v1.3.4/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE=
|
||||
github.com/bmatcuk/doublestar/v4 v4.6.1 h1:FH9SifrbvJhnlQpztAx++wlkk70QBf0iBWDwNy7PA4I=
|
||||
@@ -998,8 +1024,6 @@ github.com/grafana/prometheus-alertmanager v0.25.1-0.20250331083058-4563aec7a975
|
||||
github.com/grafana/prometheus-alertmanager v0.25.1-0.20250331083058-4563aec7a975/go.mod h1:FGdGvhI40Dq+CTQaSzK9evuve774cgOUdGfVO04OXkw=
|
||||
github.com/grafana/prometheus-alertmanager v0.25.1-0.20250604130045-92c8f6389b36 h1:AjZ58JRw1ZieFH/SdsddF5BXtsDKt5kSrKNPWrzYz3Y=
|
||||
github.com/grafana/prometheus-alertmanager v0.25.1-0.20250604130045-92c8f6389b36/go.mod h1:O/QP1BCm0HHIzbKvgMzqb5sSyH88rzkFk84F4TfJjBU=
|
||||
github.com/grafana/prometheus-alertmanager v0.25.1-0.20260112162805-d29cc9cf7f0f h1:9tRhudagkQO2s61SLFLSziIdCm7XlkfypVKDxpcHokg=
|
||||
github.com/grafana/prometheus-alertmanager v0.25.1-0.20260112162805-d29cc9cf7f0f/go.mod h1:AsVdCBeDFN9QbgpJg+8voDAcgsW0RmNvBd70ecMMdC0=
|
||||
github.com/grafana/pyroscope-go/godeltaprof v0.1.8/go.mod h1:2+l7K7twW49Ct4wFluZD3tZ6e0SjanjcUUBPVD/UuGU=
|
||||
github.com/grafana/pyroscope/api v1.2.1-0.20250415190842-3ff7247547ae/go.mod h1:6CJ1uXmLZ13ufpO9xE4pST+DyaBt0uszzrV0YnoaVLQ=
|
||||
github.com/grafana/sqlds/v4 v4.2.4/go.mod h1:BQRjUG8rOqrBI4NAaeoWrIMuoNgfi8bdhCJ+5cgEfLU=
|
||||
@@ -1092,6 +1116,7 @@ github.com/jon-whit/go-grpc-prometheus v1.4.0/go.mod h1:iTPm+Iuhh3IIqR0iGZ91JJEg
|
||||
github.com/joncrlsn/dque v0.0.0-20211108142734-c2ef48c5192a h1:sfe532Ipn7GX0V6mHdynBk393rDmqgI0QmjLK7ct7TU=
|
||||
github.com/joncrlsn/dque v0.0.0-20211108142734-c2ef48c5192a/go.mod h1:dNKs71rs2VJGBAmttu7fouEsRQlRjxy0p1Sx+T5wbpY=
|
||||
github.com/josephspurrier/goversioninfo v1.4.0/go.mod h1:JWzv5rKQr+MmW+LvM412ToT/IkYDZjaclF2pKDss8IY=
|
||||
github.com/json-iterator/go v0.0.0-20171115153421-f7279a603ede/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o=
|
||||
github.com/jsternberg/zap-logfmt v1.3.0 h1:z1n1AOHVVydOOVuyphbOKyR4NICDQFiJMn1IK5hVQ5Y=
|
||||
github.com/jsternberg/zap-logfmt v1.3.0/go.mod h1:N3DENp9WNmCZxvkBD/eReWwz1149BK6jEN9cQ4fNwZE=
|
||||
|
||||
@@ -35,6 +35,14 @@
|
||||
},
|
||||
"./test": {
|
||||
"@grafana-app/source": "./test/index.ts"
|
||||
},
|
||||
"./themes/schema.generated.json": {
|
||||
"@grafana-app/source": "./src/themes/schema.generated.json",
|
||||
"default": "./dist/esm/themes/schema.generated.json"
|
||||
},
|
||||
"./themes/definitions/*.json": {
|
||||
"@grafana-app/source": "./src/themes/themeDefinitions/*.json",
|
||||
"default": "./dist/esm/themes/themeDefinitions/*.json"
|
||||
}
|
||||
},
|
||||
"publishConfig": {
|
||||
@@ -52,7 +60,7 @@
|
||||
"typecheck": "tsc --emitDeclarationOnly false --noEmit",
|
||||
"prepack": "cp package.json package.json.bak && node ../../scripts/prepare-npm-package.js",
|
||||
"postpack": "mv package.json.bak package.json",
|
||||
"themes-schema": "tsx ./src/themes/scripts/generateSchema.ts"
|
||||
"themes-schema": "tsx ./scripts/generateSchema.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@braintree/sanitize-url": "7.0.1",
|
||||
@@ -102,6 +110,7 @@
|
||||
"react-dom": "18.3.1",
|
||||
"rimraf": "6.0.1",
|
||||
"rollup": "^4.22.4",
|
||||
"rollup-plugin-copy": "3.5.0",
|
||||
"rollup-plugin-esbuild": "6.2.1",
|
||||
"rollup-plugin-node-externals": "^8.0.0",
|
||||
"tsx": "^4.21.0",
|
||||
|
||||
@@ -1,21 +1,40 @@
|
||||
import json from '@rollup/plugin-json';
|
||||
import { createRequire } from 'node:module';
|
||||
import copy from 'rollup-plugin-copy';
|
||||
|
||||
import { entryPoint, plugins, esmOutput, cjsOutput } from '../rollup.config.parts';
|
||||
|
||||
const rq = createRequire(import.meta.url);
|
||||
const pkg = rq('./package.json');
|
||||
|
||||
const grafanaDataPlugins = [
|
||||
...plugins,
|
||||
copy({
|
||||
targets: [
|
||||
{
|
||||
src: 'src/themes/schema.generated.json',
|
||||
dest: 'dist/esm/',
|
||||
},
|
||||
{
|
||||
src: 'src/themes/themeDefinitions/*.json',
|
||||
dest: 'dist/esm/',
|
||||
},
|
||||
],
|
||||
flatten: false,
|
||||
}),
|
||||
json(),
|
||||
];
|
||||
|
||||
export default [
|
||||
{
|
||||
input: entryPoint,
|
||||
plugins: [...plugins, json()],
|
||||
plugins: grafanaDataPlugins,
|
||||
output: [cjsOutput(pkg, 'grafana-data'), esmOutput(pkg, 'grafana-data')],
|
||||
treeshake: false,
|
||||
},
|
||||
{
|
||||
input: 'src/unstable.ts',
|
||||
plugins: [...plugins, json()],
|
||||
plugins: grafanaDataPlugins,
|
||||
output: [cjsOutput(pkg, 'grafana-data'), esmOutput(pkg, 'grafana-data')],
|
||||
treeshake: false,
|
||||
},
|
||||
|
||||
22
packages/grafana-data/scripts/generateSchema.ts
Normal file
22
packages/grafana-data/scripts/generateSchema.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
import { NewThemeOptionsSchema } from '../src/themes/createTheme';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
const jsonOut = path.join(__dirname, '..', 'src', 'themes', 'schema.generated.json');
|
||||
|
||||
fs.writeFileSync(
|
||||
jsonOut,
|
||||
JSON.stringify(
|
||||
NewThemeOptionsSchema.toJSONSchema({
|
||||
target: 'draft-07',
|
||||
}),
|
||||
undefined,
|
||||
2
|
||||
)
|
||||
);
|
||||
|
||||
console.log('Successfully generated theme schema');
|
||||
@@ -93,7 +93,6 @@ export { DataTransformerID } from '../transformations/transformers/ids';
|
||||
|
||||
export { mergeTransformer } from '../transformations/transformers/merge';
|
||||
export { getThemeById } from '../themes/registry';
|
||||
export * as experimentalThemeDefinitions from '../themes/themeDefinitions';
|
||||
export { GrafanaEdition } from '../types/config';
|
||||
export { SIPrefix } from '../valueFormats/symbolFormatters';
|
||||
|
||||
|
||||
@@ -1,7 +1,18 @@
|
||||
import { Registry, RegistryItem } from '../utils/Registry';
|
||||
|
||||
import { createTheme, NewThemeOptionsSchema } from './createTheme';
|
||||
import * as extraThemes from './themeDefinitions';
|
||||
import aubergine from './themeDefinitions/aubergine.json';
|
||||
import debug from './themeDefinitions/debug.json';
|
||||
import desertbloom from './themeDefinitions/desertbloom.json';
|
||||
import gildedgrove from './themeDefinitions/gildedgrove.json';
|
||||
import gloom from './themeDefinitions/gloom.json';
|
||||
import mars from './themeDefinitions/mars.json';
|
||||
import matrix from './themeDefinitions/matrix.json';
|
||||
import sapphiredusk from './themeDefinitions/sapphiredusk.json';
|
||||
import synthwave from './themeDefinitions/synthwave.json';
|
||||
import tron from './themeDefinitions/tron.json';
|
||||
import victorian from './themeDefinitions/victorian.json';
|
||||
import zen from './themeDefinitions/zen.json';
|
||||
import { GrafanaTheme2 } from './types';
|
||||
|
||||
export interface ThemeRegistryItem extends RegistryItem {
|
||||
@@ -9,6 +20,21 @@ export interface ThemeRegistryItem extends RegistryItem {
|
||||
build: () => GrafanaTheme2;
|
||||
}
|
||||
|
||||
const extraThemes: { [key: string]: unknown } = {
|
||||
aubergine,
|
||||
debug,
|
||||
desertbloom,
|
||||
gildedgrove,
|
||||
gloom,
|
||||
mars,
|
||||
matrix,
|
||||
sapphiredusk,
|
||||
synthwave,
|
||||
tron,
|
||||
victorian,
|
||||
zen,
|
||||
};
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* Only for internal use, never use this from a plugin
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
import { NewThemeOptionsSchema } from '../createTheme';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
fs.writeFileSync(
|
||||
path.join(__dirname, '../schema.generated.json'),
|
||||
JSON.stringify(
|
||||
NewThemeOptionsSchema.toJSONSchema({
|
||||
target: 'draft-07',
|
||||
}),
|
||||
undefined,
|
||||
2
|
||||
)
|
||||
);
|
||||
@@ -1,12 +0,0 @@
|
||||
export { default as aubergine } from './aubergine.json';
|
||||
export { default as debug } from './debug.json';
|
||||
export { default as desertbloom } from './desertbloom.json';
|
||||
export { default as gildedgrove } from './gildedgrove.json';
|
||||
export { default as mars } from './mars.json';
|
||||
export { default as matrix } from './matrix.json';
|
||||
export { default as sapphiredusk } from './sapphiredusk.json';
|
||||
export { default as synthwave } from './synthwave.json';
|
||||
export { default as tron } from './tron.json';
|
||||
export { default as victorian } from './victorian.json';
|
||||
export { default as zen } from './zen.json';
|
||||
export { default as gloom } from './gloom.json';
|
||||
@@ -531,6 +531,10 @@ export interface FeatureToggles {
|
||||
*/
|
||||
alertingListViewV2?: boolean;
|
||||
/**
|
||||
* Enables the new Alerting navigation structure with improved menu grouping
|
||||
*/
|
||||
alertingNavigationV2?: boolean;
|
||||
/**
|
||||
* Enables saved searches for alert rules list
|
||||
*/
|
||||
alertingSavedSearches?: boolean;
|
||||
|
||||
@@ -9,4 +9,4 @@
|
||||
* and be subject to the standard policies
|
||||
*/
|
||||
|
||||
export { default as themeJsonSchema } from './themes/schema.generated.json';
|
||||
export {};
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
"emitDeclarationOnly": true,
|
||||
"isolatedModules": true,
|
||||
"rootDirs": ["."],
|
||||
"moduleResolution": "bundler"
|
||||
"moduleResolution": "bundler",
|
||||
"resolveJsonModule": true
|
||||
},
|
||||
"exclude": ["dist/**/*"],
|
||||
"include": [
|
||||
|
||||
@@ -879,6 +879,13 @@ var (
|
||||
Owner: grafanaAlertingSquad,
|
||||
FrontendOnly: true,
|
||||
},
|
||||
{
|
||||
Name: "alertingNavigationV2",
|
||||
Description: "Enables the new Alerting navigation structure with improved menu grouping",
|
||||
Stage: FeatureStageExperimental,
|
||||
Owner: grafanaAlertingSquad,
|
||||
FrontendOnly: false,
|
||||
},
|
||||
{
|
||||
Name: "alertingSavedSearches",
|
||||
Description: "Enables saved searches for alert rules list",
|
||||
|
||||
1
pkg/services/featuremgmt/toggles_gen.csv
generated
1
pkg/services/featuremgmt/toggles_gen.csv
generated
@@ -121,6 +121,7 @@ dashboardLibrary,experimental,@grafana/sharing-squad,false,false,false
|
||||
suggestedDashboards,experimental,@grafana/sharing-squad,false,false,false
|
||||
dashboardTemplates,preview,@grafana/sharing-squad,false,false,false
|
||||
alertingListViewV2,privatePreview,@grafana/alerting-squad,false,false,true
|
||||
alertingNavigationV2,experimental,@grafana/alerting-squad,false,false,false
|
||||
alertingSavedSearches,experimental,@grafana/alerting-squad,false,false,true
|
||||
alertingDisableSendAlertsExternal,experimental,@grafana/alerting-squad,false,false,false
|
||||
preserveDashboardStateWhenNavigating,experimental,@grafana/dashboards-squad,false,false,false
|
||||
|
||||
|
4
pkg/services/featuremgmt/toggles_gen.go
generated
4
pkg/services/featuremgmt/toggles_gen.go
generated
@@ -371,6 +371,10 @@ const (
|
||||
// Enables a flow to get started with a new dashboard from a template
|
||||
FlagDashboardTemplates = "dashboardTemplates"
|
||||
|
||||
// FlagAlertingNavigationV2
|
||||
// Enables the new Alerting navigation structure with improved menu grouping
|
||||
FlagAlertingNavigationV2 = "alertingNavigationV2"
|
||||
|
||||
// FlagAlertingDisableSendAlertsExternal
|
||||
// Disables the ability to send alerts to an external Alertmanager datasource.
|
||||
FlagAlertingDisableSendAlertsExternal = "alertingDisableSendAlertsExternal"
|
||||
|
||||
12
pkg/services/featuremgmt/toggles_gen.json
generated
12
pkg/services/featuremgmt/toggles_gen.json
generated
@@ -348,6 +348,18 @@
|
||||
"expression": "true"
|
||||
}
|
||||
},
|
||||
{
|
||||
"metadata": {
|
||||
"name": "alertingNavigationV2",
|
||||
"resourceVersion": "1768320918269",
|
||||
"creationTimestamp": "2026-01-13T16:15:18Z"
|
||||
},
|
||||
"spec": {
|
||||
"description": "Enables the new Alerting navigation structure with improved menu grouping",
|
||||
"stage": "experimental",
|
||||
"codeowner": "@grafana/alerting-squad"
|
||||
}
|
||||
},
|
||||
{
|
||||
"metadata": {
|
||||
"name": "alertingNotificationHistory",
|
||||
|
||||
@@ -600,6 +600,7 @@ type Cfg struct {
|
||||
IndexRebuildInterval time.Duration
|
||||
IndexCacheTTL time.Duration
|
||||
IndexMinUpdateInterval time.Duration // Don't update index if it was updated less than this interval ago.
|
||||
IndexScoringModel string // Note: Temporary config to switch the index scoring model and will be removed soon.
|
||||
MaxFileIndexAge time.Duration // Max age of file-based indexes. Index older than this will be rebuilt asynchronously.
|
||||
MinFileIndexBuildVersion string // Minimum version of Grafana that built the file-based index. If index was built with older Grafana, it will be rebuilt asynchronously.
|
||||
EnableSharding bool
|
||||
|
||||
@@ -123,6 +123,10 @@ func (cfg *Cfg) setUnifiedStorageConfig() {
|
||||
cfg.IndexRebuildInterval = section.Key("index_rebuild_interval").MustDuration(24 * time.Hour)
|
||||
cfg.IndexCacheTTL = section.Key("index_cache_ttl").MustDuration(10 * time.Minute)
|
||||
cfg.IndexMinUpdateInterval = section.Key("index_min_update_interval").MustDuration(0)
|
||||
cfg.IndexScoringModel = section.Key("index_scoring_model").MustString("")
|
||||
if cfg.IndexScoringModel != "" {
|
||||
cfg.Logger.Info("Index scoring model set", "model", cfg.IndexScoringModel)
|
||||
}
|
||||
cfg.SprinklesApiServer = section.Key("sprinkles_api_server").String()
|
||||
cfg.SprinklesApiServerPageLimit = section.Key("sprinkles_api_server_page_limit").MustInt(10000)
|
||||
cfg.CACertPath = section.Key("ca_cert_path").String()
|
||||
|
||||
@@ -9,11 +9,13 @@ import "resource.proto";
|
||||
// Unlike the ResourceStore, this service can be exposed to clients directly
|
||||
// It should be implemented with efficient indexes and does not need read-after-write semantics
|
||||
service ResourceIndex {
|
||||
// Query for documents
|
||||
rpc Search(ResourceSearchRequest) returns (ResourceSearchResponse);
|
||||
|
||||
// Get the resource stats
|
||||
rpc GetStats(ResourceStatsRequest) returns (ResourceStatsResponse);
|
||||
|
||||
// Rebuild the search index
|
||||
rpc RebuildIndexes(RebuildIndexesRequest) returns (RebuildIndexesResponse);
|
||||
}
|
||||
|
||||
@@ -49,6 +51,20 @@ message ResourceStatsResponse {
|
||||
repeated Stats stats = 2;
|
||||
}
|
||||
|
||||
// This controls what query and analyzers are applied to the specified field
|
||||
// See: https://blevesearch.com/docs/Analyzers/
|
||||
enum QueryFieldType {
|
||||
// Picks a reasonable analyzer given the input. Currently this always uses TEXT
|
||||
// In the future, it may change to depend on the indexed field type
|
||||
DEFAULT = 0;
|
||||
// Use free text analyzer. The query is broken into a normalized set of tokens
|
||||
TEXT = 1;
|
||||
// The query must exactly match the indexed token
|
||||
KEYWORD = 2;
|
||||
// Like a text query, but the position and offsets influence the score
|
||||
PHRASE = 3;
|
||||
}
|
||||
|
||||
// Search within a single resource
|
||||
message ResourceSearchRequest {
|
||||
message Sort {
|
||||
@@ -64,6 +80,18 @@ message ResourceSearchRequest {
|
||||
// date queries
|
||||
}
|
||||
|
||||
// Defines the field in the index to query
|
||||
// Boost is optional, and allows weighting the field higher in the results
|
||||
message QueryField {
|
||||
// The field name in the index to query
|
||||
string name = 1;
|
||||
|
||||
QueryFieldType type = 2;
|
||||
|
||||
// Boost value for this field
|
||||
float boost = 3;
|
||||
}
|
||||
|
||||
// The key must include namespace + group + resource
|
||||
ListOptions options = 1;
|
||||
|
||||
@@ -99,6 +127,9 @@ message ResourceSearchRequest {
|
||||
int64 page = 11;
|
||||
|
||||
int64 permission = 12;
|
||||
|
||||
// Optionally specify which fields are included in the query
|
||||
repeated QueryField query_fields = 13;
|
||||
}
|
||||
|
||||
message ResourceSearchResponse {
|
||||
|
||||
@@ -290,7 +290,6 @@ const SEARCH_FIELD_NAMESPACE = "namespace"
|
||||
const SEARCH_FIELD_NAME = "name"
|
||||
const SEARCH_FIELD_RV = "rv"
|
||||
const SEARCH_FIELD_TITLE = "title"
|
||||
const SEARCH_FIELD_TITLE_NGRAM = "title_ngram"
|
||||
const SEARCH_FIELD_TITLE_PHRASE = "title_phrase" // filtering/sorting on title by full phrase
|
||||
const SEARCH_FIELD_DESCRIPTION = "description"
|
||||
const SEARCH_FIELD_TAGS = "tags"
|
||||
|
||||
@@ -21,6 +21,65 @@ const (
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
// This controls what query and analyzers are applied to the specified field
|
||||
// See: https://blevesearch.com/docs/Analyzers/
|
||||
type QueryFieldType int32
|
||||
|
||||
const (
|
||||
// Picks a reasonable analyzer given the input. Currently this always uses TEXT
|
||||
// In the future, it may change to depend on the indexed field type
|
||||
QueryFieldType_DEFAULT QueryFieldType = 0
|
||||
// Use free text analyzer. The query is broken into a normalized set of tokens
|
||||
QueryFieldType_TEXT QueryFieldType = 1
|
||||
// The query must exactly match the indexed token
|
||||
QueryFieldType_KEYWORD QueryFieldType = 2
|
||||
// Like a text query, but the position and offsets influence the score
|
||||
QueryFieldType_PHRASE QueryFieldType = 3
|
||||
)
|
||||
|
||||
// Enum value maps for QueryFieldType.
|
||||
var (
|
||||
QueryFieldType_name = map[int32]string{
|
||||
0: "DEFAULT",
|
||||
1: "TEXT",
|
||||
2: "KEYWORD",
|
||||
3: "PHRASE",
|
||||
}
|
||||
QueryFieldType_value = map[string]int32{
|
||||
"DEFAULT": 0,
|
||||
"TEXT": 1,
|
||||
"KEYWORD": 2,
|
||||
"PHRASE": 3,
|
||||
}
|
||||
)
|
||||
|
||||
func (x QueryFieldType) Enum() *QueryFieldType {
|
||||
p := new(QueryFieldType)
|
||||
*p = x
|
||||
return p
|
||||
}
|
||||
|
||||
func (x QueryFieldType) String() string {
|
||||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
||||
}
|
||||
|
||||
func (QueryFieldType) Descriptor() protoreflect.EnumDescriptor {
|
||||
return file_search_proto_enumTypes[0].Descriptor()
|
||||
}
|
||||
|
||||
func (QueryFieldType) Type() protoreflect.EnumType {
|
||||
return &file_search_proto_enumTypes[0]
|
||||
}
|
||||
|
||||
func (x QueryFieldType) Number() protoreflect.EnumNumber {
|
||||
return protoreflect.EnumNumber(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use QueryFieldType.Descriptor instead.
|
||||
func (QueryFieldType) EnumDescriptor() ([]byte, []int) {
|
||||
return file_search_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
// Get statistics across multiple resources
|
||||
// For these queries, we do not need authorization to see the actual values
|
||||
type ResourceStatsRequest struct {
|
||||
@@ -165,10 +224,12 @@ type ResourceSearchRequest struct {
|
||||
// the return fields (empty will return everything)
|
||||
Fields []string `protobuf:"bytes,8,rep,name=fields,proto3" json:"fields,omitempty"`
|
||||
// explain each result (added to the each row)
|
||||
Explain bool `protobuf:"varint,9,opt,name=explain,proto3" json:"explain,omitempty"`
|
||||
IsDeleted bool `protobuf:"varint,10,opt,name=is_deleted,json=isDeleted,proto3" json:"is_deleted,omitempty"`
|
||||
Page int64 `protobuf:"varint,11,opt,name=page,proto3" json:"page,omitempty"`
|
||||
Permission int64 `protobuf:"varint,12,opt,name=permission,proto3" json:"permission,omitempty"`
|
||||
Explain bool `protobuf:"varint,9,opt,name=explain,proto3" json:"explain,omitempty"`
|
||||
IsDeleted bool `protobuf:"varint,10,opt,name=is_deleted,json=isDeleted,proto3" json:"is_deleted,omitempty"`
|
||||
Page int64 `protobuf:"varint,11,opt,name=page,proto3" json:"page,omitempty"`
|
||||
Permission int64 `protobuf:"varint,12,opt,name=permission,proto3" json:"permission,omitempty"`
|
||||
// Optionally specify which fields are included in the query
|
||||
QueryFields []*ResourceSearchRequest_QueryField `protobuf:"bytes,13,rep,name=query_fields,json=queryFields,proto3" json:"query_fields,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
@@ -287,6 +348,13 @@ func (x *ResourceSearchRequest) GetPermission() int64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *ResourceSearchRequest) GetQueryFields() []*ResourceSearchRequest_QueryField {
|
||||
if x != nil {
|
||||
return x.QueryFields
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ResourceSearchResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
// Error details
|
||||
@@ -670,6 +738,70 @@ func (x *ResourceSearchRequest_Facet) GetLimit() int64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
// Defines the field in the index to query
|
||||
// Boost is optional, and allows weighting the field higher in the results
|
||||
type ResourceSearchRequest_QueryField struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
// The field name in the index to query
|
||||
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||
Type QueryFieldType `protobuf:"varint,2,opt,name=type,proto3,enum=resource.QueryFieldType" json:"type,omitempty"`
|
||||
// Boost value for this field
|
||||
Boost float32 `protobuf:"fixed32,3,opt,name=boost,proto3" json:"boost,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *ResourceSearchRequest_QueryField) Reset() {
|
||||
*x = ResourceSearchRequest_QueryField{}
|
||||
mi := &file_search_proto_msgTypes[9]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *ResourceSearchRequest_QueryField) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ResourceSearchRequest_QueryField) ProtoMessage() {}
|
||||
|
||||
func (x *ResourceSearchRequest_QueryField) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_search_proto_msgTypes[9]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ResourceSearchRequest_QueryField.ProtoReflect.Descriptor instead.
|
||||
func (*ResourceSearchRequest_QueryField) Descriptor() ([]byte, []int) {
|
||||
return file_search_proto_rawDescGZIP(), []int{2, 2}
|
||||
}
|
||||
|
||||
func (x *ResourceSearchRequest_QueryField) GetName() string {
|
||||
if x != nil {
|
||||
return x.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ResourceSearchRequest_QueryField) GetType() QueryFieldType {
|
||||
if x != nil {
|
||||
return x.Type
|
||||
}
|
||||
return QueryFieldType_DEFAULT
|
||||
}
|
||||
|
||||
func (x *ResourceSearchRequest_QueryField) GetBoost() float32 {
|
||||
if x != nil {
|
||||
return x.Boost
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type ResourceSearchResponse_Facet struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Field string `protobuf:"bytes,1,opt,name=field,proto3" json:"field,omitempty"`
|
||||
@@ -685,7 +817,7 @@ type ResourceSearchResponse_Facet struct {
|
||||
|
||||
func (x *ResourceSearchResponse_Facet) Reset() {
|
||||
*x = ResourceSearchResponse_Facet{}
|
||||
mi := &file_search_proto_msgTypes[10]
|
||||
mi := &file_search_proto_msgTypes[11]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
@@ -697,7 +829,7 @@ func (x *ResourceSearchResponse_Facet) String() string {
|
||||
func (*ResourceSearchResponse_Facet) ProtoMessage() {}
|
||||
|
||||
func (x *ResourceSearchResponse_Facet) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_search_proto_msgTypes[10]
|
||||
mi := &file_search_proto_msgTypes[11]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@@ -751,7 +883,7 @@ type ResourceSearchResponse_TermFacet struct {
|
||||
|
||||
func (x *ResourceSearchResponse_TermFacet) Reset() {
|
||||
*x = ResourceSearchResponse_TermFacet{}
|
||||
mi := &file_search_proto_msgTypes[11]
|
||||
mi := &file_search_proto_msgTypes[12]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
@@ -763,7 +895,7 @@ func (x *ResourceSearchResponse_TermFacet) String() string {
|
||||
func (*ResourceSearchResponse_TermFacet) ProtoMessage() {}
|
||||
|
||||
func (x *ResourceSearchResponse_TermFacet) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_search_proto_msgTypes[11]
|
||||
mi := &file_search_proto_msgTypes[12]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@@ -818,7 +950,7 @@ var file_search_proto_rawDesc = string([]byte{
|
||||
0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63,
|
||||
0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e,
|
||||
0x74, 0x22, 0x8e, 0x05, 0x0a, 0x15, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65,
|
||||
0x74, 0x22, 0xc3, 0x06, 0x0a, 0x15, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65,
|
||||
0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x07, 0x6f,
|
||||
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x72,
|
||||
0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x70, 0x74, 0x69,
|
||||
@@ -846,93 +978,109 @@ var file_search_proto_rawDesc = string([]byte{
|
||||
0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x0b,
|
||||
0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x70, 0x61, 0x67, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x65,
|
||||
0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a,
|
||||
0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x1a, 0x30, 0x0a, 0x04, 0x53, 0x6f,
|
||||
0x72, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x65, 0x73, 0x63,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x64, 0x65, 0x73, 0x63, 0x1a, 0x33, 0x0a, 0x05,
|
||||
0x46, 0x61, 0x63, 0x65, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6c,
|
||||
0x69, 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69,
|
||||
0x74, 0x1a, 0x5f, 0x0a, 0x0a, 0x46, 0x61, 0x63, 0x65, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12,
|
||||
0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65,
|
||||
0x79, 0x12, 0x3b, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
|
||||
0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f,
|
||||
0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x4d, 0x0a, 0x0c, 0x71, 0x75,
|
||||
0x65, 0x72, 0x79, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b,
|
||||
0x32, 0x2a, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f,
|
||||
0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||
0x74, 0x2e, 0x46, 0x61, 0x63, 0x65, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02,
|
||||
0x38, 0x01, 0x22, 0xea, 0x04, 0x0a, 0x16, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53,
|
||||
0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2b, 0x0a,
|
||||
0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x72,
|
||||
0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x73,
|
||||
0x75, 0x6c, 0x74, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x27, 0x0a, 0x03, 0x6b, 0x65,
|
||||
0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72,
|
||||
0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x03,
|
||||
0x6b, 0x65, 0x79, 0x12, 0x31, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x03,
|
||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e,
|
||||
0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x07, 0x72,
|
||||
0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f,
|
||||
0x68, 0x69, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x6f, 0x74, 0x61,
|
||||
0x6c, 0x48, 0x69, 0x74, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x63,
|
||||
0x6f, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x01, 0x52, 0x09, 0x71, 0x75, 0x65, 0x72, 0x79,
|
||||
0x43, 0x6f, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x63, 0x6f, 0x72,
|
||||
0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x01, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x53, 0x63, 0x6f, 0x72,
|
||||
0x65, 0x12, 0x41, 0x0a, 0x05, 0x66, 0x61, 0x63, 0x65, 0x74, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b,
|
||||
0x32, 0x2b, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f,
|
||||
0x74, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x0b, 0x71, 0x75,
|
||||
0x65, 0x72, 0x79, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x1a, 0x30, 0x0a, 0x04, 0x53, 0x6f, 0x72,
|
||||
0x74, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x65, 0x73, 0x63, 0x18,
|
||||
0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x64, 0x65, 0x73, 0x63, 0x1a, 0x33, 0x0a, 0x05, 0x46,
|
||||
0x61, 0x63, 0x65, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69,
|
||||
0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74,
|
||||
0x1a, 0x64, 0x0a, 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x12,
|
||||
0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
|
||||
0x6d, 0x65, 0x12, 0x2c, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e,
|
||||
0x32, 0x18, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x51, 0x75, 0x65, 0x72,
|
||||
0x79, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65,
|
||||
0x12, 0x14, 0x0a, 0x05, 0x62, 0x6f, 0x6f, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x02, 0x52,
|
||||
0x05, 0x62, 0x6f, 0x6f, 0x73, 0x74, 0x1a, 0x5f, 0x0a, 0x0a, 0x46, 0x61, 0x63, 0x65, 0x74, 0x45,
|
||||
0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3b, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
|
||||
0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
|
||||
0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x46, 0x61, 0x63, 0x65, 0x74, 0x52, 0x05, 0x76, 0x61,
|
||||
0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xea, 0x04, 0x0a, 0x16, 0x52, 0x65, 0x73, 0x6f,
|
||||
0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||
0x73, 0x65, 0x2e, 0x46, 0x61, 0x63, 0x65, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x66,
|
||||
0x61, 0x63, 0x65, 0x74, 0x1a, 0x8f, 0x01, 0x0a, 0x05, 0x46, 0x61, 0x63, 0x65, 0x74, 0x12, 0x14,
|
||||
0x0a, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x66,
|
||||
0x69, 0x65, 0x6c, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, 0x20,
|
||||
0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x69,
|
||||
0x73, 0x73, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x6d, 0x69, 0x73,
|
||||
0x73, 0x69, 0x6e, 0x67, 0x12, 0x40, 0x0a, 0x05, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x18, 0x04, 0x20,
|
||||
0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52,
|
||||
0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73,
|
||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x54, 0x65, 0x72, 0x6d, 0x46, 0x61, 0x63, 0x65, 0x74, 0x52,
|
||||
0x05, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x1a, 0x35, 0x0a, 0x09, 0x54, 0x65, 0x72, 0x6d, 0x46, 0x61,
|
||||
0x63, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x72, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x04, 0x74, 0x65, 0x72, 0x6d, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x1a, 0x60, 0x0a,
|
||||
0x0a, 0x46, 0x61, 0x63, 0x65, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b,
|
||||
0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3c, 0x0a,
|
||||
0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x72,
|
||||
0x73, 0x65, 0x12, 0x2b, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x0b, 0x32, 0x15, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x45, 0x72, 0x72,
|
||||
0x6f, 0x72, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12,
|
||||
0x27, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x72,
|
||||
0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
|
||||
0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x46,
|
||||
0x61, 0x63, 0x65, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22,
|
||||
0x60, 0x0a, 0x15, 0x52, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65,
|
||||
0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65,
|
||||
0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d,
|
||||
0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x29, 0x0a, 0x04, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x02,
|
||||
0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e,
|
||||
0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x04, 0x6b, 0x65, 0x79,
|
||||
0x73, 0x22, 0x83, 0x01, 0x0a, 0x16, 0x52, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x6e, 0x64,
|
||||
0x65, 0x78, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x22, 0x0a, 0x0c,
|
||||
0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x03, 0x52, 0x0c, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74,
|
||||
0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x2b, 0x0a, 0x05, 0x65, 0x72,
|
||||
0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x72, 0x65, 0x73, 0x6f,
|
||||
0x75, 0x72, 0x63, 0x65, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74,
|
||||
0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x32, 0xfe, 0x01, 0x0a, 0x0d, 0x52, 0x65, 0x73, 0x6f,
|
||||
0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x4b, 0x0a, 0x06, 0x53, 0x65, 0x61,
|
||||
0x72, 0x63, 0x68, 0x12, 0x1f, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52,
|
||||
0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e,
|
||||
0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65,
|
||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61,
|
||||
0x74, 0x73, 0x12, 0x1e, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65,
|
||||
0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||
0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65,
|
||||
0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x0e, 0x52, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x6e,
|
||||
0x64, 0x65, 0x78, 0x65, 0x73, 0x12, 0x1f, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
|
||||
0x2e, 0x52, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x73, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63,
|
||||
0x65, 0x2e, 0x52, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x73,
|
||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x3b, 0x5a, 0x39, 0x67, 0x69, 0x74, 0x68,
|
||||
0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, 0x61, 0x66, 0x61, 0x6e, 0x61, 0x2f, 0x67,
|
||||
0x72, 0x61, 0x66, 0x61, 0x6e, 0x61, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x61,
|
||||
0x67, 0x65, 0x2f, 0x75, 0x6e, 0x69, 0x66, 0x69, 0x65, 0x64, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75,
|
||||
0x72, 0x63, 0x65, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x4b, 0x65, 0x79, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x31, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75,
|
||||
0x6c, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x72, 0x65, 0x73, 0x6f,
|
||||
0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x61, 0x62,
|
||||
0x6c, 0x65, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x74,
|
||||
0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x68, 0x69, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52,
|
||||
0x09, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x48, 0x69, 0x74, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x71, 0x75,
|
||||
0x65, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x01, 0x52, 0x09,
|
||||
0x71, 0x75, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x78,
|
||||
0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x01, 0x52, 0x08, 0x6d, 0x61,
|
||||
0x78, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x41, 0x0a, 0x05, 0x66, 0x61, 0x63, 0x65, 0x74, 0x18,
|
||||
0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
|
||||
0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52,
|
||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x46, 0x61, 0x63, 0x65, 0x74, 0x45, 0x6e, 0x74,
|
||||
0x72, 0x79, 0x52, 0x05, 0x66, 0x61, 0x63, 0x65, 0x74, 0x1a, 0x8f, 0x01, 0x0a, 0x05, 0x46, 0x61,
|
||||
0x63, 0x65, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74,
|
||||
0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12,
|
||||
0x18, 0x0a, 0x07, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03,
|
||||
0x52, 0x07, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x12, 0x40, 0x0a, 0x05, 0x74, 0x65, 0x72,
|
||||
0x6d, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75,
|
||||
0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x61, 0x72,
|
||||
0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x54, 0x65, 0x72, 0x6d, 0x46,
|
||||
0x61, 0x63, 0x65, 0x74, 0x52, 0x05, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x1a, 0x35, 0x0a, 0x09, 0x54,
|
||||
0x65, 0x72, 0x6d, 0x46, 0x61, 0x63, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x72, 0x6d,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x72, 0x6d, 0x12, 0x14, 0x0a, 0x05,
|
||||
0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x63, 0x6f, 0x75,
|
||||
0x6e, 0x74, 0x1a, 0x60, 0x0a, 0x0a, 0x46, 0x61, 0x63, 0x65, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79,
|
||||
0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b,
|
||||
0x65, 0x79, 0x12, 0x3c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||
0x0b, 0x32, 0x26, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73,
|
||||
0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x2e, 0x46, 0x61, 0x63, 0x65, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
|
||||
0x3a, 0x02, 0x38, 0x01, 0x22, 0x60, 0x0a, 0x15, 0x52, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x49,
|
||||
0x6e, 0x64, 0x65, 0x78, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a,
|
||||
0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x29, 0x0a, 0x04, 0x6b,
|
||||
0x65, 0x79, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x72, 0x65, 0x73, 0x6f,
|
||||
0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4b, 0x65, 0x79,
|
||||
0x52, 0x04, 0x6b, 0x65, 0x79, 0x73, 0x22, 0x83, 0x01, 0x0a, 0x16, 0x52, 0x65, 0x62, 0x75, 0x69,
|
||||
0x6c, 0x64, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||
0x65, 0x12, 0x22, 0x0a, 0x0c, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x43, 0x6f, 0x75, 0x6e,
|
||||
0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64,
|
||||
0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12,
|
||||
0x2b, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15,
|
||||
0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52,
|
||||
0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2a, 0x40, 0x0a, 0x0e,
|
||||
0x51, 0x75, 0x65, 0x72, 0x79, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b,
|
||||
0x0a, 0x07, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x54,
|
||||
0x45, 0x58, 0x54, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x4b, 0x45, 0x59, 0x57, 0x4f, 0x52, 0x44,
|
||||
0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x50, 0x48, 0x52, 0x41, 0x53, 0x45, 0x10, 0x03, 0x32, 0xfe,
|
||||
0x01, 0x0a, 0x0d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78,
|
||||
0x12, 0x4b, 0x0a, 0x06, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x1f, 0x2e, 0x72, 0x65, 0x73,
|
||||
0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65,
|
||||
0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x72, 0x65,
|
||||
0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53,
|
||||
0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a,
|
||||
0x08, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x1e, 0x2e, 0x72, 0x65, 0x73, 0x6f,
|
||||
0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x74, 0x61,
|
||||
0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x72, 0x65, 0x73, 0x6f,
|
||||
0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x74, 0x61,
|
||||
0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x0e, 0x52, 0x65,
|
||||
0x62, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x73, 0x12, 0x1f, 0x2e, 0x72,
|
||||
0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x49,
|
||||
0x6e, 0x64, 0x65, 0x78, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e,
|
||||
0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64,
|
||||
0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42,
|
||||
0x3b, 0x5a, 0x39, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72,
|
||||
0x61, 0x66, 0x61, 0x6e, 0x61, 0x2f, 0x67, 0x72, 0x61, 0x66, 0x61, 0x6e, 0x61, 0x2f, 0x70, 0x6b,
|
||||
0x67, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2f, 0x75, 0x6e, 0x69, 0x66, 0x69, 0x65,
|
||||
0x64, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x33,
|
||||
})
|
||||
|
||||
var (
|
||||
@@ -947,53 +1095,58 @@ func file_search_proto_rawDescGZIP() []byte {
|
||||
return file_search_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_search_proto_msgTypes = make([]protoimpl.MessageInfo, 13)
|
||||
var file_search_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
||||
var file_search_proto_msgTypes = make([]protoimpl.MessageInfo, 14)
|
||||
var file_search_proto_goTypes = []any{
|
||||
(*ResourceStatsRequest)(nil), // 0: resource.ResourceStatsRequest
|
||||
(*ResourceStatsResponse)(nil), // 1: resource.ResourceStatsResponse
|
||||
(*ResourceSearchRequest)(nil), // 2: resource.ResourceSearchRequest
|
||||
(*ResourceSearchResponse)(nil), // 3: resource.ResourceSearchResponse
|
||||
(*RebuildIndexesRequest)(nil), // 4: resource.RebuildIndexesRequest
|
||||
(*RebuildIndexesResponse)(nil), // 5: resource.RebuildIndexesResponse
|
||||
(*ResourceStatsResponse_Stats)(nil), // 6: resource.ResourceStatsResponse.Stats
|
||||
(*ResourceSearchRequest_Sort)(nil), // 7: resource.ResourceSearchRequest.Sort
|
||||
(*ResourceSearchRequest_Facet)(nil), // 8: resource.ResourceSearchRequest.Facet
|
||||
nil, // 9: resource.ResourceSearchRequest.FacetEntry
|
||||
(*ResourceSearchResponse_Facet)(nil), // 10: resource.ResourceSearchResponse.Facet
|
||||
(*ResourceSearchResponse_TermFacet)(nil), // 11: resource.ResourceSearchResponse.TermFacet
|
||||
nil, // 12: resource.ResourceSearchResponse.FacetEntry
|
||||
(*ErrorResult)(nil), // 13: resource.ErrorResult
|
||||
(*ListOptions)(nil), // 14: resource.ListOptions
|
||||
(*ResourceKey)(nil), // 15: resource.ResourceKey
|
||||
(*ResourceTable)(nil), // 16: resource.ResourceTable
|
||||
(QueryFieldType)(0), // 0: resource.QueryFieldType
|
||||
(*ResourceStatsRequest)(nil), // 1: resource.ResourceStatsRequest
|
||||
(*ResourceStatsResponse)(nil), // 2: resource.ResourceStatsResponse
|
||||
(*ResourceSearchRequest)(nil), // 3: resource.ResourceSearchRequest
|
||||
(*ResourceSearchResponse)(nil), // 4: resource.ResourceSearchResponse
|
||||
(*RebuildIndexesRequest)(nil), // 5: resource.RebuildIndexesRequest
|
||||
(*RebuildIndexesResponse)(nil), // 6: resource.RebuildIndexesResponse
|
||||
(*ResourceStatsResponse_Stats)(nil), // 7: resource.ResourceStatsResponse.Stats
|
||||
(*ResourceSearchRequest_Sort)(nil), // 8: resource.ResourceSearchRequest.Sort
|
||||
(*ResourceSearchRequest_Facet)(nil), // 9: resource.ResourceSearchRequest.Facet
|
||||
(*ResourceSearchRequest_QueryField)(nil), // 10: resource.ResourceSearchRequest.QueryField
|
||||
nil, // 11: resource.ResourceSearchRequest.FacetEntry
|
||||
(*ResourceSearchResponse_Facet)(nil), // 12: resource.ResourceSearchResponse.Facet
|
||||
(*ResourceSearchResponse_TermFacet)(nil), // 13: resource.ResourceSearchResponse.TermFacet
|
||||
nil, // 14: resource.ResourceSearchResponse.FacetEntry
|
||||
(*ErrorResult)(nil), // 15: resource.ErrorResult
|
||||
(*ListOptions)(nil), // 16: resource.ListOptions
|
||||
(*ResourceKey)(nil), // 17: resource.ResourceKey
|
||||
(*ResourceTable)(nil), // 18: resource.ResourceTable
|
||||
}
|
||||
var file_search_proto_depIdxs = []int32{
|
||||
13, // 0: resource.ResourceStatsResponse.error:type_name -> resource.ErrorResult
|
||||
6, // 1: resource.ResourceStatsResponse.stats:type_name -> resource.ResourceStatsResponse.Stats
|
||||
14, // 2: resource.ResourceSearchRequest.options:type_name -> resource.ListOptions
|
||||
15, // 3: resource.ResourceSearchRequest.federated:type_name -> resource.ResourceKey
|
||||
7, // 4: resource.ResourceSearchRequest.sortBy:type_name -> resource.ResourceSearchRequest.Sort
|
||||
9, // 5: resource.ResourceSearchRequest.facet:type_name -> resource.ResourceSearchRequest.FacetEntry
|
||||
13, // 6: resource.ResourceSearchResponse.error:type_name -> resource.ErrorResult
|
||||
15, // 7: resource.ResourceSearchResponse.key:type_name -> resource.ResourceKey
|
||||
16, // 8: resource.ResourceSearchResponse.results:type_name -> resource.ResourceTable
|
||||
12, // 9: resource.ResourceSearchResponse.facet:type_name -> resource.ResourceSearchResponse.FacetEntry
|
||||
15, // 10: resource.RebuildIndexesRequest.keys:type_name -> resource.ResourceKey
|
||||
13, // 11: resource.RebuildIndexesResponse.error:type_name -> resource.ErrorResult
|
||||
8, // 12: resource.ResourceSearchRequest.FacetEntry.value:type_name -> resource.ResourceSearchRequest.Facet
|
||||
11, // 13: resource.ResourceSearchResponse.Facet.terms:type_name -> resource.ResourceSearchResponse.TermFacet
|
||||
10, // 14: resource.ResourceSearchResponse.FacetEntry.value:type_name -> resource.ResourceSearchResponse.Facet
|
||||
2, // 15: resource.ResourceIndex.Search:input_type -> resource.ResourceSearchRequest
|
||||
0, // 16: resource.ResourceIndex.GetStats:input_type -> resource.ResourceStatsRequest
|
||||
4, // 17: resource.ResourceIndex.RebuildIndexes:input_type -> resource.RebuildIndexesRequest
|
||||
3, // 18: resource.ResourceIndex.Search:output_type -> resource.ResourceSearchResponse
|
||||
1, // 19: resource.ResourceIndex.GetStats:output_type -> resource.ResourceStatsResponse
|
||||
5, // 20: resource.ResourceIndex.RebuildIndexes:output_type -> resource.RebuildIndexesResponse
|
||||
18, // [18:21] is the sub-list for method output_type
|
||||
15, // [15:18] is the sub-list for method input_type
|
||||
15, // [15:15] is the sub-list for extension type_name
|
||||
15, // [15:15] is the sub-list for extension extendee
|
||||
0, // [0:15] is the sub-list for field type_name
|
||||
15, // 0: resource.ResourceStatsResponse.error:type_name -> resource.ErrorResult
|
||||
7, // 1: resource.ResourceStatsResponse.stats:type_name -> resource.ResourceStatsResponse.Stats
|
||||
16, // 2: resource.ResourceSearchRequest.options:type_name -> resource.ListOptions
|
||||
17, // 3: resource.ResourceSearchRequest.federated:type_name -> resource.ResourceKey
|
||||
8, // 4: resource.ResourceSearchRequest.sortBy:type_name -> resource.ResourceSearchRequest.Sort
|
||||
11, // 5: resource.ResourceSearchRequest.facet:type_name -> resource.ResourceSearchRequest.FacetEntry
|
||||
10, // 6: resource.ResourceSearchRequest.query_fields:type_name -> resource.ResourceSearchRequest.QueryField
|
||||
15, // 7: resource.ResourceSearchResponse.error:type_name -> resource.ErrorResult
|
||||
17, // 8: resource.ResourceSearchResponse.key:type_name -> resource.ResourceKey
|
||||
18, // 9: resource.ResourceSearchResponse.results:type_name -> resource.ResourceTable
|
||||
14, // 10: resource.ResourceSearchResponse.facet:type_name -> resource.ResourceSearchResponse.FacetEntry
|
||||
17, // 11: resource.RebuildIndexesRequest.keys:type_name -> resource.ResourceKey
|
||||
15, // 12: resource.RebuildIndexesResponse.error:type_name -> resource.ErrorResult
|
||||
0, // 13: resource.ResourceSearchRequest.QueryField.type:type_name -> resource.QueryFieldType
|
||||
9, // 14: resource.ResourceSearchRequest.FacetEntry.value:type_name -> resource.ResourceSearchRequest.Facet
|
||||
13, // 15: resource.ResourceSearchResponse.Facet.terms:type_name -> resource.ResourceSearchResponse.TermFacet
|
||||
12, // 16: resource.ResourceSearchResponse.FacetEntry.value:type_name -> resource.ResourceSearchResponse.Facet
|
||||
3, // 17: resource.ResourceIndex.Search:input_type -> resource.ResourceSearchRequest
|
||||
1, // 18: resource.ResourceIndex.GetStats:input_type -> resource.ResourceStatsRequest
|
||||
5, // 19: resource.ResourceIndex.RebuildIndexes:input_type -> resource.RebuildIndexesRequest
|
||||
4, // 20: resource.ResourceIndex.Search:output_type -> resource.ResourceSearchResponse
|
||||
2, // 21: resource.ResourceIndex.GetStats:output_type -> resource.ResourceStatsResponse
|
||||
6, // 22: resource.ResourceIndex.RebuildIndexes:output_type -> resource.RebuildIndexesResponse
|
||||
20, // [20:23] is the sub-list for method output_type
|
||||
17, // [17:20] is the sub-list for method input_type
|
||||
17, // [17:17] is the sub-list for extension type_name
|
||||
17, // [17:17] is the sub-list for extension extendee
|
||||
0, // [0:17] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_search_proto_init() }
|
||||
@@ -1007,13 +1160,14 @@ func file_search_proto_init() {
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_search_proto_rawDesc), len(file_search_proto_rawDesc)),
|
||||
NumEnums: 0,
|
||||
NumMessages: 13,
|
||||
NumEnums: 1,
|
||||
NumMessages: 14,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
GoTypes: file_search_proto_goTypes,
|
||||
DependencyIndexes: file_search_proto_depIdxs,
|
||||
EnumInfos: file_search_proto_enumTypes,
|
||||
MessageInfos: file_search_proto_msgTypes,
|
||||
}.Build()
|
||||
File_search_proto = out.File
|
||||
|
||||
@@ -31,9 +31,11 @@ const (
|
||||
// Unlike the ResourceStore, this service can be exposed to clients directly
|
||||
// It should be implemented with efficient indexes and does not need read-after-write semantics
|
||||
type ResourceIndexClient interface {
|
||||
// Query for documents
|
||||
Search(ctx context.Context, in *ResourceSearchRequest, opts ...grpc.CallOption) (*ResourceSearchResponse, error)
|
||||
// Get the resource stats
|
||||
GetStats(ctx context.Context, in *ResourceStatsRequest, opts ...grpc.CallOption) (*ResourceStatsResponse, error)
|
||||
// Rebuild the search index
|
||||
RebuildIndexes(ctx context.Context, in *RebuildIndexesRequest, opts ...grpc.CallOption) (*RebuildIndexesResponse, error)
|
||||
}
|
||||
|
||||
@@ -82,9 +84,11 @@ func (c *resourceIndexClient) RebuildIndexes(ctx context.Context, in *RebuildInd
|
||||
// Unlike the ResourceStore, this service can be exposed to clients directly
|
||||
// It should be implemented with efficient indexes and does not need read-after-write semantics
|
||||
type ResourceIndexServer interface {
|
||||
// Query for documents
|
||||
Search(context.Context, *ResourceSearchRequest) (*ResourceSearchResponse, error)
|
||||
// Get the resource stats
|
||||
GetStats(context.Context, *ResourceStatsRequest) (*ResourceStatsResponse, error)
|
||||
// Rebuild the search index
|
||||
RebuildIndexes(context.Context, *RebuildIndexesRequest) (*RebuildIndexesResponse, error)
|
||||
}
|
||||
|
||||
|
||||
@@ -81,6 +81,11 @@ type BleveOptions struct {
|
||||
// Indexes that are not owned by current instance are eligible for cleanup.
|
||||
// If nil, all indexes are owned by the current instance.
|
||||
OwnsIndex func(key resource.NamespacedResource) (bool, error)
|
||||
|
||||
// ScoringModel defines the scoring model used for the bleve indexes
|
||||
// Default: index.TFIDFScoring
|
||||
// Supported values: index.TFIDFScoring and index.BM25Scoring
|
||||
ScoringModel string
|
||||
}
|
||||
|
||||
type bleveBackend struct {
|
||||
@@ -368,7 +373,7 @@ func (b *bleveBackend) BuildIndex(
|
||||
attribute.String("reason", indexBuildReason),
|
||||
)
|
||||
|
||||
mapper, err := GetBleveMappings(fields)
|
||||
mapper, err := GetBleveMappings(b.opts.ScoringModel, fields)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1177,6 +1182,7 @@ func (b *bleveIndex) getIndex(
|
||||
return b.index, nil
|
||||
}
|
||||
|
||||
// nolint:gocyclo
|
||||
func (b *bleveIndex) toBleveSearchRequest(ctx context.Context, req *resourcepb.ResourceSearchRequest, access authlib.AccessClient) (*bleve.SearchRequest, *resourcepb.ErrorResult) {
|
||||
ctx, span := tracer.Start(ctx, "search.bleveIndex.toBleveSearchRequest")
|
||||
defer span.End()
|
||||
@@ -1235,42 +1241,62 @@ func (b *bleveIndex) toBleveSearchRequest(ctx context.Context, req *resourcepb.R
|
||||
}
|
||||
}
|
||||
|
||||
if len(req.Query) > 1 && strings.Contains(req.Query, "*") {
|
||||
// wildcard query is expensive - should be used with caution
|
||||
wildcard := bleve.NewWildcardQuery(req.Query)
|
||||
queries = append(queries, wildcard)
|
||||
}
|
||||
if len(req.Query) > 1 {
|
||||
if strings.Contains(req.Query, "*") {
|
||||
// wildcard query is expensive - should be used with caution
|
||||
wildcard := bleve.NewWildcardQuery(req.Query)
|
||||
queries = append(queries, wildcard)
|
||||
} else {
|
||||
// When using a
|
||||
searchrequest.Fields = append(searchrequest.Fields, resource.SEARCH_FIELD_SCORE)
|
||||
disjoin := bleve.NewDisjunctionQuery()
|
||||
queries = append(queries, disjoin)
|
||||
|
||||
if req.Query != "" && !strings.Contains(req.Query, "*") {
|
||||
// Add a text query
|
||||
searchrequest.Fields = append(searchrequest.Fields, resource.SEARCH_FIELD_SCORE)
|
||||
queryFields := req.QueryFields
|
||||
if len(queryFields) == 0 {
|
||||
queryFields = []*resourcepb.ResourceSearchRequest_QueryField{
|
||||
{
|
||||
Name: resource.SEARCH_FIELD_TITLE,
|
||||
Type: resourcepb.QueryFieldType_KEYWORD,
|
||||
Boost: 10, // exact match -- includes ngrams! If they lived on their own field, we could score them differently
|
||||
}, {
|
||||
Name: resource.SEARCH_FIELD_TITLE,
|
||||
Type: resourcepb.QueryFieldType_TEXT,
|
||||
Boost: 2, // standard analyzer (with ngrams!)
|
||||
}, {
|
||||
Name: resource.SEARCH_FIELD_TITLE_PHRASE,
|
||||
Type: resourcepb.QueryFieldType_TEXT,
|
||||
Boost: 5, // standard analyzer
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// There are multiple ways to match the query string to documents. The following queries are ordered by priority:
|
||||
for _, field := range queryFields {
|
||||
switch field.Type {
|
||||
case resourcepb.QueryFieldType_TEXT, resourcepb.QueryFieldType_DEFAULT:
|
||||
q := bleve.NewMatchQuery(removeSmallTerms(req.Query)) // removeSmallTerms should be part of the analyzer
|
||||
q.SetBoost(float64(field.Boost))
|
||||
q.SetField(field.Name)
|
||||
q.Analyzer = standard.Name // analyze the text
|
||||
q.Operator = query.MatchQueryOperatorAnd // all terms must match
|
||||
disjoin.AddQuery(q)
|
||||
|
||||
// Query 1: Match the exact query string
|
||||
queryExact := bleve.NewMatchQuery(req.Query)
|
||||
queryExact.SetBoost(10.0)
|
||||
queryExact.SetField(resource.SEARCH_FIELD_TITLE)
|
||||
queryExact.Analyzer = keyword.Name // don't analyze the query input - treat it as a single token
|
||||
queryExact.Operator = query.MatchQueryOperatorAnd // This doesn't make a difference for keyword analyzer, we add it just to be explicit.
|
||||
searchQuery := bleve.NewDisjunctionQuery(queryExact)
|
||||
case resourcepb.QueryFieldType_KEYWORD:
|
||||
q := bleve.NewMatchQuery(req.Query)
|
||||
q.SetBoost(float64(field.Boost))
|
||||
q.SetField(field.Name)
|
||||
q.Analyzer = keyword.Name // don't analyze the query input - treat it as a single token
|
||||
disjoin.AddQuery(q)
|
||||
|
||||
// Query 2: Phrase query with standard analyzer
|
||||
queryPhrase := bleve.NewMatchPhraseQuery(req.Query)
|
||||
queryPhrase.SetBoost(5.0)
|
||||
queryPhrase.SetField(resource.SEARCH_FIELD_TITLE)
|
||||
queryPhrase.Analyzer = standard.Name
|
||||
searchQuery.AddQuery(queryPhrase)
|
||||
|
||||
// Query 3: Match query with standard analyzer
|
||||
queryAnalyzed := bleve.NewMatchQuery(removeSmallTerms(req.Query))
|
||||
queryAnalyzed.SetField(resource.SEARCH_FIELD_TITLE)
|
||||
queryAnalyzed.SetBoost(2.0)
|
||||
queryAnalyzed.Analyzer = standard.Name
|
||||
queryAnalyzed.Operator = query.MatchQueryOperatorAnd // Make sure all terms from the query are matched
|
||||
searchQuery.AddQuery(queryAnalyzed)
|
||||
|
||||
queries = append(queries, searchQuery)
|
||||
case resourcepb.QueryFieldType_PHRASE:
|
||||
q := bleve.NewMatchPhraseQuery(req.Query)
|
||||
q.SetBoost(float64(field.Boost))
|
||||
q.SetField(field.Name)
|
||||
q.Analyzer = standard.Name
|
||||
disjoin.AddQuery(q)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch len(queries) {
|
||||
@@ -1872,7 +1898,7 @@ func (q *permissionScopedQuery) Searcher(ctx context.Context, i index.IndexReade
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
filteringSearcher := bleveSearch.NewFilteringSearcher(ctx, searcher, func(d *search.DocumentMatch) bool {
|
||||
filteringSearcher := bleveSearch.NewFilteringSearcher(ctx, searcher, func(_ *search.SearchContext, d *search.DocumentMatch) bool {
|
||||
// The doc ID has the format: <namespace>/<group>/<resourceType>/<name>
|
||||
// IndexInternalID will be the same as the doc ID when using an in-memory index, but when using a file-based
|
||||
// index it becomes a binary encoded number that has some other internal meaning. Using ExternalID() will get the
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
index "github.com/blevesearch/bleve_index_api"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/storage/unified/resource"
|
||||
@@ -19,6 +20,7 @@ func TestBleveSearchBackend(t *testing.T) {
|
||||
backend, err := NewBleveBackend(BleveOptions{
|
||||
Root: tempDir,
|
||||
FileThreshold: 5,
|
||||
ScoringModel: index.BM25Scoring,
|
||||
}, nil)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, backend)
|
||||
@@ -52,3 +54,32 @@ func TestSearchBackendBenchmark(t *testing.T) {
|
||||
|
||||
unitest.BenchmarkSearchBackend(t, backend, opts)
|
||||
}
|
||||
|
||||
func BenchmarkScoringModels(b *testing.B) {
|
||||
models := []string{index.TFIDFScoring, index.BM25Scoring}
|
||||
|
||||
for _, model := range models {
|
||||
b.Run(model, func(b *testing.B) {
|
||||
tempDir := b.TempDir()
|
||||
|
||||
backend, err := NewBleveBackend(BleveOptions{
|
||||
Root: tempDir,
|
||||
ScoringModel: model,
|
||||
}, nil)
|
||||
require.NoError(b, err)
|
||||
require.NotNil(b, backend)
|
||||
|
||||
b.Cleanup(backend.Stop)
|
||||
|
||||
opts := &unitest.BenchmarkOptions{
|
||||
NumResources: 1000,
|
||||
Concurrency: 4,
|
||||
NumNamespaces: 10,
|
||||
NumGroups: 10,
|
||||
NumResourceTypes: 10,
|
||||
}
|
||||
|
||||
unitest.BenchmarkSearchBackend(b, backend, opts)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,13 +5,15 @@ import (
|
||||
"github.com/blevesearch/bleve/v2/analysis/analyzer/keyword"
|
||||
"github.com/blevesearch/bleve/v2/analysis/analyzer/standard"
|
||||
"github.com/blevesearch/bleve/v2/mapping"
|
||||
|
||||
"github.com/grafana/grafana/pkg/storage/unified/resource"
|
||||
"github.com/grafana/grafana/pkg/storage/unified/resourcepb"
|
||||
)
|
||||
|
||||
func GetBleveMappings(fields resource.SearchableDocumentFields) (mapping.IndexMapping, error) {
|
||||
func GetBleveMappings(scoringModel string, fields resource.SearchableDocumentFields) (mapping.IndexMapping, error) {
|
||||
mapper := bleve.NewIndexMapping()
|
||||
if scoringModel != "" {
|
||||
mapper.ScoringModel = scoringModel
|
||||
}
|
||||
|
||||
err := RegisterCustomAnalyzers(mapper)
|
||||
if err != nil {
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
)
|
||||
|
||||
func TestDocumentMapping(t *testing.T) {
|
||||
mappings, err := search.GetBleveMappings(nil)
|
||||
mappings, err := search.GetBleveMappings("", nil)
|
||||
require.NoError(t, err)
|
||||
data := resource.IndexableDocument{
|
||||
Title: "title",
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/blevesearch/bleve/v2"
|
||||
index "github.com/blevesearch/bleve_index_api"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
||||
@@ -258,6 +259,7 @@ func newTestDashboardsIndex(t testing.TB, threshold int64, size int64, writer re
|
||||
backend, err := search.NewBleveBackend(search.BleveOptions{
|
||||
Root: t.TempDir(),
|
||||
FileThreshold: threshold, // use in-memory for tests
|
||||
ScoringModel: index.BM25Scoring,
|
||||
}, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/blevesearch/bleve/v2"
|
||||
index "github.com/blevesearch/bleve_index_api"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/testutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -50,6 +51,7 @@ func TestBleveBackend(t *testing.T) {
|
||||
backend, err := NewBleveBackend(BleveOptions{
|
||||
Root: tmpdir,
|
||||
FileThreshold: 5, // with more than 5 items we create a file on disk
|
||||
ScoringModel: index.BM25Scoring,
|
||||
}, nil)
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(backend.Stop)
|
||||
@@ -773,6 +775,7 @@ func setupBleveBackend(t *testing.T, options ...setupOption) (*bleveBackend, pro
|
||||
IndexCacheTTL: defaultIndexCacheTTL,
|
||||
Logger: log.NewNopLogger(),
|
||||
BuildVersion: buildVersion,
|
||||
ScoringModel: index.BM25Scoring,
|
||||
}
|
||||
for _, opt := range options {
|
||||
opt(&opts)
|
||||
|
||||
@@ -46,6 +46,7 @@ func NewSearchOptions(
|
||||
BuildVersion: cfg.BuildVersion,
|
||||
OwnsIndex: ownsIndexFn,
|
||||
IndexMinUpdateInterval: cfg.IndexMinUpdateInterval,
|
||||
ScoringModel: cfg.IndexScoringModel,
|
||||
}, indexMetrics)
|
||||
|
||||
if err != nil {
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
index "github.com/blevesearch/bleve_index_api"
|
||||
"github.com/go-jose/go-jose/v4/jwt"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -129,21 +130,28 @@ func TestIntegrationSearchAndStorage(t *testing.T) {
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
// Create a new bleve backend
|
||||
search, err := search.NewBleveBackend(search.BleveOptions{
|
||||
FileThreshold: 0,
|
||||
Root: t.TempDir(),
|
||||
}, nil)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, search)
|
||||
t.Cleanup(search.Stop)
|
||||
scoringModels := []string{index.TFIDFScoring, index.BM25Scoring}
|
||||
|
||||
// Create a new resource backend
|
||||
storage, _ := newTestBackend(t, false, 0)
|
||||
require.NotNil(t, storage)
|
||||
for _, model := range scoringModels {
|
||||
t.Run(model, func(t *testing.T) {
|
||||
// Create a new bleve backend
|
||||
search, err := search.NewBleveBackend(search.BleveOptions{
|
||||
FileThreshold: 0,
|
||||
Root: t.TempDir(),
|
||||
ScoringModel: model,
|
||||
}, nil)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, search)
|
||||
t.Cleanup(search.Stop)
|
||||
|
||||
// Run the shared storage and search tests
|
||||
unitest.RunTestSearchAndStorage(t, ctx, storage, search)
|
||||
// Create a new resource backend
|
||||
storage, _ := newTestBackend(t, false, 0)
|
||||
require.NotNil(t, storage)
|
||||
|
||||
// Run the shared storage and search tests
|
||||
unitest.RunTestSearchAndStorage(t, ctx, storage, search)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientServer(t *testing.T) {
|
||||
|
||||
@@ -209,7 +209,7 @@
|
||||
"path": "public/plugins/grafana-azure-monitor-datasource/img/azure_monitor_cpu.png"
|
||||
}
|
||||
],
|
||||
"version": "12.3.0-pre",
|
||||
"version": "12.4.0-pre",
|
||||
"updated": "",
|
||||
"keywords": [
|
||||
"azure",
|
||||
@@ -589,7 +589,7 @@
|
||||
"hasUpdate": false,
|
||||
"defaultNavUrl": "/plugins/datagrid/",
|
||||
"category": "",
|
||||
"state": "beta",
|
||||
"state": "deprecated",
|
||||
"signature": "internal",
|
||||
"signatureType": "",
|
||||
"signatureOrg": "",
|
||||
@@ -880,7 +880,7 @@
|
||||
},
|
||||
"build": {},
|
||||
"screenshots": null,
|
||||
"version": "12.3.0-pre",
|
||||
"version": "12.4.0-pre",
|
||||
"updated": "",
|
||||
"keywords": null
|
||||
},
|
||||
@@ -934,7 +934,7 @@
|
||||
},
|
||||
"build": {},
|
||||
"screenshots": null,
|
||||
"version": "12.3.0-pre",
|
||||
"version": "12.4.0-pre",
|
||||
"updated": "",
|
||||
"keywords": [
|
||||
"grafana",
|
||||
@@ -1000,7 +1000,7 @@
|
||||
},
|
||||
"build": {},
|
||||
"screenshots": null,
|
||||
"version": "12.3.0-pre",
|
||||
"version": "12.4.0-pre",
|
||||
"updated": "",
|
||||
"keywords": null
|
||||
},
|
||||
@@ -1217,7 +1217,7 @@
|
||||
},
|
||||
"build": {},
|
||||
"screenshots": null,
|
||||
"version": "12.3.0-pre",
|
||||
"version": "12.4.0-pre",
|
||||
"updated": "",
|
||||
"keywords": null
|
||||
},
|
||||
@@ -1325,7 +1325,7 @@
|
||||
},
|
||||
"build": {},
|
||||
"screenshots": null,
|
||||
"version": "12.3.0-pre",
|
||||
"version": "12.4.0-pre",
|
||||
"updated": "",
|
||||
"keywords": null
|
||||
},
|
||||
@@ -1375,7 +1375,7 @@
|
||||
},
|
||||
"build": {},
|
||||
"screenshots": null,
|
||||
"version": "12.3.0-pre",
|
||||
"version": "12.4.0-pre",
|
||||
"updated": "",
|
||||
"keywords": null
|
||||
},
|
||||
@@ -1425,7 +1425,7 @@
|
||||
},
|
||||
"build": {},
|
||||
"screenshots": null,
|
||||
"version": "12.3.0-pre",
|
||||
"version": "12.4.0-pre",
|
||||
"updated": "",
|
||||
"keywords": null
|
||||
},
|
||||
@@ -1575,7 +1575,7 @@
|
||||
},
|
||||
"build": {},
|
||||
"screenshots": null,
|
||||
"version": "",
|
||||
"version": "12.4.0-pre",
|
||||
"updated": "",
|
||||
"keywords": null
|
||||
},
|
||||
@@ -1629,7 +1629,7 @@
|
||||
},
|
||||
"build": {},
|
||||
"screenshots": null,
|
||||
"version": "12.3.0-pre",
|
||||
"version": "12.4.0-pre",
|
||||
"updated": "",
|
||||
"keywords": [
|
||||
"grafana",
|
||||
@@ -1734,7 +1734,7 @@
|
||||
},
|
||||
"build": {},
|
||||
"screenshots": null,
|
||||
"version": "12.3.0-pre",
|
||||
"version": "12.4.0-pre",
|
||||
"updated": "",
|
||||
"keywords": null
|
||||
},
|
||||
@@ -2042,7 +2042,7 @@
|
||||
},
|
||||
"build": {},
|
||||
"screenshots": null,
|
||||
"version": "12.3.0-pre",
|
||||
"version": "12.4.0-pre",
|
||||
"updated": "",
|
||||
"keywords": null
|
||||
},
|
||||
@@ -2092,7 +2092,7 @@
|
||||
},
|
||||
"build": {},
|
||||
"screenshots": null,
|
||||
"version": "12.3.0-pre",
|
||||
"version": "12.4.0-pre",
|
||||
"updated": "",
|
||||
"keywords": null
|
||||
},
|
||||
@@ -2445,7 +2445,7 @@
|
||||
},
|
||||
"build": {},
|
||||
"screenshots": null,
|
||||
"version": "12.3.0-pre",
|
||||
"version": "12.4.0-pre",
|
||||
"updated": "",
|
||||
"keywords": null
|
||||
},
|
||||
|
||||
@@ -97,7 +97,7 @@ func TestIntegrationSearchDevDashboards(t *testing.T) {
|
||||
require.Equal(t, 16, fileCount, "file count from %s", devenv)
|
||||
|
||||
// Helper to call search
|
||||
callSearch := func(user apis.User, params string) dashboardV0.SearchResults {
|
||||
callSearch := func(user apis.User, params map[string]string) dashboardV0.SearchResults {
|
||||
require.NotNil(t, user)
|
||||
ns := user.Identity.GetNamespace()
|
||||
cfg := dynamic.ConfigFor(user.NewRestConfig())
|
||||
@@ -107,17 +107,12 @@ func TestIntegrationSearchDevDashboards(t *testing.T) {
|
||||
|
||||
var statusCode int
|
||||
req := restClient.Get().AbsPath("apis", "dashboard.grafana.app", "v0alpha1", "namespaces", ns, "search").
|
||||
//Param("explain", "true") // helpful to understand which field made things match
|
||||
Param("limit", "1000").
|
||||
Param("type", "dashboard") // Only search dashboards
|
||||
|
||||
for kv := range strings.SplitSeq(params, "&") {
|
||||
if kv == "" {
|
||||
continue
|
||||
}
|
||||
parts := strings.SplitN(kv, "=", 2)
|
||||
if len(parts) == 2 {
|
||||
req = req.Param(parts[0], parts[1])
|
||||
}
|
||||
for k, v := range params {
|
||||
req = req.Param(k, v)
|
||||
}
|
||||
res := req.Do(ctx).StatusCode(&statusCode)
|
||||
require.NoError(t, res.Error())
|
||||
@@ -140,22 +135,47 @@ func TestIntegrationSearchDevDashboards(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
user apis.User
|
||||
params string
|
||||
params map[string]string
|
||||
}{
|
||||
{
|
||||
name: "all",
|
||||
user: helper.Org1.Admin,
|
||||
params: "", // only dashboards
|
||||
name: "all",
|
||||
user: helper.Org1.Admin,
|
||||
},
|
||||
{
|
||||
name: "simple-query",
|
||||
user: helper.Org1.Admin,
|
||||
params: "query=stacking",
|
||||
name: "query-single-word",
|
||||
user: helper.Org1.Admin,
|
||||
params: map[string]string{
|
||||
"query": "stacking",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "with-text-panel",
|
||||
user: helper.Org1.Admin,
|
||||
params: "field=panel_types&panelType=text",
|
||||
name: "query-multiple-words",
|
||||
user: helper.Org1.Admin,
|
||||
params: map[string]string{
|
||||
"query": "graph softMin", // must match ALL terms
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "with-text-panel",
|
||||
user: helper.Org1.Admin,
|
||||
params: map[string]string{
|
||||
"field": "panel_types", // return panel types
|
||||
"panelType": "text",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "title-ngram-prefix",
|
||||
user: helper.Org1.Admin,
|
||||
params: map[string]string{
|
||||
"query": "zer", // should match "Zero Decimals Y Ticks"
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "title-ngram-middle-word",
|
||||
user: helper.Org1.Admin,
|
||||
params: map[string]string{
|
||||
"query": "decim", // should match "Zero Decimals Y Ticks"
|
||||
},
|
||||
},
|
||||
}
|
||||
for i, tc := range testCases {
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"panel-tests",
|
||||
"graph-ng"
|
||||
],
|
||||
"score": 0.658
|
||||
"score": 0.284
|
||||
},
|
||||
{
|
||||
"resource": "dashboards",
|
||||
@@ -21,8 +21,8 @@
|
||||
"panel-tests",
|
||||
"graph-ng"
|
||||
],
|
||||
"score": 0.625
|
||||
"score": 0.269
|
||||
}
|
||||
],
|
||||
"maxScore": 0.658
|
||||
"maxScore": 0.284
|
||||
}
|
||||
17
pkg/tests/apis/dashboard/testdata/searchV0/t02-query-multiple-words.json
vendored
Normal file
17
pkg/tests/apis/dashboard/testdata/searchV0/t02-query-multiple-words.json
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"totalHits": 1,
|
||||
"hits": [
|
||||
{
|
||||
"resource": "dashboards",
|
||||
"name": "timeseries-soft-limits",
|
||||
"title": "Panel Tests - Graph NG - softMin/softMax",
|
||||
"tags": [
|
||||
"gdev",
|
||||
"panel-tests",
|
||||
"graph-ng"
|
||||
],
|
||||
"score": 0.024
|
||||
}
|
||||
],
|
||||
"maxScore": 0.024
|
||||
}
|
||||
17
pkg/tests/apis/dashboard/testdata/searchV0/t04-title-ngram-prefix.json
vendored
Normal file
17
pkg/tests/apis/dashboard/testdata/searchV0/t04-title-ngram-prefix.json
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"totalHits": 1,
|
||||
"hits": [
|
||||
{
|
||||
"resource": "dashboards",
|
||||
"name": "timeseries-y-ticks-zero-decimals",
|
||||
"title": "Zero Decimals Y Ticks",
|
||||
"tags": [
|
||||
"gdev",
|
||||
"panel-tests",
|
||||
"graph-ng"
|
||||
],
|
||||
"score": 0.35
|
||||
}
|
||||
],
|
||||
"maxScore": 0.35
|
||||
}
|
||||
17
pkg/tests/apis/dashboard/testdata/searchV0/t05-title-ngram-middle-word.json
vendored
Normal file
17
pkg/tests/apis/dashboard/testdata/searchV0/t05-title-ngram-middle-word.json
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"totalHits": 1,
|
||||
"hits": [
|
||||
{
|
||||
"resource": "dashboards",
|
||||
"name": "timeseries-y-ticks-zero-decimals",
|
||||
"title": "Zero Decimals Y Ticks",
|
||||
"tags": [
|
||||
"gdev",
|
||||
"panel-tests",
|
||||
"graph-ng"
|
||||
],
|
||||
"score": 0.35
|
||||
}
|
||||
],
|
||||
"maxScore": 0.35
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import { DataQuery } from '@grafana/data';
|
||||
import { createMonitoringLogger, MonitoringLogger } from '@grafana/runtime';
|
||||
import store from 'app/core/store';
|
||||
import { RichHistoryQuery } from 'app/types/explore';
|
||||
|
||||
@@ -26,8 +27,15 @@ jest.mock('@grafana/runtime', () => ({
|
||||
...jest.requireActual('@grafana/runtime'),
|
||||
getBackendSrv: () => backendSrv,
|
||||
getDataSourceSrv: () => dsMock,
|
||||
createMonitoringLogger: jest.fn().mockReturnValue({ logWarning: jest.fn() }),
|
||||
}));
|
||||
|
||||
// logger is created at import so we cannot initialize inside the test
|
||||
const loggerIndex = (createMonitoringLogger as jest.Mock).mock.calls.findIndex(
|
||||
(args) => args[0] === 'features.query-history.local-storage'
|
||||
);
|
||||
const loggerMock: MonitoringLogger = (createMonitoringLogger as jest.Mock).mock.results[loggerIndex]?.value;
|
||||
|
||||
interface MockQuery extends DataQuery {
|
||||
query: string;
|
||||
}
|
||||
@@ -75,6 +83,8 @@ describe('RichHistoryLocalStorage', () => {
|
||||
jest.setSystemTime(now);
|
||||
storage = new RichHistoryLocalStorage();
|
||||
await storage.deleteAll();
|
||||
|
||||
(loggerMock.logWarning as jest.Mock).mockReset();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -223,6 +233,90 @@ describe('RichHistoryLocalStorage', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('quota errors and retries', () => {
|
||||
it('should rotate and retry saving when QuotaExceededError occurs once', async () => {
|
||||
const initial = [
|
||||
{ ts: Date.now(), starred: true, comment: 'starred1', queries: [], datasourceName: 'name-of-dev-test' },
|
||||
{ ts: Date.now(), starred: false, comment: 'notStarred1', queries: [], datasourceName: 'name-of-dev-test' },
|
||||
{ ts: Date.now(), starred: true, comment: 'starred2', queries: [], datasourceName: 'name-of-dev-test' },
|
||||
];
|
||||
store.setObject(key, initial);
|
||||
|
||||
// Spy on setObject to throw once with QuotaExceededError, then call through
|
||||
const originalSetObject = store.setObject.bind(store);
|
||||
jest
|
||||
.spyOn(store, 'setObject')
|
||||
// first attempt throws and errors
|
||||
.mockImplementationOnce(() => {
|
||||
const err = new Error('quota hit');
|
||||
err.name = 'QuotaExceededError';
|
||||
throw err;
|
||||
})
|
||||
// second attempt calls through
|
||||
.mockImplementation((k: string, value: unknown) => {
|
||||
return originalSetObject(k, value);
|
||||
});
|
||||
|
||||
const result = await storage.addToRichHistory({
|
||||
starred: false,
|
||||
datasourceUid: 'dev-test',
|
||||
datasourceName: 'name-of-dev-test',
|
||||
comment: 'new',
|
||||
queries: [{ refId: 'A' }],
|
||||
});
|
||||
expect(result.richHistoryQuery).toBeDefined();
|
||||
|
||||
// After one failure, rotation removes one unstarred entry
|
||||
const saved = store.getObject<RichHistoryQuery[]>(key)!;
|
||||
expect(saved).toHaveLength(3);
|
||||
expect(saved).toMatchObject([
|
||||
expect.objectContaining({ comment: 'new' }),
|
||||
expect.objectContaining({ comment: 'starred1' }),
|
||||
expect.objectContaining({ comment: 'starred2' }),
|
||||
]);
|
||||
|
||||
// Ensure logger was called for the failure, with expected flags
|
||||
expect(loggerMock.logWarning).toHaveBeenCalled();
|
||||
const [message, payload] = (loggerMock.logWarning as jest.Mock).mock.calls[0];
|
||||
expect(message).toContain('Failed to save rich history to local storage');
|
||||
expect(payload.saveRetriesLeft).toBe('3');
|
||||
expect(payload.quotaExceededError).toBe('true');
|
||||
});
|
||||
|
||||
it('should throw StorageFull when QuotaExceededError persists for all retries and track attempts', async () => {
|
||||
store.setObject(key, [
|
||||
{ ts: Date.now(), starred: false, comment: 'notStarred1', queries: [], datasourceName: 'name-of-dev-test' },
|
||||
]);
|
||||
|
||||
const setSpy = jest.spyOn(store, 'setObject').mockImplementation(() => {
|
||||
const err = new Error('quota still hit');
|
||||
err.name = 'QuotaExceededError';
|
||||
throw err;
|
||||
});
|
||||
|
||||
await expect(
|
||||
storage.addToRichHistory({
|
||||
starred: false,
|
||||
datasourceUid: 'dev-test',
|
||||
datasourceName: 'name-of-dev-test',
|
||||
comment: 'new',
|
||||
queries: [{ refId: 'B' }],
|
||||
})
|
||||
).rejects.toMatchObject({ name: 'StorageFull' });
|
||||
|
||||
// 4 failed tracking attempts (1 save + 3 retries) should be logged (for each failed try)
|
||||
expect(loggerMock.logWarning).toHaveBeenCalledTimes(4);
|
||||
const calls = (loggerMock.logWarning as jest.Mock).mock.calls;
|
||||
expect(calls[0][0]).toContain('Failed to save rich history to local storage');
|
||||
expect(calls[0][1].saveRetriesLeft).toBe('3');
|
||||
expect(calls[1][1].saveRetriesLeft).toBe('2');
|
||||
expect(calls[2][1].saveRetriesLeft).toBe('1');
|
||||
expect(calls[3][1].saveRetriesLeft).toBe('0');
|
||||
|
||||
setSpy.mockRestore();
|
||||
});
|
||||
});
|
||||
|
||||
describe('migration', () => {
|
||||
afterEach(() => {
|
||||
storage.deleteAll();
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { find, isEqual, omit } from 'lodash';
|
||||
|
||||
import { DataQuery, SelectableValue } from '@grafana/data';
|
||||
import { RichHistorySearchFilters, RichHistorySettings } from 'app/core/utils/richHistoryTypes';
|
||||
import { createMonitoringLogger } from '@grafana/runtime';
|
||||
import { RichHistorySearchFilters, RichHistorySettings, SortOrder } from 'app/core/utils/richHistoryTypes';
|
||||
import { RichHistoryQuery } from 'app/types/explore';
|
||||
|
||||
import store from '../store';
|
||||
@@ -26,10 +27,18 @@ export type RichHistoryLocalStorageDTO = {
|
||||
queries: DataQuery[];
|
||||
};
|
||||
|
||||
const logger = createMonitoringLogger('features.query-history.local-storage');
|
||||
|
||||
/**
|
||||
* Local storage implementation for Rich History. It keeps all entries in browser's local storage.
|
||||
*/
|
||||
export default class RichHistoryLocalStorage implements RichHistoryStorage {
|
||||
public static getLocalStorageUsageInBytes(): number {
|
||||
const richHistory: RichHistoryLocalStorageDTO[] = store.get(RICH_HISTORY_KEY) || '';
|
||||
// each character is 2 bytes
|
||||
return richHistory.length * 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return history entries based on provided filters, perform migration and clean up entries not matching retention policy.
|
||||
*/
|
||||
@@ -77,21 +86,43 @@ export default class RichHistoryLocalStorage implements RichHistoryStorage {
|
||||
throw error;
|
||||
}
|
||||
|
||||
const { queriesToKeep, limitExceeded } = checkLimits(currentRichHistoryDTOs);
|
||||
let { queriesToKeep, limitExceeded } = cleanUpUnstarredQuery(currentRichHistoryDTOs, MAX_HISTORY_ITEMS);
|
||||
|
||||
const updatedHistory: RichHistoryLocalStorageDTO[] = [newRichHistoryQueryDTO, ...queriesToKeep];
|
||||
let updatedHistory: RichHistoryLocalStorageDTO[] = [newRichHistoryQueryDTO, ...queriesToKeep];
|
||||
|
||||
try {
|
||||
store.setObject(RICH_HISTORY_KEY, updatedHistory);
|
||||
} catch (error) {
|
||||
if (error instanceof Error && error.name === 'QuotaExceededError') {
|
||||
throwError(RichHistoryServiceError.StorageFull, `Saving rich history failed: ${error.message}`);
|
||||
} else {
|
||||
throw error;
|
||||
let saveRetriesLeft = 3;
|
||||
let saved = false;
|
||||
|
||||
while (!saved && saveRetriesLeft >= 0) {
|
||||
try {
|
||||
store.setObject(RICH_HISTORY_KEY, updatedHistory);
|
||||
saved = true;
|
||||
} catch (error) {
|
||||
await this.trackLocalStorageUsage('Failed to save rich history to local storage', {
|
||||
saveRetriesLeft: saveRetriesLeft.toString(),
|
||||
quotaExceededError: error instanceof Error && error.name === 'QuotaExceededError' ? 'true' : 'false',
|
||||
errorMessage: error instanceof Error ? error?.message : 'unknown',
|
||||
});
|
||||
|
||||
if (saveRetriesLeft >= 1) {
|
||||
saveRetriesLeft--;
|
||||
const { queriesToKeep: newQueriesToKeep } = cleanUpUnstarredQuery(queriesToKeep, queriesToKeep.length - 1);
|
||||
updatedHistory = [newRichHistoryQueryDTO, ...newQueriesToKeep];
|
||||
queriesToKeep = newQueriesToKeep;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (error instanceof Error && error.name === 'QuotaExceededError') {
|
||||
throwError(RichHistoryServiceError.StorageFull, `Saving rich history failed: ${error.message}`);
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (limitExceeded) {
|
||||
await this.trackLocalStorageUsage('Rich history query limit exceeded.');
|
||||
|
||||
return {
|
||||
warning: {
|
||||
type: RichHistoryStorageWarning.LimitExceeded,
|
||||
@@ -148,6 +179,33 @@ export default class RichHistoryLocalStorage implements RichHistoryStorage {
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
private async trackLocalStorageUsage(message: string, additionalInfo?: Record<string, string>) {
|
||||
const allQueriesCount =
|
||||
(
|
||||
await this.getRichHistory({
|
||||
search: '',
|
||||
sortOrder: SortOrder.Ascending,
|
||||
datasourceFilters: [],
|
||||
starred: false,
|
||||
})
|
||||
).total || -1;
|
||||
|
||||
const allQueriesSizeInBytes = RichHistoryLocalStorage.getLocalStorageUsageInBytes();
|
||||
|
||||
const totalLocalStorageSize = calculateTotalLocalStorageSize();
|
||||
|
||||
const localStats = {
|
||||
totalLocalStorageSize: totalLocalStorageSize?.toString(),
|
||||
allQueriesSizeInBytes: allQueriesSizeInBytes?.toString(),
|
||||
allQueriesCount: allQueriesCount?.toString(),
|
||||
};
|
||||
|
||||
logger.logWarning(message, {
|
||||
...localStats,
|
||||
...additionalInfo,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function updateRichHistory(
|
||||
@@ -185,17 +243,20 @@ function cleanUp(richHistory: RichHistoryLocalStorageDTO[]): RichHistoryLocalSto
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the entry can be added. Throws an error if current limit has been hit.
|
||||
* Ensures the entry can be added.
|
||||
* Returns queries that should be saved back giving space for one extra query.
|
||||
*/
|
||||
export function checkLimits(queriesToKeep: RichHistoryLocalStorageDTO[]): {
|
||||
export function cleanUpUnstarredQuery(
|
||||
queriesToKeep: RichHistoryLocalStorageDTO[],
|
||||
max: number
|
||||
): {
|
||||
queriesToKeep: RichHistoryLocalStorageDTO[];
|
||||
limitExceeded: boolean;
|
||||
} {
|
||||
// remove oldest non-starred items to give space for the recent query
|
||||
let limitExceeded = false;
|
||||
let current = queriesToKeep.length - 1;
|
||||
while (current >= 0 && queriesToKeep.length >= MAX_HISTORY_ITEMS) {
|
||||
while (current >= 0 && queriesToKeep.length >= max) {
|
||||
if (!queriesToKeep[current].starred) {
|
||||
queriesToKeep.splice(current, 1);
|
||||
limitExceeded = true;
|
||||
@@ -247,3 +308,26 @@ function throwError(name: string, message: string) {
|
||||
error.name = name;
|
||||
throw error;
|
||||
}
|
||||
|
||||
function calculateTotalLocalStorageSize() {
|
||||
try {
|
||||
let total = 0;
|
||||
|
||||
// eslint-disable-next-line
|
||||
const ls = window.localStorage;
|
||||
|
||||
for (let i = 0; i < ls.length; i++) {
|
||||
const key = ls.key(i);
|
||||
if (key) {
|
||||
const value = ls.getItem(key);
|
||||
if (value) {
|
||||
total += key.length + value.length;
|
||||
}
|
||||
}
|
||||
}
|
||||
// each character is 2 bytes
|
||||
return total * 2;
|
||||
} catch (e) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ export type RichHistorySearchFilters = {
|
||||
// so the resulting timerange from this will be [now - from, now - to].
|
||||
from?: number;
|
||||
to?: number;
|
||||
// true if only starred entries should be returned, false if ALL entries should be returned,
|
||||
starred: boolean;
|
||||
page?: number;
|
||||
};
|
||||
|
||||
@@ -200,7 +200,7 @@ describe('Explore: Query History', () => {
|
||||
await waitForExplore();
|
||||
await openQueryHistory();
|
||||
|
||||
jest.spyOn(localStorage, 'checkLimits').mockImplementationOnce((queries) => {
|
||||
jest.spyOn(localStorage, 'cleanUpUnstarredQuery').mockImplementationOnce((queries) => {
|
||||
return { queriesToKeep: queries, limitExceeded: true };
|
||||
});
|
||||
|
||||
|
||||
@@ -2,8 +2,20 @@ import { css } from '@emotion/css';
|
||||
import { useId, useState } from 'react';
|
||||
|
||||
import { createTheme, GrafanaTheme2, NewThemeOptions } from '@grafana/data';
|
||||
import { experimentalThemeDefinitions, NewThemeOptionsSchema } from '@grafana/data/internal';
|
||||
import { themeJsonSchema } from '@grafana/data/unstable';
|
||||
import { NewThemeOptionsSchema } from '@grafana/data/internal';
|
||||
import aubergine from '@grafana/data/themes/definitions/aubergine.json';
|
||||
import debug from '@grafana/data/themes/definitions/debug.json';
|
||||
import desertbloom from '@grafana/data/themes/definitions/desertbloom.json';
|
||||
import gildedgrove from '@grafana/data/themes/definitions/gildedgrove.json';
|
||||
import gloom from '@grafana/data/themes/definitions/gloom.json';
|
||||
import mars from '@grafana/data/themes/definitions/mars.json';
|
||||
import matrix from '@grafana/data/themes/definitions/matrix.json';
|
||||
import sapphiredusk from '@grafana/data/themes/definitions/sapphiredusk.json';
|
||||
import synthwave from '@grafana/data/themes/definitions/synthwave.json';
|
||||
import tron from '@grafana/data/themes/definitions/tron.json';
|
||||
import victorian from '@grafana/data/themes/definitions/victorian.json';
|
||||
import zen from '@grafana/data/themes/definitions/zen.json';
|
||||
import themeJsonSchema from '@grafana/data/themes/schema.generated.json';
|
||||
import { t } from '@grafana/i18n';
|
||||
import { useChromeHeaderHeight } from '@grafana/runtime';
|
||||
import { CodeEditor, Combobox, Field, Stack, useStyles2 } from '@grafana/ui';
|
||||
@@ -34,8 +46,23 @@ const themeMap: Record<string, NewThemeOptions> = {
|
||||
},
|
||||
};
|
||||
|
||||
const experimentalDefinitions: Record<string, unknown> = {
|
||||
aubergine,
|
||||
debug,
|
||||
desertbloom,
|
||||
gildedgrove,
|
||||
gloom,
|
||||
mars,
|
||||
matrix,
|
||||
sapphiredusk,
|
||||
synthwave,
|
||||
tron,
|
||||
victorian,
|
||||
zen,
|
||||
};
|
||||
|
||||
// Add additional themes
|
||||
for (const [name, json] of Object.entries(experimentalThemeDefinitions)) {
|
||||
for (const [name, json] of Object.entries(experimentalDefinitions)) {
|
||||
const result = NewThemeOptionsSchema.safeParse(json);
|
||||
if (!result.success) {
|
||||
console.error(`Invalid theme definition for theme ${name}: ${result.error.message}`);
|
||||
|
||||
@@ -11,6 +11,7 @@ failed_checks=()
|
||||
for file in "$ARTIFACTS_DIR"/*.tgz; do
|
||||
echo "🔍 Checking NPM package: $file"
|
||||
|
||||
# If you need to debug ATTW issues, pass "--format json" to get verbose output.
|
||||
if ! NODE_OPTIONS="-C @grafana-app/source" yarn attw "$file" --ignore-rules "false-cjs" --profile "node16"; then
|
||||
echo "attw check failed for $file"
|
||||
echo ""
|
||||
|
||||
Reference in New Issue
Block a user