From 31cb78c46787fdbc6cff69deb13d4f88f2fb10e9 Mon Sep 17 00:00:00 2001 From: TzeYiing Date: Thu, 21 Sep 2023 22:36:26 +0800 Subject: [PATCH 1/6] feat: ingestion specs for openapi --- .../controllers/log_controller.ex | 23 +++++++++++++++++++ lib/logflare_web/open_api.ex | 7 ++++++ lib/logflare_web/open_api_schemas.ex | 6 +++++ 3 files changed, 36 insertions(+) diff --git a/lib/logflare_web/controllers/log_controller.ex b/lib/logflare_web/controllers/log_controller.ex index 5b53bc17c..0f88db58a 100644 --- a/lib/logflare_web/controllers/log_controller.ex +++ b/lib/logflare_web/controllers/log_controller.ex @@ -1,9 +1,19 @@ defmodule LogflareWeb.LogController do use LogflareWeb, :controller + use OpenApiSpex.ControllerSpecs alias Logflare.Logs.IngestTypecasting alias Logflare.Backends + alias LogflareWeb.OpenApi.Accepted + alias LogflareWeb.OpenApi.Created + alias LogflareWeb.OpenApi.ServerError + alias LogflareWeb.OpenApiSchemas.LogsCreated + + action_fallback(LogflareWeb.Api.FallbackController) + + tags(["Ingestion"]) + plug( CORSPlug, [ @@ -25,6 +35,19 @@ defmodule LogflareWeb.LogController do @message "Logged!" + operation(:create, + summary: "Create log event", + description: "Full details are available in the [ingestion documentation](https://docs.logflare.app/concepts/ingestion/)", + parameters: [ + source: [in: :query, description: "Source UUID", type: :string, example: "a040ae88-3e27-448b-9ee6-622278b23193", required: false], + source_name: [in: :query, description: "Source name", type: :string, example: "MyApp.MySource", required: false] + ], + responses: %{ + 201 => Created.response(LogsCreated), + 500 => ServerError.response() + } + ) + def create(%{assigns: %{source: source}} = conn, %{"batch" => batch}) when is_list(batch) do ingest_and_render(conn, batch, source) end diff --git a/lib/logflare_web/open_api.ex b/lib/logflare_web/open_api.ex index 26be23648..82ee4c997 100644 --- a/lib/logflare_web/open_api.ex +++ b/lib/logflare_web/open_api.ex @@ -52,4 +52,11 @@ defmodule LogflareWeb.OpenApi do def response(), do: {"Not found", "text/plain", __MODULE__} end + + defmodule ServerError do + require OpenApiSpex + OpenApiSpex.schema(%{}) + + def response(), do: {"Server error", "text/plain", __MODULE__} + end end diff --git a/lib/logflare_web/open_api_schemas.ex b/lib/logflare_web/open_api_schemas.ex index e8df44576..451b6f719 100644 --- a/lib/logflare_web/open_api_schemas.ex +++ b/lib/logflare_web/open_api_schemas.ex @@ -1,6 +1,12 @@ defmodule LogflareWeb.OpenApiSchemas do alias OpenApiSpex.Schema + defmodule LogsCreated do + @properties %{ + message: %Schema{type: :string, example: "Logged!"}, + } + use LogflareWeb.OpenApi, properties: @properties, required: [] + end defmodule Endpoint do @properties %{ token: %Schema{type: :string}, From 80103befb990ca9d142114bc57e30326e07b6f5a Mon Sep 17 00:00:00 2001 From: TzeYiing Date: Thu, 21 Sep 2023 22:58:12 +0800 Subject: [PATCH 2/6] feat: only permit /api/* paths --- lib/logflare_web/api_spec.ex | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/logflare_web/api_spec.ex b/lib/logflare_web/api_spec.ex index 2bab3bac8..8021f332f 100644 --- a/lib/logflare_web/api_spec.ex +++ b/lib/logflare_web/api_spec.ex @@ -19,7 +19,7 @@ defmodule LogflareWeb.ApiSpec do title: to_string(Application.spec(:logflare, :description)), version: to_string(Application.spec(:logflare, :vsn)) }, - paths: Paths.from_router(Router), + paths: Paths.from_router(Router) |> filter_routes(), components: %Components{ securitySchemes: %{ "authorization" => %SecurityScheme{type: "http", scheme: "bearer", bearerFormat: "JWT"} @@ -27,4 +27,10 @@ defmodule LogflareWeb.ApiSpec do } }) end + + defp filter_routes(routes_map) do + for {"/api" <> _path = k, v} <- routes_map, into: %{} do + {k, v} + end + end end From 24ab499d6eec24d9d089721b72b0eb53b662581a Mon Sep 17 00:00:00 2001 From: TzeYiing Date: Thu, 21 Sep 2023 22:58:23 +0800 Subject: [PATCH 3/6] feat: add endpoints query controller to OpenAPI --- .../controllers/endpoints_controller.ex | 26 +++++++++++++++++++ .../controllers/log_controller.ex | 21 ++++++++++++--- lib/logflare_web/open_api_schemas.ex | 17 +++++++++++- 3 files changed, 59 insertions(+), 5 deletions(-) diff --git a/lib/logflare_web/controllers/endpoints_controller.ex b/lib/logflare_web/controllers/endpoints_controller.ex index d90e83d4d..180a8228b 100644 --- a/lib/logflare_web/controllers/endpoints_controller.ex +++ b/lib/logflare_web/controllers/endpoints_controller.ex @@ -1,9 +1,16 @@ defmodule LogflareWeb.EndpointsController do use LogflareWeb, :controller + use OpenApiSpex.ControllerSpecs + require Logger alias Logflare.Endpoints + alias LogflareWeb.OpenApi.Accepted + alias LogflareWeb.OpenApi.ServerError + alias LogflareWeb.OpenApiSchemas.EndpointQuery + action_fallback(LogflareWeb.Api.FallbackController) + tags(["Public"]) plug CORSPlug, origin: "*", @@ -18,6 +25,25 @@ defmodule LogflareWeb.EndpointsController do methods: ["GET", "POST", "OPTIONS"], send_preflight_response?: true + operation(:query, + summary: "Query a Logflare Endpoint", + description: + "Full details are available in the [Logflare Endpoints documentation](https://docs.logflare.app/concepts/endpoints/)", + parameters: [ + token_or_name: [ + in: :path, + description: "Endpoint UUID or name", + type: :string, + example: "a040ae88-3e27-448b-9ee6-622278b23193", + required: true + ] + ], + responses: %{ + 200 => EndpointQuery.response(), + 500 => ServerError.response() + } + ) + def query(%{assigns: %{endpoint: endpoint}} = conn, _params) do endpoint_query = Endpoints.map_query_sources(endpoint) diff --git a/lib/logflare_web/controllers/log_controller.ex b/lib/logflare_web/controllers/log_controller.ex index 0f88db58a..f6d857a9d 100644 --- a/lib/logflare_web/controllers/log_controller.ex +++ b/lib/logflare_web/controllers/log_controller.ex @@ -12,7 +12,7 @@ defmodule LogflareWeb.LogController do action_fallback(LogflareWeb.Api.FallbackController) - tags(["Ingestion"]) + tags(["Public"]) plug( CORSPlug, @@ -37,11 +37,24 @@ defmodule LogflareWeb.LogController do operation(:create, summary: "Create log event", - description: "Full details are available in the [ingestion documentation](https://docs.logflare.app/concepts/ingestion/)", + description: + "Full details are available in the [ingestion documentation](https://docs.logflare.app/concepts/ingestion/)", parameters: [ - source: [in: :query, description: "Source UUID", type: :string, example: "a040ae88-3e27-448b-9ee6-622278b23193", required: false], - source_name: [in: :query, description: "Source name", type: :string, example: "MyApp.MySource", required: false] + source: [ + in: :query, + description: "Source UUID", + type: :string, + example: "a040ae88-3e27-448b-9ee6-622278b23193", + required: false ], + source_name: [ + in: :query, + description: "Source name", + type: :string, + example: "MyApp.MySource", + required: false + ] + ], responses: %{ 201 => Created.response(LogsCreated), 500 => ServerError.response() diff --git a/lib/logflare_web/open_api_schemas.ex b/lib/logflare_web/open_api_schemas.ex index 451b6f719..22152bbcd 100644 --- a/lib/logflare_web/open_api_schemas.ex +++ b/lib/logflare_web/open_api_schemas.ex @@ -1,12 +1,27 @@ defmodule LogflareWeb.OpenApiSchemas do alias OpenApiSpex.Schema + defmodule EndpointQuery do + @properties %{ + result: %Schema{type: :string, example: "Logged!"}, + errors: %Schema{ + required: false, + oneOf: [ + %Schema{type: :object}, + %Schema{type: :string} + ] + } + } + use LogflareWeb.OpenApi, properties: @properties, required: [] + end + defmodule LogsCreated do @properties %{ - message: %Schema{type: :string, example: "Logged!"}, + message: %Schema{type: :string, example: "Logged!"} } use LogflareWeb.OpenApi, properties: @properties, required: [] end + defmodule Endpoint do @properties %{ token: %Schema{type: :string}, From 7b83731d08619e3a0df4b894525fa1b8e88abefb Mon Sep 17 00:00:00 2001 From: TzeYiing Date: Thu, 21 Sep 2023 22:58:38 +0800 Subject: [PATCH 4/6] chore: remove compilation warnings --- lib/logflare_web/controllers/endpoints_controller.ex | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/logflare_web/controllers/endpoints_controller.ex b/lib/logflare_web/controllers/endpoints_controller.ex index 180a8228b..6811b91f3 100644 --- a/lib/logflare_web/controllers/endpoints_controller.ex +++ b/lib/logflare_web/controllers/endpoints_controller.ex @@ -5,7 +5,6 @@ defmodule LogflareWeb.EndpointsController do require Logger alias Logflare.Endpoints - alias LogflareWeb.OpenApi.Accepted alias LogflareWeb.OpenApi.ServerError alias LogflareWeb.OpenApiSchemas.EndpointQuery From b8c5c42664ed13589d8540d8c0ff5ca46f06a55f Mon Sep 17 00:00:00 2001 From: TzeYiing Date: Thu, 21 Sep 2023 22:58:51 +0800 Subject: [PATCH 5/6] chore: more compilation warnings --- lib/logflare_web/controllers/log_controller.ex | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/logflare_web/controllers/log_controller.ex b/lib/logflare_web/controllers/log_controller.ex index f6d857a9d..5082c9d42 100644 --- a/lib/logflare_web/controllers/log_controller.ex +++ b/lib/logflare_web/controllers/log_controller.ex @@ -5,7 +5,6 @@ defmodule LogflareWeb.LogController do alias Logflare.Logs.IngestTypecasting alias Logflare.Backends - alias LogflareWeb.OpenApi.Accepted alias LogflareWeb.OpenApi.Created alias LogflareWeb.OpenApi.ServerError alias LogflareWeb.OpenApiSchemas.LogsCreated From 414de4d21ed8ebda070756eb513df80283647131 Mon Sep 17 00:00:00 2001 From: TzeYiing Date: Thu, 21 Sep 2023 23:06:16 +0800 Subject: [PATCH 6/6] docs: add in links to swagger docs --- docs/docs.logflare.com/docs/concepts/endpoints.md | 2 ++ docs/docs.logflare.com/docs/concepts/ingestion/index.mdx | 2 ++ 2 files changed, 4 insertions(+) diff --git a/docs/docs.logflare.com/docs/concepts/endpoints.md b/docs/docs.logflare.com/docs/concepts/endpoints.md index 4527b46e0..26a00fdb4 100644 --- a/docs/docs.logflare.com/docs/concepts/endpoints.md +++ b/docs/docs.logflare.com/docs/concepts/endpoints.md @@ -23,6 +23,8 @@ GET https://api.logflare.app/api/endpoints/query/my.custom.endpoint Querying by name requires authentication to be enabled and for a valid access token to be provided. +OpenAPI documentation for querying Logflare Endpoints can be found [here](https://logflare.app/swaggerui#/Public). + ## Crafting a Query Queries will be passed to the underlying backend to perform the querying. diff --git a/docs/docs.logflare.com/docs/concepts/ingestion/index.mdx b/docs/docs.logflare.com/docs/concepts/ingestion/index.mdx index d58738db0..4d78cf2c2 100644 --- a/docs/docs.logflare.com/docs/concepts/ingestion/index.mdx +++ b/docs/docs.logflare.com/docs/concepts/ingestion/index.mdx @@ -26,6 +26,8 @@ POST https://api.logflare.app/api/logs?source=9dd9a6f6-8e9b-4fa4-b682-4f2f5cd99d POST https://api.logflare.app/api/logs?source_name=my.logs.source ``` +OpenAPI documentation for ingestion can be found [here](https://logflare.app/swaggerui#/Public). + ### Batching Your Events You can ingest events individually, or via a batch.