Skip to main content

tests_integration/
otlp.rs

1// Copyright 2023 Greptime Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#[cfg(test)]
16mod test {
17    use std::sync::Arc;
18
19    use client::{DEFAULT_CATALOG_NAME, OutputData};
20    use common_recordbatch::RecordBatches;
21    use frontend::instance::Instance;
22    use otel_arrow_rust::proto::opentelemetry::collector::metrics::v1::ExportMetricsServiceRequest;
23    use otel_arrow_rust::proto::opentelemetry::common::v1::any_value::Value as Val;
24    use otel_arrow_rust::proto::opentelemetry::common::v1::{
25        AnyValue, InstrumentationScope, KeyValue,
26    };
27    use otel_arrow_rust::proto::opentelemetry::metrics::v1::number_data_point::Value;
28    use otel_arrow_rust::proto::opentelemetry::metrics::v1::{
29        Gauge, Histogram, HistogramDataPoint, Metric, NumberDataPoint, ResourceMetrics,
30        ScopeMetrics, metric,
31    };
32    use otel_arrow_rust::proto::opentelemetry::resource::v1::Resource;
33    use servers::query_handler::OpenTelemetryProtocolHandler;
34    use servers::query_handler::sql::SqlQueryHandler;
35    use session::context::QueryContext;
36
37    use crate::standalone::GreptimeDbStandaloneBuilder;
38    use crate::tests;
39
40    #[tokio::test(flavor = "multi_thread")]
41    pub async fn test_otlp_on_standalone() {
42        let standalone = GreptimeDbStandaloneBuilder::new("test_standalone_otlp")
43            .build()
44            .await;
45        let instance = standalone.fe_instance();
46
47        test_otlp(instance).await;
48    }
49
50    #[tokio::test(flavor = "multi_thread")]
51    pub async fn test_otlp_on_distributed() {
52        let instance = tests::create_distributed_instance("test_standalone_otlp").await;
53
54        test_otlp(&instance.frontend()).await;
55    }
56
57    async fn test_otlp(instance: &Arc<Instance>) {
58        let req = build_request();
59        let db = "otlp";
60        let ctx = Arc::new(QueryContext::with(DEFAULT_CATALOG_NAME, db));
61
62        assert!(
63            SqlQueryHandler::do_query(
64                instance.as_ref(),
65                &format!("CREATE DATABASE IF NOT EXISTS {db}"),
66                ctx.clone(),
67            )
68            .await
69            .first()
70            .unwrap()
71            .is_ok()
72        );
73
74        let resp = instance.metrics(req, ctx.clone()).await;
75        assert!(resp.is_ok());
76
77        let mut output = instance
78            .do_query(
79                "SELECT * FROM my_test_metric_my_ignored_unit ORDER BY greptime_timestamp",
80                ctx.clone(),
81            )
82            .await;
83        let output = output.remove(0).unwrap();
84        let OutputData::Stream(stream) = output.data else {
85            unreachable!()
86        };
87        let recordbatches = RecordBatches::try_collect(stream).await.unwrap();
88        assert_eq!(
89            recordbatches.pretty_print().unwrap(),
90            "\
91+----------------+---------------------+----------------+
92| container_name | greptime_timestamp  | greptime_value |
93+----------------+---------------------+----------------+
94| testserver     | 1970-01-01T00:00:00 | 105.0          |
95| testsevrer     | 1970-01-01T00:00:00 | 100.0          |
96+----------------+---------------------+----------------+",
97        );
98
99        let mut output = instance
100            .do_query(
101                "SELECT le, greptime_value FROM my_test_histo_my_ignored_unit_bucket order by le",
102                ctx.clone(),
103            )
104            .await;
105        let output = output.remove(0).unwrap();
106        let OutputData::Stream(stream) = output.data else {
107            unreachable!()
108        };
109        let recordbatches = RecordBatches::try_collect(stream).await.unwrap();
110        assert_eq!(
111            recordbatches.pretty_print().unwrap(),
112            "\
113+-----+----------------+
114| le  | greptime_value |
115+-----+----------------+
116| 1   | 1.0            |
117| 5   | 3.0            |
118| inf | 4.0            |
119+-----+----------------+",
120        );
121
122        let mut output = instance
123            .do_query(
124                "SELECT * FROM my_test_histo_my_ignored_unit_sum",
125                ctx.clone(),
126            )
127            .await;
128        let output = output.remove(0).unwrap();
129        let OutputData::Stream(stream) = output.data else {
130            unreachable!()
131        };
132        let recordbatches = RecordBatches::try_collect(stream).await.unwrap();
133        assert_eq!(
134            recordbatches.pretty_print().unwrap(),
135            "\
136+------------+---------------------+----------------+
137| host       | greptime_timestamp  | greptime_value |
138+------------+---------------------+----------------+
139| testserver | 1970-01-01T00:00:00 | 51.0           |
140+------------+---------------------+----------------+",
141        );
142
143        let mut output = instance
144            .do_query(
145                "SELECT * FROM my_test_histo_my_ignored_unit_count",
146                ctx.clone(),
147            )
148            .await;
149        let output = output.remove(0).unwrap();
150        let OutputData::Stream(stream) = output.data else {
151            unreachable!()
152        };
153        let recordbatches = RecordBatches::try_collect(stream).await.unwrap();
154        assert_eq!(
155            recordbatches.pretty_print().unwrap(),
156            "\
157+------------+---------------------+----------------+
158| host       | greptime_timestamp  | greptime_value |
159+------------+---------------------+----------------+
160| testserver | 1970-01-01T00:00:00 | 4.0            |
161+------------+---------------------+----------------+",
162        );
163    }
164
165    fn build_request() -> ExportMetricsServiceRequest {
166        let data_points = vec![
167            NumberDataPoint {
168                attributes: vec![keyvalue("container.name", "testsevrer")],
169                time_unix_nano: 100,
170                value: Some(Value::AsInt(100)),
171                ..Default::default()
172            },
173            NumberDataPoint {
174                attributes: vec![keyvalue("container.name", "testserver")],
175                time_unix_nano: 105,
176                value: Some(Value::AsInt(105)),
177                ..Default::default()
178            },
179        ];
180        let gauge = Gauge { data_points };
181
182        let histo_data_points = vec![HistogramDataPoint {
183            attributes: vec![keyvalue("host", "testserver")],
184            time_unix_nano: 100,
185            count: 4,
186            bucket_counts: vec![1, 2, 1],
187            explicit_bounds: vec![1.0f64, 5.0f64],
188            sum: Some(51f64),
189            ..Default::default()
190        }];
191
192        let histo = Histogram {
193            data_points: histo_data_points,
194            aggregation_temporality: 0,
195        };
196
197        ExportMetricsServiceRequest {
198            resource_metrics: vec![ResourceMetrics {
199                scope_metrics: vec![ScopeMetrics {
200                    metrics: vec![
201                        Metric {
202                            name: "my.test.metric".into(),
203                            description: "my ignored desc".into(),
204                            unit: "my ignored unit".into(),
205                            metadata: vec![],
206                            data: Some(metric::Data::Gauge(gauge)),
207                        },
208                        Metric {
209                            name: "my.test.histo".into(),
210                            description: "my ignored desc".into(),
211                            unit: "my ignored unit".into(),
212                            metadata: vec![],
213                            data: Some(metric::Data::Histogram(histo)),
214                        },
215                    ],
216                    scope: Some(InstrumentationScope {
217                        attributes: vec![
218                            keyvalue("scope", "otel"),
219                            keyvalue("telemetry.sdk.name", "java"),
220                        ],
221                        ..Default::default()
222                    }),
223                    ..Default::default()
224                }],
225                resource: Some(Resource {
226                    attributes: vec![keyvalue("resource", "greptimedb")],
227                    dropped_attributes_count: 0,
228                    entity_refs: vec![],
229                }),
230                ..Default::default()
231            }],
232        }
233    }
234
235    fn keyvalue(key: &str, value: &str) -> KeyValue {
236        KeyValue {
237            key: key.into(),
238            value: Some(AnyValue {
239                value: Some(Val::StringValue(value.into())),
240            }),
241        }
242    }
243}