initial health check

This commit is contained in:
Weves
2023-05-19 12:20:04 -07:00
committed by Chris Weaver
parent 16dd429826
commit 544ba8f50d
21 changed files with 131 additions and 32 deletions

View File

@@ -1,7 +1,8 @@
FROM python:3.11-slim-bullseye
RUN apt-get update \
&& apt-get install -y git cmake pkg-config libprotobuf-c-dev protobuf-compiler libprotobuf-dev libgoogle-perftools-dev libpq-dev build-essential \
&& apt-get install -y git cmake pkg-config libprotobuf-c-dev protobuf-compiler \
libprotobuf-dev libgoogle-perftools-dev libpq-dev build-essential curl \
&& rm -rf /var/lib/apt/lists/*
COPY ./requirements/default.txt /tmp/requirements.txt

View File

@@ -1,7 +1,8 @@
FROM python:3.11-slim-bullseye
RUN apt-get update \
&& apt-get install -y git cmake pkg-config libprotobuf-c-dev protobuf-compiler libprotobuf-dev libgoogle-perftools-dev libpq-dev build-essential cron \
&& apt-get install -y git cmake pkg-config libprotobuf-c-dev protobuf-compiler \
libprotobuf-dev libgoogle-perftools-dev libpq-dev build-essential cron curl \
&& rm -rf /var/lib/apt/lists/*
COPY ./requirements/default.txt /tmp/requirements.txt

View File

@@ -13,6 +13,7 @@ from danswer.configs.app_configs import WEB_DOMAIN
from danswer.datastores.qdrant.indexing import list_collections
from danswer.server.admin import router as admin_router
from danswer.server.event_loading import router as event_processing_router
from danswer.server.health import router as health_router
from danswer.server.search_backend import router as backend_router
from danswer.utils.logging import setup_logger
from fastapi import FastAPI
@@ -39,6 +40,7 @@ def get_application() -> FastAPI:
application.include_router(backend_router)
application.include_router(event_processing_router)
application.include_router(admin_router)
application.include_router(health_router)
application.include_router(
fastapi_users.get_auth_router(auth_backend),

View File

@@ -21,7 +21,9 @@ from danswer.dynamic_configs.interface import ConfigNotFoundError
from danswer.server.models import AuthStatus
from danswer.server.models import AuthUrl
from danswer.server.models import GDriveCallback
from danswer.server.models import IndexAttemptRequest
from danswer.server.models import IndexAttemptSnapshot
from danswer.server.models import ListIndexAttemptsResponse
from danswer.utils.logging import setup_logger
from fastapi import APIRouter
from fastapi import Depends
@@ -69,11 +71,6 @@ def modify_slack_config(
update_slack_config(slack_config)
class IndexAttemptRequest(BaseModel):
input_type: InputType = InputType.PULL
connector_specific_config: dict[str, Any]
@router.post("/connectors/{source}/index-attempt", status_code=201)
def index(
source: DocumentSource,
@@ -100,10 +97,6 @@ def index(
)
class ListIndexAttemptsResponse(BaseModel):
index_attempts: list[IndexAttemptSnapshot]
@router.get("/connectors/{source}/index-attempt")
def list_index_attempts(
source: DocumentSource,

View File

@@ -0,0 +1,10 @@
from danswer.server.models import HealthCheckResponse
from fastapi import APIRouter
router = APIRouter()
@router.get("/health")
def healthcheck() -> HealthCheckResponse:
return {"status": "ok"}

View File

@@ -1,12 +1,18 @@
from datetime import datetime
from typing import Any
from typing import Literal
from danswer.configs.constants import DocumentSource
from danswer.connectors.models import InputType
from danswer.datastores.interfaces import DatastoreFilter
from danswer.db.models import IndexingStatus
from pydantic import BaseModel
class HealthCheckResponse(BaseModel):
status: Literal["ok"]
class AuthStatus(BaseModel):
authenticated: bool
@@ -51,6 +57,11 @@ class UserByEmail(BaseModel):
user_email: str
class IndexAttemptRequest(BaseModel):
input_type: InputType = InputType.PULL
connector_specific_config: dict[str, Any]
class IndexAttemptSnapshot(BaseModel):
connector_specific_config: dict[str, Any]
status: IndexingStatus
@@ -60,5 +71,5 @@ class IndexAttemptSnapshot(BaseModel):
docs_indexed: int
class ListWebsiteIndexAttemptsResponse(BaseModel):
class ListIndexAttemptsResponse(BaseModel):
index_attempts: list[IndexAttemptSnapshot]

View File

@@ -35,7 +35,7 @@ services:
web_server:
build:
context: ../web
dockerfile: Dockerfile
dockerfile: Dockerfile.dev
depends_on:
- api_server
restart: always
@@ -43,7 +43,6 @@ services:
- .env
environment:
- INTERNAL_URL=http://api_server:8080
- NODE_ENV=development
ports:
- "3000:3000"
relational_db:
@@ -59,6 +58,8 @@ services:
vector_db:
image: qdrant/qdrant:v1.1.3
restart: always
ports:
- "6333:6333"
volumes:
- qdrant_volume:/qdrant/storage
volumes:

View File

@@ -33,7 +33,7 @@ services:
web_server:
build:
context: ../web
dockerfile: Dockerfile
dockerfile: Dockerfile.prod
depends_on:
- api_server
restart: always
@@ -41,7 +41,6 @@ services:
- .env
environment:
- INTERNAL_URL=http://api_server:8080
- NODE_ENV=production
relational_db:
image: postgres:15.2-alpine
restart: always

32
web/Dockerfile.dev Normal file
View File

@@ -0,0 +1,32 @@
FROM node:18-alpine
WORKDIR /app
# Install dependencies based on the preferred package manager
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./
RUN \
if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
elif [ -f package-lock.json ]; then npm ci; \
elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i; \
# Allow install without lockfile, so example works even without Node.js installed locally
else echo "Warning: Lockfile not found. It is recommended to commit lockfiles to version control." && yarn install; \
fi
COPY src ./src
COPY public ./public
COPY next.config.js .
COPY tsconfig.json .
# Next.js collects completely anonymous telemetry data about general usage. Learn more here: https://nextjs.org/telemetry
# Uncomment the following line to disable telemetry at run time
ENV NEXT_TELEMETRY_DISABLED 1
# Note: Don't expose ports here, Compose will handle that for us
# Start Next.js in development mode based on the preferred package manager
CMD \
if [ -f yarn.lock ]; then yarn dev; \
elif [ -f package-lock.json ]; then npm run dev; \
elif [ -f pnpm-lock.yaml ]; then pnpm dev; \
else yarn dev; \
fi

View File

@@ -4,10 +4,14 @@ import * as Yup from "yup";
import { IndexForm } from "@/components/admin/connectors/Form";
import { GithubIcon } from "@/components/icons/icons";
import { TextFormField } from "@/components/admin/connectors/Field";
import { HealthCheckBanner } from "@/components/health/healthcheck";
export default function Page() {
return (
<div className="mx-auto">
<div className="mb-4">
<HealthCheckBanner />
</div>
<div className="border-solid border-gray-600 border-b mb-4 pb-2 flex">
<GithubIcon size="32" />
<h1 className="text-3xl font-bold pl-2">Github PRs</h1>

View File

@@ -1,5 +1,5 @@
import { getDomain } from "@/lib/redirectSS";
import { buildUrl } from "@/lib/userSS";
import { buildUrl } from "@/lib/utilsSS";
import { NextRequest, NextResponse } from "next/server";
export const GET = async (request: NextRequest) => {

View File

@@ -16,6 +16,7 @@ import { LoadingAnimation } from "@/components/Loading";
import { useRouter } from "next/navigation";
import { Popup } from "@/components/admin/connectors/Popup";
import { useState } from "react";
import { HealthCheckBanner } from "@/components/health/healthcheck";
export default function Page() {
const router = useRouter();
@@ -43,9 +44,14 @@ export default function Page() {
} | null>(null);
const header = (
<div className="border-solid border-gray-600 border-b mb-4 pb-2 flex">
<GoogleDriveIcon size="32" />
<h1 className="text-3xl font-bold pl-2">Google Drive</h1>
<div>
<div className="mb-4">
<HealthCheckBanner />
</div>
<div className="border-solid border-gray-600 border-b mb-4 pb-2 flex">
<GoogleDriveIcon size="32" />
<h1 className="text-3xl font-bold pl-2">Google Drive</h1>
</div>
</div>
);

View File

@@ -7,6 +7,7 @@ import { SlackConfig } from "../../../../components/admin/connectors/types";
import { LoadingAnimation } from "@/components/Loading";
import { InitialSetupForm } from "./InitialSetupForm";
import { useRouter } from "next/navigation";
import { HealthCheckBanner } from "@/components/health/healthcheck";
const MainSection = () => {
// TODO: add back in once this is ready
@@ -29,9 +30,7 @@ const MainSection = () => {
</div>
);
} else if (error || !data) {
return (
<div className="mt-16">{`Error loading Slack config - ${error}`}</div>
);
return <div>{`Error loading Slack config - ${error}`}</div>;
}
return (
@@ -62,6 +61,9 @@ const MainSection = () => {
export default function Page() {
return (
<div className="mx-auto">
<div className="mb-4">
<HealthCheckBanner />
</div>
<div className="border-solid border-gray-600 border-b mb-4 pb-2 flex">
<SlackIcon size="32" />
<h1 className="text-3xl font-bold pl-2">Slack</h1>

View File

@@ -15,6 +15,7 @@ import {
import { IndexForm } from "@/components/admin/connectors/Form";
import { TextFormField } from "@/components/admin/connectors/Field";
import { useRouter } from "next/navigation";
import { HealthCheckBanner } from "@/components/health/healthcheck";
const COLUMNS = [
{ header: "Base URL", key: "url" },
@@ -54,6 +55,9 @@ export default function Web() {
return (
<div className="mx-auto">
<div className="mb-4">
<HealthCheckBanner />
</div>
<div className="border-solid border-gray-600 border-b pb-2 mb-4 flex">
<GlobeIcon size="32" />
<h1 className="text-3xl font-bold pl-2">Web</h1>

View File

@@ -16,6 +16,7 @@ import { CheckCircle, XCircle } from "@phosphor-icons/react";
import { submitIndexRequest } from "@/components/admin/connectors/Form";
import { useState } from "react";
import { Popup } from "@/components/admin/connectors/Popup";
import { HealthCheckBanner } from "@/components/health/healthcheck";
const getModifiedSource = (indexAttempt: IndexAttempt) => {
return indexAttempt.source === "web"
@@ -63,6 +64,9 @@ export default function Status() {
return (
<div className="mx-auto">
{popup && <Popup message={popup.message} type={popup.type} />}
<div className="mb-4">
<HealthCheckBanner />
</div>
<div className="border-solid border-gray-600 border-b pb-2 mb-4 flex">
<NotebookIcon size="32" />
<h1 className="text-3xl font-bold pl-2">Indexing Status</h1>

View File

@@ -1,5 +1,5 @@
import { getDomain } from "@/lib/redirectSS";
import { buildUrl } from "@/lib/userSS";
import { buildUrl } from "@/lib/utilsSS";
import { NextRequest, NextResponse } from "next/server";
export const GET = async (request: NextRequest) => {

View File

@@ -3,6 +3,7 @@ import { Header } from "@/components/Header";
import { getCurrentUserSS } from "@/lib/userSS";
import { redirect } from "next/navigation";
import { DISABLE_AUTH } from "@/lib/constants";
import { HealthCheckBanner } from "@/components/health/healthcheck";
export default async function Home() {
let user = null;
@@ -15,6 +16,9 @@ export default async function Home() {
return (
<>
<Header user={user} />
<div className="m-3">
<HealthCheckBanner />
</div>
<div className="px-24 pt-10 flex flex-col items-center min-h-screen bg-gray-900 text-gray-100">
<div className="max-w-[800px] w-full">
<SearchSection />

View File

@@ -0,0 +1,24 @@
"use client";
import { fetcher } from "@/lib/fetcher";
import useSWR from "swr";
export const HealthCheckBanner = () => {
const { error } = useSWR("/api/health", fetcher);
if (!error) {
return null;
}
return (
<div className="text-xs mx-auto bg-gradient-to-r from-red-900 to-red-700 p-2 rounded-sm border-hidden text-gray-300">
<p className="font-bold pb-1">The backend is currently unavailable.</p>
<p className="px-1">
If this is your initial setup or you just updated your Danswer
deployment, this is likely because the backend is still starting up.
Give it a minute or two, and then refresh the page. If that does not
work, make sure the backend is setup and/or contact an administrator.
</p>
</div>
);
};

View File

@@ -1,13 +1,6 @@
import { cookies } from "next/headers";
import { User } from "./types";
import { INTERNAL_URL } from "./constants";
export const buildUrl = (path: string) => {
if (path.startsWith("/")) {
return `${INTERNAL_URL}${path}`;
}
return `${INTERNAL_URL}/${path}`;
};
import { buildUrl } from "./utilsSS";
export const getGoogleOAuthUrlSS = async (): Promise<string> => {
const res = await fetch(buildUrl("/auth/google/authorize"));

8
web/src/lib/utilsSS.ts Normal file
View File

@@ -0,0 +1,8 @@
import { INTERNAL_URL } from "./constants";
export const buildUrl = (path: string) => {
if (path.startsWith("/")) {
return `${INTERNAL_URL}${path}`;
}
return `${INTERNAL_URL}/${path}`;
};