@@ -10,7 +10,7 @@ use bytes::Bytes;
10
10
use chrono:: prelude:: * ;
11
11
use futures_util:: stream:: FuturesOrdered ;
12
12
use http:: Response ;
13
- use serde:: Deserialize ;
13
+ use serde:: { Deserialize , Serialize } ;
14
14
use thiserror:: Error ;
15
15
use tokio_stream:: StreamExt ;
16
16
use tracing:: { debug, info} ;
@@ -21,28 +21,42 @@ use grafana_plugin_sdk::{
21
21
prelude:: * ,
22
22
} ;
23
23
24
- #[ derive( Clone , Debug , Default ) ]
25
- struct MyPluginService ( Arc < AtomicUsize > ) ;
24
+ #[ derive( Clone , Debug ) ]
25
+ struct MyPluginService {
26
+ counter : Arc < AtomicUsize > ,
27
+ data_client : backend:: DataClient ,
28
+ }
26
29
27
30
impl MyPluginService {
28
31
fn new ( ) -> Self {
29
- Self ( Arc :: new ( AtomicUsize :: new ( 0 ) ) )
32
+ Self {
33
+ counter : Arc :: new ( AtomicUsize :: new ( 0 ) ) ,
34
+ data_client : backend:: DataClient :: new ( "localhost:10000" ) . expect ( "valid URL" ) ,
35
+ }
30
36
}
31
37
}
32
38
33
39
// Data service implementation.
34
40
35
- #[ derive( Debug , Deserialize ) ]
41
+ #[ derive( Clone , Debug , Deserialize , Serialize ) ]
36
42
#[ serde( rename_all = "camelCase" ) ]
37
43
struct Query {
38
44
pub expression : String ,
39
45
pub other_user_input : u64 ,
40
46
}
41
47
48
+ #[ derive( Debug , Error ) ]
49
+ enum SDKError {
50
+ #[ error( "SDK error: {0}" ) ]
51
+ Data ( data:: Error ) ,
52
+ #[ error( "Query data error: {0}" ) ]
53
+ QueryData ( backend:: QueryDataError ) ,
54
+ }
55
+
42
56
#[ derive( Debug , Error ) ]
43
57
#[ error( "Error querying backend for query {ref_id}: {source}" ) ]
44
58
struct QueryError {
45
- source : data :: Error ,
59
+ source : SDKError ,
46
60
ref_id : String ,
47
61
}
48
62
@@ -58,40 +72,60 @@ impl backend::DataService for MyPluginService {
58
72
type QueryError = QueryError ;
59
73
type Stream = backend:: BoxDataResponseStream < Self :: QueryError > ;
60
74
async fn query_data ( & self , request : backend:: QueryDataRequest < Self :: Query > ) -> Self :: Stream {
75
+ let client = self . data_client . clone ( ) ;
76
+ let transport_metadata = request. transport_metadata ( ) . clone ( ) ;
61
77
Box :: pin (
62
78
request
63
79
. queries
64
80
. into_iter ( )
65
- . map ( |x : DataQuery < Self :: Query > | async move {
81
+ . map ( |x : DataQuery < Self :: Query > | {
66
82
// We can see the user's query in `x.query`:
67
83
debug ! (
68
84
expression = x. query. expression,
69
85
other_user_input = x. query. other_user_input,
70
86
"Got backend query" ,
71
87
) ;
72
- // Here we create a single response Frame for each query.
73
- // Frames can be created from iterators of fields using [`IntoFrame`].
74
- Ok ( backend:: DataResponse :: new (
75
- x. ref_id . clone ( ) ,
76
- vec ! [ [
77
- // Fields can be created from iterators of a variety of
78
- // relevant datatypes.
79
- [
80
- Utc . ymd( 2021 , 1 , 1 ) . and_hms( 12 , 0 , 0 ) ,
81
- Utc . ymd( 2021 , 1 , 1 ) . and_hms( 12 , 0 , 1 ) ,
82
- Utc . ymd( 2021 , 1 , 1 ) . and_hms( 12 , 0 , 2 ) ,
88
+
89
+ let ref_id = x. ref_id . clone ( ) ;
90
+ let transport_metadata = transport_metadata. clone ( ) ;
91
+ let mut client = client. clone ( ) ;
92
+
93
+ async move {
94
+ // We can proxy this request to a different datasource if we like.
95
+ // Here we do that, but ignore the response.
96
+ let proxied = client
97
+ . query_data ( vec ! [ x. clone( ) ] , & transport_metadata)
98
+ . await
99
+ . map_err ( |source| QueryError {
100
+ source : SDKError :: QueryData ( source) ,
101
+ ref_id : ref_id. clone ( ) ,
102
+ } ) ?;
103
+ info ! ( "Got proxied response: {:?}" , proxied) ;
104
+
105
+ // Here we create a single response Frame for each query.
106
+ // Frames can be created from iterators of fields using [`IntoFrame`].
107
+ Ok ( backend:: DataResponse :: new (
108
+ ref_id. clone ( ) ,
109
+ vec ! [ [
110
+ // Fields can be created from iterators of a variety of
111
+ // relevant datatypes.
112
+ [
113
+ Utc . ymd( 2021 , 1 , 1 ) . and_hms( 12 , 0 , 0 ) ,
114
+ Utc . ymd( 2021 , 1 , 1 ) . and_hms( 12 , 0 , 1 ) ,
115
+ Utc . ymd( 2021 , 1 , 1 ) . and_hms( 12 , 0 , 2 ) ,
116
+ ]
117
+ . into_field( "time" ) ,
118
+ [ 1_u32 , 2 , 3 ] . into_field( "x" ) ,
119
+ [ "a" , "b" , "c" ] . into_field( "y" ) ,
83
120
]
84
- . into_field( "time" ) ,
85
- [ 1_u32 , 2 , 3 ] . into_field( "x" ) ,
86
- [ "a" , "b" , "c" ] . into_field( "y" ) ,
87
- ]
88
- . into_frame( "foo" )
89
- . check( )
90
- . map_err( |source| QueryError {
91
- ref_id: x. ref_id,
92
- source,
93
- } ) ?] ,
94
- ) )
121
+ . into_frame( "foo" )
122
+ . check( )
123
+ . map_err( |source| QueryError {
124
+ source: SDKError :: Data ( source) ,
125
+ ref_id,
126
+ } ) ?] ,
127
+ ) )
128
+ }
95
129
} )
96
130
. collect :: < FuturesOrdered < _ > > ( ) ,
97
131
)
@@ -195,7 +229,7 @@ impl backend::ResourceService for MyPluginService {
195
229
& self ,
196
230
r : backend:: CallResourceRequest ,
197
231
) -> Result < ( Self :: InitialResponse , Self :: Stream ) , Self :: Error > {
198
- let count = Arc :: clone ( & self . 0 ) ;
232
+ let count = Arc :: clone ( & self . counter ) ;
199
233
let response_and_stream = match r. request . uri ( ) . path ( ) {
200
234
// Just send back a single response.
201
235
"/echo" => Ok ( (
0 commit comments