@@ -2,19 +2,22 @@ package trino
22
33import (
44 "context"
5+ "encoding/json"
56 "fmt"
67 "strings"
78
89 "github.com/grafana/grafana-plugin-sdk-go/backend"
910 "github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
11+ "github.com/grafana/grafana-plugin-sdk-go/backend/log"
1012 "github.com/grafana/sqlds/v2"
1113 "github.com/trinodb/grafana-trino/pkg/trino/models"
1214)
1315
1416const (
15- accessTokenKey = "accessToken"
16- trinoUserHeader = "X-Trino-User"
17- bearerPrefix = "Bearer "
17+ accessTokenKey = "accessToken"
18+ trinoUserHeader = "X-Trino-User"
19+ trinoClientTagsKey = "X-Trino-Client-Tags"
20+ bearerPrefix = "Bearer "
1821)
1922
2023type SQLDatasourceWithTrinoUserContext struct {
@@ -36,13 +39,67 @@ func (ds *SQLDatasourceWithTrinoUserContext) QueryData(ctx context.Context, req
3639 if user == nil {
3740 return nil , fmt .Errorf ("user can't be nil if impersonation is enabled" )
3841 }
39-
4042 ctx = context .WithValue (ctx , trinoUserHeader , user )
4143 }
4244
45+ ctx = injectClientTags (ctx , req , settings )
46+
4347 return ds .SQLDatasource .QueryData (ctx , req )
4448}
4549
50+ func injectAccessToken (ctx context.Context , req * backend.QueryDataRequest ) context.Context {
51+ header := req .GetHTTPHeader (backend .OAuthIdentityTokenHeaderName )
52+
53+ if strings .HasPrefix (header , bearerPrefix ) {
54+ token := strings .TrimPrefix (header , bearerPrefix )
55+ return context .WithValue (ctx , accessTokenKey , token )
56+ }
57+
58+ return ctx
59+ }
60+
61+ func injectClientTags (ctx context.Context , req * backend.QueryDataRequest , settings models.TrinoDatasourceSettings ) context.Context {
62+ type queryClientTag struct {
63+ ClientTags string `json:"clientTags"`
64+ }
65+
66+ tagSet := make (map [string ]struct {})
67+
68+ for i := range req .Queries {
69+ var queryTags queryClientTag
70+ if err := json .Unmarshal (req .Queries [i ].JSON , & queryTags ); err != nil {
71+ log .DefaultLogger .Warn (
72+ "failed to unmarshal query client tags" ,
73+ "queryIndex" , i ,
74+ "error" , err ,
75+ )
76+ continue
77+ }
78+
79+ for _ , tag := range strings .Split (queryTags .ClientTags , "," ) {
80+ tag = strings .TrimSpace (tag )
81+ if tag != "" {
82+ tagSet [tag ] = struct {}{}
83+ }
84+ }
85+ }
86+
87+ if len (tagSet ) > 0 {
88+ tags := make ([]string , 0 , len (tagSet ))
89+ for tag := range tagSet {
90+ tags = append (tags , tag )
91+ }
92+
93+ return context .WithValue (ctx , trinoClientTagsKey , strings .Join (tags , "," ))
94+ }
95+
96+ if settings .ClientTags != "" {
97+ return context .WithValue (ctx , trinoClientTagsKey , settings .ClientTags )
98+ }
99+
100+ return ctx
101+ }
102+
46103func (ds * SQLDatasourceWithTrinoUserContext ) NewDatasource (settings backend.DataSourceInstanceSettings ) (instancemgmt.Instance , error ) {
47104 _ , err := ds .SQLDatasource .NewDatasource (settings )
48105 if err != nil {
@@ -55,14 +112,3 @@ func NewDatasource(c sqlds.Driver) *SQLDatasourceWithTrinoUserContext {
55112 base := sqlds .NewDatasource (c )
56113 return & SQLDatasourceWithTrinoUserContext {* base }
57114}
58-
59- func injectAccessToken (ctx context.Context , req * backend.QueryDataRequest ) context.Context {
60- header := req .GetHTTPHeader (backend .OAuthIdentityTokenHeaderName )
61-
62- if strings .HasPrefix (header , bearerPrefix ) {
63- token := strings .TrimPrefix (header , bearerPrefix )
64- return context .WithValue (ctx , accessTokenKey , token )
65- }
66-
67- return ctx
68- }
0 commit comments