Skip to content

Commit

Permalink
Add Timestamp field type + define Instants schema
Browse files Browse the repository at this point in the history
  • Loading branch information
arendjr committed Dec 1, 2023
1 parent 83fbd16 commit 13b77ca
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 35 deletions.
53 changes: 30 additions & 23 deletions fiberplane-pdk-macros/src/schema_field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ use crate::casing::Casing;

/// All the possible field types we can generate.
pub enum SchemaField {
Array(ArrayField),
Checkbox(CheckboxField),
DateTimeRange(DateTimeRangeField),
Integer(IntegerField),
Label(LabelField),
Select(SelectField),
Text(TextField),
Array(ArraySchema),
Timestamp(TimestampField),
}

/// A compile-time representation of an ArrayField schema,
Expand All @@ -28,7 +29,7 @@ pub enum SchemaField {
///
/// This is why all fields are only exposed to the crate,
/// and no public method is available either.
pub struct ArraySchema {
pub struct ArrayField {
pub(crate) name: String,
pub(crate) label: String,
pub(crate) element_struct_type_name: String,
Expand All @@ -40,16 +41,17 @@ impl SchemaField {
pub fn required(self) -> Self {
use SchemaField::*;
match self {
Array(schema) => Array(ArrayField {
minimum_length: 1,
..schema
}),
Checkbox(field) => Checkbox(field.required()),
DateTimeRange(field) => DateTimeRange(field.required()),
Integer(field) => Integer(field.required()),
Label(field) => Label(field.required()),
Select(field) => Select(field.required()),
Text(field) => Text(field.required()),
Array(schema) => Array(ArraySchema {
minimum_length: 1,
..schema
}),
Timestamp(field) => Timestamp(field.required()),
}
}

Expand All @@ -66,26 +68,28 @@ impl SchemaField {
use SchemaField::*;

let field_variant = match &self {
Array(_) => quote! { Array },
Checkbox(_) => quote! { Checkbox },
DateTimeRange(_) => quote! { DateTimeRange },
Integer(_) => quote! { Integer },
Label(_) => quote! { Label },
Select(_) => quote! { Select },
Text(_) => quote! { Text },
Array(_) => quote! { Array },
Timestamp(_) => quote! { Timestamp },
};
let enum_ident = Ident::new(field_enum, Span::call_site());
let field_ident = Ident::new(&format!("{field_variant}Field"), Span::call_site());

let name = serde_field_attrs.rename.unwrap_or_else(|| {
let name = match &self {
Array(field) => &field.name,
Checkbox(field) => &field.name,
DateTimeRange(field) => &field.name,
Integer(field) => &field.name,
Label(field) => &field.name,
Select(field) => &field.name,
Text(field) => &field.name,
Array(field) => &field.name,
Timestamp(field) => &field.name,
};
serde_struct_attrs.rename_all.format_string(name)
});
Expand All @@ -97,13 +101,14 @@ impl SchemaField {
};

let label = match &self {
Array(field) => &field.label,
Checkbox(field) => &field.label,
DateTimeRange(field) => &field.label,
Integer(field) => &field.label,
Label(field) => &field.label,
Select(field) => &field.label,
Text(field) => &field.label,
Array(field) => &field.label,
Timestamp(field) => &field.label,
};
let label = match label.is_empty() {
true => quote! {},
Expand All @@ -112,7 +117,7 @@ impl SchemaField {

let max = match &self {
Integer(IntegerField { max: Some(max), .. }) => quote! { .with_max(#max) },
Array(ArraySchema {
Array(ArrayField {
maximum_length: Some(maximum_length),
..
}) => quote! { .with_maximum_length(#maximum_length) },
Expand All @@ -121,7 +126,7 @@ impl SchemaField {

let min = match &self {
Integer(IntegerField { min: Some(min), .. }) => quote! { .with_min(#min) },
Array(ArraySchema { minimum_length, .. }) if *minimum_length != 0 => {
Array(ArrayField { minimum_length, .. }) if *minimum_length != 0 => {
quote! { .with_minimum_length(#minimum_length) }
}
_ => quote! {},
Expand Down Expand Up @@ -170,13 +175,14 @@ impl SchemaField {
};

let required = match &self {
Array(_) => false,
Checkbox(field) => field.required,
DateTimeRange(field) => field.required,
Integer(field) => field.required,
Label(field) => field.required,
Select(field) => field.required,
Text(field) => field.required,
Array(_) => false,
Timestamp(field) => field.required,
};
let required = match required {
true => quote! { .required() },
Expand Down Expand Up @@ -212,7 +218,7 @@ impl SchemaField {
};

let element_schema = match &self {
Array(ArraySchema {
Array(ArrayField {
element_struct_type_name,
..
}) => {
Expand Down Expand Up @@ -247,45 +253,46 @@ impl SchemaField {
pub fn with_label(self, label: &str) -> Self {
use SchemaField::*;
match self {
Array(field) => Array(ArrayField {
label: label.to_string(),
..field
}),
Checkbox(field) => Checkbox(field.with_label(label)),
DateTimeRange(field) => DateTimeRange(field.with_label(label)),
Integer(field) => Integer(field.with_label(label)),
Label(field) => Label(field.with_label(label)),
Select(field) => Select(field.with_label(label)),
Text(field) => Text(field.with_label(label)),
Array(field) => Array(ArraySchema {
label: label.to_string(),
..field
}),
Timestamp(field) => Timestamp(field.with_label(label)),
}
}

pub fn with_name(self, name: &str) -> Self {
use SchemaField::*;
match self {
Array(field) => Array(ArrayField {
name: name.to_string(),
..field
}),
Checkbox(field) => Checkbox(field.with_name(name)),
DateTimeRange(field) => DateTimeRange(field.with_name(name)),
Integer(field) => Integer(field.with_name(name)),
Label(field) => Label(field.with_name(name)),
Select(field) => Select(field.with_name(name)),
Text(field) => Text(field.with_name(name)),
Array(field) => Array(ArraySchema {
name: name.to_string(),
..field
}),
Timestamp(field) => Timestamp(field.with_name(name)),
}
}

pub fn with_placeholder(self, name: &str) -> Self {
use SchemaField::*;
match self {
Checkbox(_) => self,
Array(_) | Checkbox(_) | Timestamp(_) => self,
DateTimeRange(field) => DateTimeRange(field.with_placeholder(name)),
Integer(_) => self,
Label(field) => Label(field.with_placeholder(name)),
Select(field) => Select(field.with_placeholder(name)),
Text(field) => Text(field.with_placeholder(name)),
Array(_) => self,
}
}
}
Expand Down
5 changes: 3 additions & 2 deletions fiberplane-pdk-macros/src/schema_generator.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::schema_field::SchemaField;
use crate::{field_attrs::FieldAttrs, schema_field::ArraySchema};
use crate::{field_attrs::FieldAttrs, schema_field::ArrayField};
use fiberplane_models::providers::*;
use proc_macro::TokenStream;
use proc_macro_error::abort;
Expand Down Expand Up @@ -99,7 +99,8 @@ fn determine_field_type(field: &Field) -> SchemaField {
SchemaField::Text(field)
}
}
(struct_name, true) => SchemaField::Array(ArraySchema {
("Timestamp", false) => SchemaField::Timestamp(TimestampField::new()),
(struct_name, true) => SchemaField::Array(ArrayField {
element_struct_type_name: struct_name.to_string(),
name: name.clone(),
label: String::new(),
Expand Down
30 changes: 22 additions & 8 deletions providers/prometheus/src/instants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@ use grafana_common::{query_direct_and_proxied, Config};
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;

#[derive(Deserialize, QuerySchema)]
pub(crate) struct InstantsQuery {
#[pdk(label = "Enter your Prometheus query", supports_suggestions)]
query: String,

#[pdk(label = "Specify a time")]
time: Option<Timestamp>,
}

#[derive(Clone, Debug, Deserialize, ProviderData, Serialize)]
#[pdk(mime_type = INSTANTS_MIME_TYPE)]
pub struct Instants(pub Vec<Instant>);
Expand All @@ -20,14 +29,19 @@ pub struct Instant {
pub metric: Metric,
}

pub async fn query_instants(request: ProviderRequest) -> Result<Blob> {
let response: PrometheusResponse<Vec<InstantVector>> = query_direct_and_proxied(
&Config::parse(request.config)?,
"prometheus",
"api/v1/query",
Some(request.query_data),
)
.await?;
pub async fn query_instants(query: InstantsQuery, config: Config) -> Result<Blob> {
let body = Blob::from({
let mut form_data = form_urlencoded::Serializer::new(String::new());
form_data.append_pair("query", &query.query);
form_data.append_pair(
"time",
&query.time.unwrap_or_else(Timestamp::now_utc).to_string(),
);
form_data
});

let response: PrometheusResponse<Vec<InstantVector>> =
query_direct_and_proxied(&config, "prometheus", "api/v1/query", Some(body)).await?;

let instants = response
.data
Expand Down
4 changes: 2 additions & 2 deletions providers/prometheus/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use config::*;
use constants::{INSTANTS_MIME_TYPE, INSTANTS_QUERY_TYPE};
use fiberplane_pdk::prelude::*;
use grafana_common::{query_direct_and_proxied, Config};
use instants::query_instants;
use instants::{query_instants, InstantsQuery};
use serde_json::Value;
use std::env;
use timeseries::{create_graph_cell, query_series, TimeseriesQuery};
Expand All @@ -31,7 +31,7 @@ pdk_query_types! {
supported_mime_types: [YAML_MIME_TYPE]
},
INSTANTS_QUERY_TYPE => {
handler: query_instants(ProviderRequest).await,
handler: query_instants(InstantsQuery, Config).await,
supported_mime_types: [INSTANTS_MIME_TYPE]
},
TIMESERIES_QUERY_TYPE => {
Expand Down

0 comments on commit 13b77ca

Please sign in to comment.