InfluxDB client functions in Gleam - extremely basic, not recommended for use, but worth a look!
influx.gleam
120 lines 2.9 kB view raw
1import gleam/float 2import gleam/http 3import gleam/http/request.{type Request} 4import gleam/http/response.{Response} 5import gleam/httpc 6import gleam/int 7import gleam/list 8import gleam/option.{type Option} 9import gleam/result 10import gleam/string 11import gleam/time/timestamp 12 13pub type Client { 14 Client(url: String, token: String, bucket: String, org: String) 15} 16 17pub fn new(base_url url: String) -> Client { 18 Client(url:, token: "", bucket: "", org: "") 19} 20 21pub fn set_url(client: Client, url: String) -> Client { 22 Client(..client, url:) 23} 24 25pub fn set_token(client: Client, token: String) -> Client { 26 Client(..client, token:) 27} 28 29pub fn set_bucket(client: Client, bucket: String) -> Client { 30 Client(..client, bucket:) 31} 32 33pub fn set_org(client: Client, org: String) -> Client { 34 Client(..client, org:) 35} 36 37pub type LineField { 38 LineFloat(number: Float) 39 LineInt(number: Int) 40 LineUInt(number: Int) 41 LineString(text: String) 42 LineBool(boolean: Bool) 43} 44 45fn encode_line_field(field: LineField) -> String { 46 case field { 47 LineBool(b) -> 48 case b { 49 True -> "true" 50 False -> "false" 51 } 52 LineFloat(number) -> number |> float.to_string 53 LineInt(number) -> number |> int.to_string <> "i" 54 LineString(s) -> "\"" <> s <> "\"" 55 LineUInt(number) -> number |> int.to_string <> "u" 56 } 57} 58 59pub type Point { 60 Point( 61 measurement: String, 62 tags: List(#(String, String)), 63 fields: List(#(String, LineField)), 64 time: Option(timestamp.Timestamp), 65 ) 66} 67 68fn encode_points(points: List(Point)) -> String { 69 list.fold(points, "", fn(points_body, point) { 70 [ 71 points_body, 72 point.measurement, 73 ",", 74 point.tags 75 |> list.map(fn(tag) { tag.0 <> "=" <> tag.1 }) 76 |> string.join(","), 77 " ", 78 point.fields 79 |> list.map(fn(field) { field.0 <> "=" <> encode_line_field(field.1) }) 80 |> string.join(","), 81 " ", 82 option.unwrap(point.time, timestamp.system_time()) 83 |> timestamp.to_unix_seconds 84 |> float.multiply(1_000_000_000.0) 85 |> float.round 86 |> int.to_string, 87 "\n", 88 ] 89 |> string.join("") 90 }) 91} 92 93pub fn set_measurements(client: Client, points: List(Point)) -> Request(String) { 94 let assert Ok(req) = request.to(client.url <> "/api/v2") 95 96 req 97 |> request.set_body(encode_points(points)) 98 |> request.set_query([#("org", client.org), #("bucket", client.bucket)]) 99 |> request.set_header("Authorization", "Token " <> client.token) 100 |> request.set_path(req.path <> "/write") 101 |> request.set_method(http.Post) 102} 103 104pub fn append_measurements( 105 req: Request(String), 106 points: List(Point), 107) -> Request(String) { 108 req 109 |> request.set_body(req.body <> encode_points(points)) 110} 111 112pub fn send_request(req: Request(String)) -> response.Response(String) { 113 req 114 |> httpc.send 115 |> result.unwrap(Response( 116 status: 500, 117 headers: [], 118 body: "failed to produce a response", 119 )) 120}