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. 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 diff --git a/lib/logflare_web/controllers/endpoints_controller.ex b/lib/logflare_web/controllers/endpoints_controller.ex index d90e83d4d..6811b91f3 100644 --- a/lib/logflare_web/controllers/endpoints_controller.ex +++ b/lib/logflare_web/controllers/endpoints_controller.ex @@ -1,9 +1,15 @@ defmodule LogflareWeb.EndpointsController do use LogflareWeb, :controller + use OpenApiSpex.ControllerSpecs + require Logger alias Logflare.Endpoints + alias LogflareWeb.OpenApi.ServerError + alias LogflareWeb.OpenApiSchemas.EndpointQuery + action_fallback(LogflareWeb.Api.FallbackController) + tags(["Public"]) plug CORSPlug, origin: "*", @@ -18,6 +24,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 5b53bc17c..5082c9d42 100644 --- a/lib/logflare_web/controllers/log_controller.ex +++ b/lib/logflare_web/controllers/log_controller.ex @@ -1,9 +1,18 @@ defmodule LogflareWeb.LogController do use LogflareWeb, :controller + use OpenApiSpex.ControllerSpecs alias Logflare.Logs.IngestTypecasting alias Logflare.Backends + alias LogflareWeb.OpenApi.Created + alias LogflareWeb.OpenApi.ServerError + alias LogflareWeb.OpenApiSchemas.LogsCreated + + action_fallback(LogflareWeb.Api.FallbackController) + + tags(["Public"]) + plug( CORSPlug, [ @@ -25,6 +34,32 @@ 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..22152bbcd 100644 --- a/lib/logflare_web/open_api_schemas.ex +++ b/lib/logflare_web/open_api_schemas.ex @@ -1,6 +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!"} + } + use LogflareWeb.OpenApi, properties: @properties, required: [] + end + defmodule Endpoint do @properties %{ token: %Schema{type: :string},